Merge mozilla-central to b2g-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 09 Jan 2015 15:54:18 +0100
changeset 248776 9c11b5f0a4c3f0c4ed0f3dff11f3112fce459dda
parent 248775 2234f393e850545eb0592c779e6dde67f6af47c2 (current diff)
parent 248743 7c03738e7a95a7d77f9cad311c02ea8d6d87e605 (diff)
child 248777 738f57e8242bc940f12da7ac5bcab475cd75889d
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to b2g-inbound
dom/indexedDB/test/test_disabled_quota_prompt.html
js/src/builtin/ParallelUtilities.js
js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSizedArrayType.js
js/src/tests/ecma_7/TypedObject/method_scatter.js
mfbt/MSIntTypes.h
testing/marionette/client/marionette/www/newTab.html
testing/web-platform/meta/media-source/mediasource-config-change-webm-v-bitrate.html.ini
testing/web-platform/meta/media-source/mediasource-config-change-webm-v-framerate.html.ini
--- a/accessible/base/ARIAMap.h
+++ b/accessible/base/ARIAMap.h
@@ -238,19 +238,19 @@ public:
     mContent(aContent), mAttrIdx(0)
   {
     mAttrCount = mContent->GetAttrCount();
   }
 
   bool Next(nsAString& aAttrName, nsAString& aAttrValue);
 
 private:
-  AttrIterator() MOZ_DELETE;
-  AttrIterator(const AttrIterator&) MOZ_DELETE;
-  AttrIterator& operator= (const AttrIterator&) MOZ_DELETE;
+  AttrIterator() = delete;
+  AttrIterator(const AttrIterator&) = delete;
+  AttrIterator& operator= (const AttrIterator&) = delete;
 
   nsIContent* mContent;
   uint32_t mAttrIdx;
   uint32_t mAttrCount;
 };
 
 } // namespace aria
 } // namespace a11y
--- a/accessible/base/AccGroupInfo.h
+++ b/accessible/base/AccGroupInfo.h
@@ -73,19 +73,19 @@ public:
    * Return next item of the same group to the given item.
    */
   static Accessible* NextItemTo(Accessible* aItem);
 
 protected:
   AccGroupInfo(Accessible* aItem, a11y::role aRole);
 
 private:
-  AccGroupInfo() MOZ_DELETE;
-  AccGroupInfo(const AccGroupInfo&) MOZ_DELETE;
-  AccGroupInfo& operator =(const AccGroupInfo&) MOZ_DELETE;
+  AccGroupInfo() = delete;
+  AccGroupInfo(const AccGroupInfo&) = delete;
+  AccGroupInfo& operator =(const AccGroupInfo&) = delete;
 
   static mozilla::a11y::role BaseRole(mozilla::a11y::role aRole)
   {
     if (aRole == mozilla::a11y::roles::CHECK_MENU_ITEM ||
         aRole == mozilla::a11y::roles::PARENT_MENUITEM ||
         aRole == mozilla::a11y::roles::RADIO_MENU_ITEM)
       return mozilla::a11y::roles::MENUITEM;
 
--- a/accessible/base/AccIterator.h
+++ b/accessible/base/AccIterator.h
@@ -276,19 +276,19 @@ class ItemIterator : public AccIterable
 public:
   explicit ItemIterator(Accessible* aItemContainer) :
     mContainer(aItemContainer), mAnchor(nullptr) { }
   virtual ~ItemIterator() { }
 
   virtual Accessible* Next();
 
 private:
-  ItemIterator() MOZ_DELETE;
-  ItemIterator(const ItemIterator&) MOZ_DELETE;
-  ItemIterator& operator = (const ItemIterator&) MOZ_DELETE;
+  ItemIterator() = delete;
+  ItemIterator(const ItemIterator&) = delete;
+  ItemIterator& operator = (const ItemIterator&) = delete;
 
   Accessible* mContainer;
   Accessible* mAnchor;
 };
 
 
 /**
  * Used to iterate through XUL tree items of the same level.
@@ -298,19 +298,19 @@ class XULTreeItemIterator : public AccIt
 public:
   XULTreeItemIterator(XULTreeAccessible* aXULTree, nsITreeView* aTreeView,
                       int32_t aRowIdx);
   virtual ~XULTreeItemIterator() { }
 
   virtual Accessible* Next();
 
 private:
-  XULTreeItemIterator() MOZ_DELETE;
-  XULTreeItemIterator(const XULTreeItemIterator&) MOZ_DELETE;
-  XULTreeItemIterator& operator = (const XULTreeItemIterator&) MOZ_DELETE;
+  XULTreeItemIterator() = delete;
+  XULTreeItemIterator(const XULTreeItemIterator&) = delete;
+  XULTreeItemIterator& operator = (const XULTreeItemIterator&) = delete;
 
   XULTreeAccessible* mXULTree;
   nsITreeView* mTreeView;
   int32_t mRowCount;
   int32_t mContainerLevel;
   int32_t mCurrRowIdx;
 };
 
--- a/accessible/base/EventQueue.h
+++ b/accessible/base/EventQueue.h
@@ -27,18 +27,18 @@ protected:
   bool PushEvent(AccEvent* aEvent);
 
   /**
    * Process events from the queue and fires events.
    */
   void ProcessEventQueue();
 
 private:
-  EventQueue(const EventQueue&) MOZ_DELETE;
-  EventQueue& operator = (const EventQueue&) MOZ_DELETE;
+  EventQueue(const EventQueue&) = delete;
+  EventQueue& operator = (const EventQueue&) = delete;
 
   // Event queue processing
   /**
    * Coalesce redundant events from the queue.
    */
   void CoalesceEvents();
 
   /**
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -204,40 +204,41 @@ NotificationController::WillRefresh(mozi
   }
 
   // Process rendered text change notifications.
   mTextHash.EnumerateEntries(TextEnumerator, mDocument);
   mTextHash.Clear();
 
   // Bind hanging child documents.
   uint32_t hangingDocCnt = mHangingChildDocuments.Length();
+  nsTArray<nsRefPtr<DocAccessible>> newChildDocs;
   for (uint32_t idx = 0; idx < hangingDocCnt; idx++) {
     DocAccessible* childDoc = mHangingChildDocuments[idx];
     if (childDoc->IsDefunct())
       continue;
 
     nsIContent* ownerContent = mDocument->DocumentNode()->
       FindContentForSubDocument(childDoc->DocumentNode());
     if (ownerContent) {
       Accessible* outerDocAcc = mDocument->GetAccessible(ownerContent);
       if (outerDocAcc && outerDocAcc->AppendChild(childDoc)) {
         if (mDocument->AppendChildDocument(childDoc)) {
-
+          newChildDocs.AppendElement(Move(mHangingChildDocuments[idx]));
           continue;
         }
 
         outerDocAcc->RemoveChild(childDoc);
       }
 
       // Failed to bind the child document, destroy it.
       childDoc->Shutdown();
     }
   }
 
-  nsTArray<nsRefPtr<DocAccessible>> newChildDocs = Move(mHangingChildDocuments);
+  mHangingChildDocuments.Clear();
 
   // If the document is ready and all its subdocuments are completely loaded
   // then process the document load.
   if (mDocument->HasLoadState(DocAccessible::eReady) &&
       !mDocument->HasLoadState(DocAccessible::eCompletelyLoaded) &&
       hangingDocCnt == 0) {
     uint32_t childDocCnt = mDocument->ChildDocumentCount(), childDocIdx = 0;
     for (; childDocIdx < childDocCnt; childDocIdx++) {
@@ -279,16 +280,17 @@ NotificationController::WillRefresh(mozi
     size_t newDocCount = newChildDocs.Length();
     for (size_t i = 0; i < newDocCount; i++) {
       DocAccessible* childDoc = newChildDocs[i];
       DocAccessibleChild* ipcDoc = new DocAccessibleChild(childDoc);
       childDoc->SetIPCDoc(ipcDoc);
       auto contentChild = dom::ContentChild::GetSingleton();
       DocAccessibleChild* parentIPCDoc = mDocument->IPCDoc();
       uint64_t id = reinterpret_cast<uintptr_t>(childDoc->Parent()->UniqueID());
+      MOZ_ASSERT(id);
       contentChild->SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
     }
   }
 
   mObservingState = eRefreshObserving;
   if (!mDocument)
     return;
 
--- a/accessible/base/Relation.h
+++ b/accessible/base/Relation.h
@@ -90,18 +90,18 @@ public:
 
     if (!mFirstIter)
       mLastIter = nullptr;
 
     return target;
   }
 
 private:
-  Relation& operator = (const Relation&) MOZ_DELETE;
-  Relation(const Relation&) MOZ_DELETE;
+  Relation& operator = (const Relation&) = delete;
+  Relation(const Relation&) = delete;
 
   nsAutoPtr<AccIterable> mFirstIter;
   AccIterable* mLastIter;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
--- a/accessible/base/StyleInfo.h
+++ b/accessible/base/StyleInfo.h
@@ -27,19 +27,19 @@ public:
   void MarginTop(nsAString& aValue) { Margin(eSideTop, aValue); }
   void MarginBottom(nsAString& aValue) { Margin(eSideBottom, aValue); }
 
   static void FormatColor(const nscolor& aValue, nsString& aFormattedValue);
   static void FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue);
   static void FormatTextDecorationStyle(uint8_t aValue, nsAString& aFormattedValue);
 
 private:
-  StyleInfo() MOZ_DELETE;
-  StyleInfo(const StyleInfo&) MOZ_DELETE;
-  StyleInfo& operator = (const StyleInfo&) MOZ_DELETE;
+  StyleInfo() = delete;
+  StyleInfo(const StyleInfo&) = delete;
+  StyleInfo& operator = (const StyleInfo&) = delete;
 
   void Margin(Side aSide, nsAString& aValue);
 
   dom::Element* mElement;
   nsRefPtr<nsStyleContext> mStyleContext;
 };
 
 } // namespace a11y
--- a/accessible/base/TextRange.h
+++ b/accessible/base/TextRange.h
@@ -213,18 +213,18 @@ public:
   bool IsValid() const { return mRoot; }
 
   void SetStartPoint(HyperTextAccessible* aContainer, int32_t aOffset)
     { mStartContainer = aContainer; mStartOffset = aOffset; }
   void SetEndPoint(HyperTextAccessible* aContainer, int32_t aOffset)
     { mStartContainer = aContainer; mStartOffset = aOffset; }
 
 private:
-  TextRange(const TextRange& aRange) MOZ_DELETE;
-  TextRange& operator=(const TextRange& aRange) MOZ_DELETE;
+  TextRange(const TextRange& aRange) = delete;
+  TextRange& operator=(const TextRange& aRange) = delete;
 
   friend class HyperTextAccessible;
   friend class xpcAccessibleTextRange;
 
   void Set(HyperTextAccessible* aRoot,
            HyperTextAccessible* aStartContainer, int32_t aStartOffset,
            HyperTextAccessible* aEndContainer, int32_t aEndOffset);
 
--- a/accessible/base/nsAccessibilityService.h
+++ b/accessible/base/nsAccessibilityService.h
@@ -246,18 +246,16 @@ GetAccService()
 }
 
 /**
  * Return true if we're in a content process and not B2G.
  */
 inline bool
 IPCAccessibilityActive()
 {
-  // XXX temporarily disable ipc accessibility because of crashes.
-return false;
 #ifdef MOZ_B2G
   return false;
 #else
   return XRE_GetProcessType() == GeckoProcessType_Content;
 #endif
 }
 
 /**
--- a/accessible/base/nsAccessiblePivot.h
+++ b/accessible/base/nsAccessiblePivot.h
@@ -34,19 +34,19 @@ public:
 
   /*
    * A simple getter for the pivot's position.
    */
   Accessible* Position() { return mPosition; }
 
 private:
   ~nsAccessiblePivot();
-  nsAccessiblePivot() MOZ_DELETE;
-  nsAccessiblePivot(const nsAccessiblePivot&) MOZ_DELETE;
-  void operator = (const nsAccessiblePivot&) MOZ_DELETE;
+  nsAccessiblePivot() = delete;
+  nsAccessiblePivot(const nsAccessiblePivot&) = delete;
+  void operator = (const nsAccessiblePivot&) = delete;
 
   /*
    * Notify all observers on a pivot change. Return true if it has changed and
    * observers have been notified.
    */
   bool NotifyOfPivotChange(Accessible* aOldAccessible,
                            int32_t aOldStart, int32_t aOldEnd,
                            PivotMoveReason aReason,
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -1107,19 +1107,19 @@ protected:
   friend class AccGroupInfo;
 
   /**
    * Non-null indicates author-supplied role; possibly state & value as well
    */
   nsRoleMapEntry* mRoleMapEntry;
 
 private:
-  Accessible() MOZ_DELETE;
-  Accessible(const Accessible&) MOZ_DELETE;
-  Accessible& operator =(const Accessible&) MOZ_DELETE;
+  Accessible() = delete;
+  Accessible(const Accessible&) = delete;
+  Accessible& operator =(const Accessible&) = delete;
 
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(Accessible,
                               NS_ACCESSIBLE_IMPL_IID)
 
 
 /**
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -117,38 +117,38 @@ var AccessFuTest = {
     // Finish through idle callback to let AccessFu._disable complete.
     SimpleTest.executeSoon(function () {
       AccessFu.detach();
       SimpleTest.finish();
     });
   },
 
   nextTest: function AccessFuTest_nextTest() {
-    var testFunc;
-    try {
-      // Get the next test function from the iterator. If none left,
-      // StopIteration exception is thrown.
-      testFunc = gIterator.next()[1];
-    } catch (ex) {
-      // StopIteration exception.
+    var result = gIterator.next();
+    if (result.done) {
       this.finish();
       return;
     }
+    var testFunc = result.value;
     testFunc();
   },
 
   runTests: function AccessFuTest_runTests(aAdditionalPrefs) {
     if (gTestFuncs.length === 0) {
       ok(false, "No tests specified!");
       SimpleTest.finish();
       return;
     }
 
     // Create an Iterator for gTestFuncs array.
-    gIterator = Iterator(gTestFuncs); // jshint ignore:line
+    gIterator = (function*() {
+      for (var testFunc of gTestFuncs) {
+        yield testFunc;
+      }
+    })();
 
     // Start AccessFu and put it in stand-by.
     Components.utils.import("resource://gre/modules/accessibility/AccessFu.jsm");
 
     AccessFu.attach(getMainChromeWindow(window));
 
     AccessFu.readyCallback = function readyCallback() {
       // Enable logging to the console service.
--- a/accessible/windows/msaa/EnumVariant.h
+++ b/accessible/windows/msaa/EnumVariant.h
@@ -35,18 +35,18 @@ public:
     /* [in] */ ULONG aCount);
 
   virtual HRESULT STDMETHODCALLTYPE Reset();
 
   virtual HRESULT STDMETHODCALLTYPE Clone(
     /* [out] */ IEnumVARIANT** aEnumVaraint);
 
 private:
-  ChildrenEnumVariant() MOZ_DELETE;
-  ChildrenEnumVariant& operator =(const ChildrenEnumVariant&) MOZ_DELETE;
+  ChildrenEnumVariant() = delete;
+  ChildrenEnumVariant& operator =(const ChildrenEnumVariant&) = delete;
 
   ChildrenEnumVariant(const ChildrenEnumVariant& aEnumVariant) :
     mAnchorAcc(aEnumVariant.mAnchorAcc), mCurAcc(aEnumVariant.mCurAcc),
     mCurIndex(aEnumVariant.mCurIndex) { }
   virtual ~ChildrenEnumVariant() { }
 
 protected:
   nsRefPtr<AccessibleWrap> mAnchorAcc;
--- a/accessible/windows/uia/uiaRawElmProvider.h
+++ b/accessible/windows/uia/uiaRawElmProvider.h
@@ -56,19 +56,19 @@ public:
   virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(
     /* [in] */ PROPERTYID aPropertyId,
     /* [retval][out] */ __RPC__out VARIANT* aPropertyValue);
 
   virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(
     /* [retval][out] */ __RPC__deref_out_opt IRawElementProviderSimple** aRawElmProvider);
 
 private:
-  uiaRawElmProvider() MOZ_DELETE;
-  uiaRawElmProvider& operator =(const uiaRawElmProvider&) MOZ_DELETE;
-  uiaRawElmProvider(const uiaRawElmProvider&) MOZ_DELETE;
+  uiaRawElmProvider() = delete;
+  uiaRawElmProvider& operator =(const uiaRawElmProvider&) = delete;
+  uiaRawElmProvider(const uiaRawElmProvider&) = delete;
 
 protected:
   nsRefPtr<AccessibleWrap> mAcc;
 };
 
 } // a11y namespace
 } // mozilla namespace
 
--- a/accessible/xpcom/xpcAccessible.h
+++ b/accessible/xpcom/xpcAccessible.h
@@ -81,16 +81,16 @@ public:
 
 protected:
   xpcAccessible() { }
   virtual ~xpcAccessible() {}
 
 private:
   Accessible* Intl();
 
-  xpcAccessible(const xpcAccessible&) MOZ_DELETE;
-  xpcAccessible& operator =(const xpcAccessible&) MOZ_DELETE;
+  xpcAccessible(const xpcAccessible&) = delete;
+  xpcAccessible& operator =(const xpcAccessible&) = delete;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/xpcom/xpcAccessibleApplication.h
+++ b/accessible/xpcom/xpcAccessibleApplication.h
@@ -33,16 +33,16 @@ public:
   NS_IMETHOD GetPlatformVersion(nsAString& aVersion) MOZ_FINAL;
 
 protected:
   virtual ~xpcAccessibleApplication() {}
 
 private:
   ApplicationAccessible* Intl() { return mIntl->AsApplication(); }
 
-  xpcAccessibleApplication(const xpcAccessibleApplication&) MOZ_DELETE;
-  xpcAccessibleApplication& operator =(const xpcAccessibleApplication&) MOZ_DELETE;
+  xpcAccessibleApplication(const xpcAccessibleApplication&) = delete;
+  xpcAccessibleApplication& operator =(const xpcAccessibleApplication&) = delete;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/xpcom/xpcAccessibleDocument.h
+++ b/accessible/xpcom/xpcAccessibleDocument.h
@@ -64,18 +64,18 @@ private:
       xpcAcc->Shutdown();
 
     mCache.Remove(aAccessible);
   }
 
   friend class DocManager;
   friend class DocAccessible;
 
-  xpcAccessibleDocument(const xpcAccessibleDocument&) MOZ_DELETE;
-  xpcAccessibleDocument& operator =(const xpcAccessibleDocument&) MOZ_DELETE;
+  xpcAccessibleDocument(const xpcAccessibleDocument&) = delete;
+  xpcAccessibleDocument& operator =(const xpcAccessibleDocument&) = delete;
 
   nsRefPtrHashtable<nsPtrHashKey<const Accessible>, xpcAccessibleGeneric> mCache;
 };
 
 inline xpcAccessibleGeneric*
 ToXPC(Accessible* aAccessible)
 {
   if (!aAccessible)
--- a/accessible/xpcom/xpcAccessibleGeneric.h
+++ b/accessible/xpcom/xpcAccessibleGeneric.h
@@ -61,18 +61,18 @@ protected:
 
 private:
   friend class Accessible;
   friend class xpcAccessible;
   friend class xpcAccessibleHyperLink;
   friend class xpcAccessibleSelectable;
   friend class xpcAccessibleValue;
 
-  xpcAccessibleGeneric(const xpcAccessibleGeneric&) MOZ_DELETE;
-  xpcAccessibleGeneric& operator =(const xpcAccessibleGeneric&) MOZ_DELETE;
+  xpcAccessibleGeneric(const xpcAccessibleGeneric&) = delete;
+  xpcAccessibleGeneric& operator =(const xpcAccessibleGeneric&) = delete;
 };
 
 inline Accessible*
 xpcAccessible::Intl()
 {
   return static_cast<xpcAccessibleGeneric*>(this)->mIntl;
 }
 
--- a/accessible/xpcom/xpcAccessibleHyperLink.h
+++ b/accessible/xpcom/xpcAccessibleHyperLink.h
@@ -30,18 +30,18 @@ public:
   NS_IMETHOD GetAnchor(int32_t aIndex, nsIAccessible** aAccessible) MOZ_FINAL;
   NS_IMETHOD GetValid(bool* aValid) MOZ_FINAL;
 
 protected:
   xpcAccessibleHyperLink() { }
   virtual ~xpcAccessibleHyperLink() {}
 
 private:
-  xpcAccessibleHyperLink(const xpcAccessibleHyperLink&) MOZ_DELETE;
-  xpcAccessibleHyperLink& operator =(const xpcAccessibleHyperLink&) MOZ_DELETE;
+  xpcAccessibleHyperLink(const xpcAccessibleHyperLink&) = delete;
+  xpcAccessibleHyperLink& operator =(const xpcAccessibleHyperLink&) = delete;
 
   Accessible* Intl();
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/xpcom/xpcAccessibleHyperText.h
+++ b/accessible/xpcom/xpcAccessibleHyperText.h
@@ -37,16 +37,16 @@ public:
   NS_DECL_NSIACCESSIBLEEDITABLETEXT
 
 protected:
   virtual ~xpcAccessibleHyperText() {}
 
 private:
   HyperTextAccessible* Intl() { return mIntl->AsHyperText(); }
 
-  xpcAccessibleHyperText(const xpcAccessibleHyperText&) MOZ_DELETE;
-  xpcAccessibleHyperText& operator =(const xpcAccessibleHyperText&) MOZ_DELETE;
+  xpcAccessibleHyperText(const xpcAccessibleHyperText&) = delete;
+  xpcAccessibleHyperText& operator =(const xpcAccessibleHyperText&) = delete;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_xpcAccessibleHyperText_h_
--- a/accessible/xpcom/xpcAccessibleImage.h
+++ b/accessible/xpcom/xpcAccessibleImage.h
@@ -28,16 +28,16 @@ public:
   NS_IMETHOD GetImageSize(int32_t* aWidth, int32_t* aHeight) MOZ_FINAL;
 
 protected:
   virtual ~xpcAccessibleImage() {}
 
 private:
   ImageAccessible* Intl() { return mIntl->AsImage(); }
 
-  xpcAccessibleImage(const xpcAccessibleImage&) MOZ_DELETE;
-  xpcAccessibleImage& operator =(const xpcAccessibleImage&) MOZ_DELETE;
+  xpcAccessibleImage(const xpcAccessibleImage&) = delete;
+  xpcAccessibleImage& operator =(const xpcAccessibleImage&) = delete;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/xpcom/xpcAccessibleSelectable.h
+++ b/accessible/xpcom/xpcAccessibleSelectable.h
@@ -34,18 +34,18 @@ public:
   NS_IMETHOD SelectAll(bool* aIsMultiSelect) MOZ_FINAL;
   NS_IMETHOD UnselectAll() MOZ_FINAL;
 
 protected:
   xpcAccessibleSelectable() { }
   virtual ~xpcAccessibleSelectable() {}
 
 private:
-  xpcAccessibleSelectable(const xpcAccessibleSelectable&) MOZ_DELETE;
-  xpcAccessibleSelectable& operator =(const xpcAccessibleSelectable&) MOZ_DELETE;
+  xpcAccessibleSelectable(const xpcAccessibleSelectable&) = delete;
+  xpcAccessibleSelectable& operator =(const xpcAccessibleSelectable&) = delete;
 
   Accessible* Intl();
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/accessible/xpcom/xpcAccessibleTable.h
+++ b/accessible/xpcom/xpcAccessibleTable.h
@@ -64,16 +64,16 @@ public:
   NS_IMETHOD IsProbablyForLayout(bool* aIsForLayout) MOZ_FINAL;
 
 protected:
   virtual ~xpcAccessibleTable() {}
 
 private:
   TableAccessible* Intl() { return mIntl->AsTable(); }
 
-  xpcAccessibleTable(const xpcAccessibleTable&) MOZ_DELETE;
-  xpcAccessibleTable& operator =(const xpcAccessibleTable&) MOZ_DELETE;
+  xpcAccessibleTable(const xpcAccessibleTable&) = delete;
+  xpcAccessibleTable& operator =(const xpcAccessibleTable&) = delete;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_xpcAccessibleTable_h_
--- a/accessible/xpcom/xpcAccessibleTableCell.h
+++ b/accessible/xpcom/xpcAccessibleTableCell.h
@@ -37,16 +37,16 @@ public:
   NS_IMETHOD IsSelected(bool* aSelected) MOZ_FINAL;
 
 protected:
   virtual ~xpcAccessibleTableCell() {}
 
 private:
   TableCellAccessible* Intl() { return mIntl->AsTableCell(); }
 
-  xpcAccessibleTableCell(const xpcAccessibleTableCell&) MOZ_DELETE;
-  xpcAccessibleTableCell& operator =(const xpcAccessibleTableCell&) MOZ_DELETE;
+  xpcAccessibleTableCell(const xpcAccessibleTableCell&) = delete;
+  xpcAccessibleTableCell& operator =(const xpcAccessibleTableCell&) = delete;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif // mozilla_a11y_xpcom_xpcAccessibletableCell_h_
--- a/accessible/xpcom/xpcAccessibleTextRange.h
+++ b/accessible/xpcom/xpcAccessibleTextRange.h
@@ -64,18 +64,18 @@ private:
   explicit xpcAccessibleTextRange(TextRange&& aRange) :
     mRange(Forward<TextRange>(aRange)) {}
   xpcAccessibleTextRange() {}
 
   ~xpcAccessibleTextRange() {}
 
   friend class xpcAccessibleHyperText;
 
-  xpcAccessibleTextRange(const xpcAccessibleTextRange&) MOZ_DELETE;
-  xpcAccessibleTextRange& operator =(const xpcAccessibleTextRange&) MOZ_DELETE;
+  xpcAccessibleTextRange(const xpcAccessibleTextRange&) = delete;
+  xpcAccessibleTextRange& operator =(const xpcAccessibleTextRange&) = delete;
 
   TextRange mRange;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(xpcAccessibleTextRange,
                               NS_ACCESSIBLETEXTRANGE_IMPL_IID)
 
 } // namespace a11y
--- a/accessible/xpcom/xpcAccessibleValue.h
+++ b/accessible/xpcom/xpcAccessibleValue.h
@@ -29,16 +29,16 @@ public:
 
 protected:
   xpcAccessibleValue() { }
   virtual ~xpcAccessibleValue() {}
 
 private:
   Accessible* Intl();
 
-  xpcAccessibleValue(const xpcAccessibleValue&) MOZ_DELETE;
-  xpcAccessibleValue& operator =(const xpcAccessibleValue&) MOZ_DELETE;
+  xpcAccessibleValue(const xpcAccessibleValue&) = delete;
+  xpcAccessibleValue& operator =(const xpcAccessibleValue&) = delete;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -690,60 +690,67 @@ pref("dom.ipc.processPriorityManager.tem
 // Number of different background levels for background processes.  We use
 // these different levels to force the low-memory killer to kill processes in
 // a LRU order.
 pref("dom.ipc.processPriorityManager.backgroundLRUPoolLevels", 5);
 
 // Kernel parameters for process priorities.  These affect how processes are
 // killed on low-memory and their relative CPU priorities.
 //
-// Note: The maximum nice value on Linux is 19, but the max value you should
-// use here is 18.  NSPR adds 1 to some threads' nice values, to mark
-// low-priority threads.  If the process priority manager were to renice a
-// process (and all its threads) to 19, all threads would have the same
-// niceness.  Then when we reniced the process to (say) 10, all threads would
-// /still/ have the same niceness; we'd effectively have erased NSPR's thread
-// priorities.
-
 // The kernel can only accept 6 (OomScoreAdjust, KillUnderKB) pairs. But it is
 // okay, kernel will still kill processes with larger OomScoreAdjust first even
 // its OomScoreAdjust don't have a corresponding KillUnderKB.
 
 pref("hal.processPriorityManager.gonk.MASTER.OomScoreAdjust", 0);
 pref("hal.processPriorityManager.gonk.MASTER.KillUnderKB", 4096);
-pref("hal.processPriorityManager.gonk.MASTER.Nice", 0);
+pref("hal.processPriorityManager.gonk.MASTER.cgroup", "");
 
 pref("hal.processPriorityManager.gonk.PREALLOC.OomScoreAdjust", 67);
-pref("hal.processPriorityManager.gonk.PREALLOC.Nice", 18);
+pref("hal.processPriorityManager.gonk.PREALLOC.cgroup", "apps/bg_non_interactive");
 
 pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.OomScoreAdjust", 67);
 pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.KillUnderKB", 5120);
-pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.Nice", 0);
+pref("hal.processPriorityManager.gonk.FOREGROUND_HIGH.cgroup", "apps/critical");
 
 pref("hal.processPriorityManager.gonk.FOREGROUND.OomScoreAdjust", 134);
 pref("hal.processPriorityManager.gonk.FOREGROUND.KillUnderKB", 6144);
-pref("hal.processPriorityManager.gonk.FOREGROUND.Nice", 1);
+pref("hal.processPriorityManager.gonk.FOREGROUND.cgroup", "apps");
 
 pref("hal.processPriorityManager.gonk.FOREGROUND_KEYBOARD.OomScoreAdjust", 200);
-pref("hal.processPriorityManager.gonk.FOREGROUND_KEYBOARD.Nice", 1);
+pref("hal.processPriorityManager.gonk.FOREGROUND_KEYBOARD.cgroup", "apps");
 
 pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.OomScoreAdjust", 400);
 pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.KillUnderKB", 7168);
-pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.Nice", 7);
+pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.cgroup", "apps/bg_perceivable");
 
 pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.OomScoreAdjust", 534);
 pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.KillUnderKB", 8192);
-pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.Nice", 18);
+pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.cgroup", "apps/bg_non_interactive");
 
 pref("hal.processPriorityManager.gonk.BACKGROUND.OomScoreAdjust", 667);
 pref("hal.processPriorityManager.gonk.BACKGROUND.KillUnderKB", 20480);
-pref("hal.processPriorityManager.gonk.BACKGROUND.Nice", 18);
+pref("hal.processPriorityManager.gonk.BACKGROUND.cgroup", "apps/bg_non_interactive");
+
+// Control group definitions (i.e., CPU priority groups) for B2G processes.
+
+// Foreground apps
+pref("hal.processPriorityManager.gonk.cgroups.apps.cpu_shares", 1024);
+pref("hal.processPriorityManager.gonk.cgroups.apps.cpu_notify_on_migrate", 1);
 
-// Processes get this niceness when they have low CPU priority.
-pref("hal.processPriorityManager.gonk.LowCPUNice", 18);
+// Foreground apps with high priority, 16x more CPU than foreground ones
+pref("hal.processPriorityManager.gonk.cgroups.apps/critical.cpu_shares", 16384);
+pref("hal.processPriorityManager.gonk.cgroups.apps/critical.cpu_notify_on_migrate", 1);
+
+// Background perceivable apps, ~10x less CPU than foreground ones
+pref("hal.processPriorityManager.gonk.cgroups.apps/bg_perceivable.cpu_shares", 103);
+pref("hal.processPriorityManager.gonk.cgroups.apps/bg_perceivable.cpu_notify_on_migrate", 0);
+
+// Background apps, ~20x less CPU than foreground ones and ~2x less than perceivable ones
+pref("hal.processPriorityManager.gonk.cgroups.apps/bg_non_interactive.cpu_shares", 52);
+pref("hal.processPriorityManager.gonk.cgroups.apps/bg_non_interactive.cpu_notify_on_migrate", 0);
 
 // By default the compositor thread on gonk runs without real-time priority.  RT
 // priority can be enabled by setting this pref to a value between 1 and 99.
 // Note that audio processing currently runs at RT priority 2 or 3 at most.
 //
 // If RT priority is disabled, then the compositor nice value is used. We prefer
 // to use a nice value of -4, which matches Android's preferences. Setting a preference
 // of RT priority 1 would mean it is higher than audio, which is -16. The compositor
--- a/b2g/config/mozconfigs/linux32_gecko/debug
+++ b/b2g/config/mozconfigs/linux32_gecko/debug
@@ -15,17 +15,17 @@ ac_add_options --enable-debug
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
-# DISABLED WHILE NOT ON TRY ac_add_options --enable-warnings-as-errors
+ac_add_options --enable-warnings-as-errors
 
 # Use sccache
 no_sccache=
 . "$topsrcdir/build/mozconfig.cache"
 
 #B2G options
 ac_add_options --enable-application=b2g
 ENABLE_MARIONETTE=1
--- a/b2g/config/mozconfigs/linux32_gecko/nightly
+++ b/b2g/config/mozconfigs/linux32_gecko/nightly
@@ -14,17 +14,17 @@ ac_add_options --enable-signmar
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
-# DISABLED WHILE NOT ON TRY ac_add_options --enable-warnings-as-errors
+ac_add_options --enable-warnings-as-errors
 
 # Use sccache
 no_sccache=
 . "$topsrcdir/build/mozconfig.cache"
 
 #B2G options
 ac_add_options --enable-application=b2g
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
--- a/b2g/config/mozconfigs/linux64_gecko/debug
+++ b/b2g/config/mozconfigs/linux64_gecko/debug
@@ -15,17 +15,17 @@ ac_add_options --enable-debug
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
-# DISABLED WHILE NOT ON TRY ac_add_options --enable-warnings-as-errors
+ac_add_options --enable-warnings-as-errors
 
 # Use sccache
 no_sccache=
 . "$topsrcdir/build/mozconfig.cache"
 
 #B2G options
 ac_add_options --enable-application=b2g
 ENABLE_MARIONETTE=1
--- a/b2g/config/mozconfigs/linux64_gecko/nightly
+++ b/b2g/config/mozconfigs/linux64_gecko/nightly
@@ -14,17 +14,17 @@ ac_add_options --enable-signmar
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 # Treat warnings as errors in directories with FAIL_ON_WARNINGS.
-# DISABLED WHILE NOT ON TRY ac_add_options --enable-warnings-as-errors
+ac_add_options --enable-warnings-as-errors
 
 # Use sccache
 no_sccache=
 . "$topsrcdir/build/mozconfig.cache"
 
 #B2G options
 ac_add_options --enable-application=b2g
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1461,16 +1461,18 @@
 
             let wasActive = document.activeElement == aBrowser;
 
             // Unhook our progress listener.
             let tab = this.getTabForBrowser(aBrowser);
             let index = tab._tPos;
             let filter = this.mTabFilters[index];
             aBrowser.webProgress.removeProgressListener(filter);
+            // Make sure the browser is destroyed so it unregisters from observer notifications
+            aBrowser.destroy();
 
             // Change the "remote" attribute.
             let parent = aBrowser.parentNode;
             let permanentKey = aBrowser.permanentKey;
             parent.removeChild(aBrowser);
             aBrowser.setAttribute("remote", aShouldBeRemote ? "true" : "false");
             // Tearing down the browser gives a new permanentKey but we want to
             // keep the old one. Re-set it explicitly after unbinding from DOM.
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -118,16 +118,17 @@ skip-if = e10s # Bug 1093153 - no about:
 [browser_addKeywordSearch.js]
 [browser_search_favicon.js]
 [browser_alltabslistener.js]
 [browser_autocomplete_a11y_label.js]
 skip-if = e10s # Bug 1101993 - times out for unknown reasons when run in the dir (works on its own)
 [browser_autocomplete_no_title.js]
 [browser_autocomplete_autoselect.js]
 [browser_autocomplete_oldschool_wrap.js]
+[browser_autocomplete_tag_star_visibility.js]
 [browser_backButtonFitts.js]
 skip-if = os != "win" || e10s # The Fitts Law back button is only supported on Windows (bug 571454) / e10s - Bug 1099154: test touches content (attempts to add an event listener directly to the contentWindow)
 [browser_blob-channelname.js]
 [browser_bookmark_titles.js]
 skip-if = buildapp == 'mulet' || toolkit == "windows" || e10s # Disabled on Windows due to frequent failures (bugs 825739, 841341) / e10s - Bug 1094205 - places doesn't return the right thing in e10s mode, for some reason
 [browser_bug304198.js]
 skip-if = e10s
 [browser_bug321000.js]
@@ -192,18 +193,17 @@ skip-if = e10s # Bug 866413 - PageInfo d
 [browser_bug521216.js]
 [browser_bug533232.js]
 [browser_bug537013.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1093206 - need to re-enable tests relying on swapFrameLoaders et al for e10s (test calls replaceTabWithWindow)
 [browser_bug537474.js]
 skip-if = e10s # Bug 1102020 - test tries to use browserDOMWindow.openURI to open a link, and gets a null rv where it expects a window
 [browser_bug550565.js]
 [browser_bug553455.js]
-skip-if = true # Bug 1094312
-#skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works on mulet? ; for e10s, indefinite waiting halfway through the test, tracked in bug 1093586
+skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works on mulet?
 [browser_bug555224.js]
 skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug555767.js]
 skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory
 [browser_bug556061.js]
 [browser_bug559991.js]
 [browser_bug561623.js]
 skip-if = e10s
@@ -227,17 +227,16 @@ skip-if = e10s # Bug 1056146 - zoom test
 [browser_bug580638.js]
 [browser_bug580956.js]
 [browser_bug581242.js]
 [browser_bug581253.js]
 skip-if = e10s # Bug 1093756 - can't bookmark the data: url in e10s somehow
 [browser_bug581947.js]
 skip-if = e10s
 [browser_bug585558.js]
-skip-if = true # Bug 1094312 - Disabling browser_bug553455.js made this permafail
 [browser_bug585785.js]
 [browser_bug585830.js]
 [browser_bug590206.js]
 [browser_bug592338.js]
 skip-if = e10s # Bug 653065 - Make the lightweight theme web installer ready for e10s
 [browser_bug594131.js]
 [browser_bug595507.js]
 skip-if = e10s # Bug 1093677 - automated form submission from the test doesn't seem to quite work yet
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_autocomplete_tag_star_visibility.js
@@ -0,0 +1,105 @@
+add_task(function*() {
+  // This test is only relevant if UnifiedComplete is enabled.
+  Services.prefs.setBoolPref("browser.urlbar.unifiedcomplete", true);
+
+  registerCleanupFunction(() => {
+    PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
+    Services.prefs.clearUserPref("browser.urlbar.unifiedcomplete");
+    Services.prefs.clearUserPref("browser.urlbar.suggest.bookmark");
+  });
+
+  function* addTagItem(tagName) {
+    let uri = NetUtil.newURI(`http://example.com/this/is/tagged/${tagName}`);
+    PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
+                                         uri,
+                                         PlacesUtils.bookmarks.DEFAULT_INDEX,
+                                         `test ${tagName}`);
+    PlacesUtils.tagging.tagURI(uri, [tagName]);
+    yield PlacesTestUtils.addVisits([{uri: uri, title: `Test page with tag ${tagName}`}]);
+  }
+
+  // We use different tags for each part of the test, as otherwise the
+  // autocomplete code tries to be smart by using the previously cached element
+  // without updating it (since all parameters it knows about are the same).
+
+  let testcases = [{
+    description: "Test with suggest.bookmark=true",
+    tagName: "tagtest1",
+    prefs: {
+      "suggest.bookmark": true,
+    },
+    input: "tagtest1",
+    expected: {
+      type: "bookmark-tag",
+      typeImageVisible: true,
+    },
+  }, {
+    description: "Test with suggest.bookmark=false",
+    tagName: "tagtest2",
+    prefs: {
+      "suggest.bookmark": false,
+    },
+    input: "tagtest2",
+    expected: {
+      type: "tag",
+      typeImageVisible: false,
+    },
+  }, {
+    description: "Test with suggest.bookmark=true (again)",
+    tagName: "tagtest3",
+    prefs: {
+      "suggest.bookmark": true,
+    },
+    input: "tagtest3",
+    expected: {
+      type: "bookmark-tag",
+      typeImageVisible: true,
+    },
+  }, {
+    description: "Test with bookmark restriction token",
+    tagName: "tagtest4",
+    prefs: {
+      "suggest.bookmark": true,
+    },
+    input: "* tagtest4",
+    expected: {
+      type: "bookmark-tag",
+      typeImageVisible: true,
+    },
+  }, {
+    description: "Test with history restriction token",
+    tagName: "tagtest5",
+    prefs: {
+      "suggest.bookmark": true,
+    },
+    input: "^ tagtest5",
+    expected: {
+      type: "tag",
+      typeImageVisible: false,
+    },
+  }];
+
+
+  for (let testcase of testcases) {
+    info(`Test case: ${testcase.description}`);
+
+    yield addTagItem(testcase.tagName);
+    for (let prefName of Object.keys(testcase.prefs)) {
+      Services.prefs.setBoolPref(`browser.urlbar.${prefName}`, testcase.prefs[prefName]);
+    }
+
+    yield promiseAutocompleteResultPopup(testcase.input);
+    let result = gURLBar.popup.richlistbox.children[1];
+    ok(result && !result.collasped, "Should have result");
+
+    is(result.getAttribute("type"), testcase.expected.type, "Result should have expected type");
+    if (testcase.expected.typeImageVisible) {
+      is_element_visible(result._typeImage, "Type image should be visible");
+    } else {
+      is_element_hidden(result._typeImage, "Type image should be hidden");
+    }
+
+    gURLBar.popup.hidePopup();
+    yield promisePopupHidden(gURLBar.popup);
+  }
+});
--- a/browser/base/content/test/general/browser_bug553455.js
+++ b/browser/base/content/test/general/browser_bug553455.js
@@ -2,41 +2,52 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 const TESTROOT = "http://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/";
 const TESTROOT2 = "http://example.org/browser/toolkit/mozapps/extensions/test/xpinstall/";
 const SECUREROOT = "https://example.com/browser/toolkit/mozapps/extensions/test/xpinstall/";
 const XPINSTALL_URL = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
 const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts";
+const PROGRESS_NOTIFICATION = "addon-progress-notification";
 
 var rootDir = getRootDirectory(gTestPath);
 var path = rootDir.split('/');
 var chromeName = path[0] + '//' + path[2];
 var croot = chromeName + "/content/browser/toolkit/mozapps/extensions/test/xpinstall/";
 var jar = getJar(croot);
 if (jar) {
   var tmpdir = extractJarToTmp(jar);
   croot = 'file://' + tmpdir.path + '/';
 }
 const CHROMEROOT = croot;
 
 var gApp = document.getElementById("bundle_brand").getString("brandShortName");
 var gVersion = Services.appinfo.version;
 var check_notification;
 
-function wait_for_notification(aCallback) {
-  info("Waiting for notification");
+function wait_for_progress_notification(aCallback) {
+  wait_for_notification(PROGRESS_NOTIFICATION, aCallback, "popupshowing");
+}
+
+function wait_for_notification(aId, aCallback, aEvent = "popupshown") {
+  info("Waiting for " + aId + " notification");
   check_notification = function() {
-    PopupNotifications.panel.removeEventListener("popupshown", check_notification, false);
-    info("Saw notification");
+    // Ignore the progress notification unless that is the notification we want
+    if (aId != PROGRESS_NOTIFICATION && PopupNotifications.panel.childNodes[0].id == PROGRESS_NOTIFICATION)
+      return;
+
+    PopupNotifications.panel.removeEventListener(aEvent, check_notification, false);
+    info("Saw a notification");
     is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
+    if (PopupNotifications.panel.childNodes.length)
+      is(PopupNotifications.panel.childNodes[0].id, aId, "Should have seen the right notification");
     aCallback(PopupNotifications.panel);
   };
-  PopupNotifications.panel.addEventListener("popupshown", check_notification, false);
+  PopupNotifications.panel.addEventListener(aEvent, check_notification, false);
 }
 
 function wait_for_notification_close(aCallback) {
   info("Waiting for notification to close");
   PopupNotifications.panel.addEventListener("popuphidden", function() {
     PopupNotifications.panel.removeEventListener("popuphidden", arguments.callee, false);
     aCallback();
   }, false);
@@ -98,19 +109,18 @@ function setup_redirect(aSettings) {
   req.send(null);
 }
 
 var TESTS = [
 function test_disabled_install() {
   Services.prefs.setBoolPref("xpinstall.enabled", false);
 
   // Wait for the disabled notification
-  wait_for_notification(function(aPanel) {
+  wait_for_notification("xpinstall-disabled-notification", function(aPanel) {
     let notification = aPanel.childNodes[0];
-    is(notification.id, "xpinstall-disabled-notification", "Should have seen installs disabled");
     is(notification.button.label, "Enable", "Should have seen the right button");
     is(notification.getAttribute("label"),
        "Software installation is currently disabled. Click Enable and try again.");
 
     wait_for_notification_close(function() {
       try {
         ok(Services.prefs.getBoolPref("xpinstall.enabled"), "Installation should be enabled");
       }
@@ -136,31 +146,29 @@ function test_disabled_install() {
     "XPI": "unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_blocked_install() {
   // Wait for the blocked notification
-  wait_for_notification(function(aPanel) {
+  wait_for_notification("addon-install-blocked-notification", function(aPanel) {
     let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-install-blocked-notification", "Should have seen the install blocked");
     is(notification.button.label, "Allow", "Should have seen the right button");
     is(notification.getAttribute("label"),
        gApp + " prevented this site (example.com) from asking you to install " +
        "software on your computer.",
        "Should have seen the right message");
 
     // Wait for the install confirmation dialog
     wait_for_install_dialog(function(aWindow) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
+      wait_for_notification("addon-install-complete-notification", function(aPanel) {
         let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
         is(notification.button.label, "Restart Now", "Should have seen the right button");
         is(notification.getAttribute("label"),
            "XPI Test will be installed after you restart " + gApp + ".",
            "Should have seen the right message");
 
         AddonManager.getAllInstalls(function(aInstalls) {
         is(aInstalls.length, 1, "Should be one pending install");
           aInstalls[0].cancel();
@@ -187,26 +195,22 @@ function test_blocked_install() {
     "XPI": "unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_whitelisted_install() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the install confirmation dialog
     wait_for_install_dialog(function(aWindow) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
+      wait_for_notification("addon-install-complete-notification", function(aPanel) {
         let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
         is(notification.button.label, "Restart Now", "Should have seen the right button");
         is(notification.getAttribute("label"),
            "XPI Test will be installed after you restart " + gApp + ".",
            "Should have seen the right message");
 
         AddonManager.getAllInstalls(function(aInstalls) {
           is(aInstalls.length, 1, "Should be one pending install");
           aInstalls[0].cancel();
@@ -228,24 +232,20 @@ function test_whitelisted_install() {
     "XPI": "unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_failed_download() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the failed notification
-    wait_for_notification(function(aPanel) {
+    wait_for_notification("addon-install-failed-notification", function(aPanel) {
       let notification = aPanel.childNodes[0];
-      is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
       is(notification.getAttribute("label"),
          "The add-on could not be downloaded because of a connection failure " +
          "on example.com.",
          "Should have seen the right message");
 
       Services.perms.remove("example.com", "install");
       wait_for_notification_close(runNextTest);
       gBrowser.removeTab(gBrowser.selectedTab);
@@ -259,24 +259,20 @@ function test_failed_download() {
     "XPI": "missing.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_corrupt_file() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the failed notification
-    wait_for_notification(function(aPanel) {
+    wait_for_notification("addon-install-failed-notification", function(aPanel) {
       let notification = aPanel.childNodes[0];
-      is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
       is(notification.getAttribute("label"),
          "The add-on downloaded from example.com could not be installed " +
          "because it appears to be corrupt.",
          "Should have seen the right message");
 
       Services.perms.remove("example.com", "install");
       wait_for_notification_close(runNextTest);
       gBrowser.removeTab(gBrowser.selectedTab);
@@ -290,24 +286,20 @@ function test_corrupt_file() {
     "XPI": "corrupt.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_incompatible() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the failed notification
-    wait_for_notification(function(aPanel) {
+    wait_for_notification("addon-install-failed-notification", function(aPanel) {
       let notification = aPanel.childNodes[0];
-      is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
       is(notification.getAttribute("label"),
          "XPI Test could not be installed because it is not compatible with " +
          gApp + " " + gVersion + ".",
          "Should have seen the right message");
 
       Services.perms.remove("example.com", "install");
       wait_for_notification_close(runNextTest);
       gBrowser.removeTab(gBrowser.selectedTab);
@@ -321,26 +313,22 @@ function test_incompatible() {
     "XPI": "incompatible.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_restartless() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the install confirmation dialog
     wait_for_install_dialog(function(aWindow) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
+      wait_for_notification("addon-install-complete-notification", function(aPanel) {
         let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
         is(notification.getAttribute("label"),
            "XPI Test has been installed successfully.",
            "Should have seen the right message");
 
         AddonManager.getAllInstalls(function(aInstalls) {
           is(aInstalls.length, 0, "Should be no pending installs");
 
           AddonManager.getAddonByID("restartless-xpi@tests.mozilla.org", function(aAddon) {
@@ -364,26 +352,22 @@ function test_restartless() {
     "XPI": "restartless.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_multiple() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the install confirmation dialog
     wait_for_install_dialog(function(aWindow) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
+      wait_for_notification("addon-install-complete-notification", function(aPanel) {
         let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
         is(notification.button.label, "Restart Now", "Should have seen the right button");
         is(notification.getAttribute("label"),
            "2 add-ons will be installed after you restart " + gApp + ".",
            "Should have seen the right message");
 
         AddonManager.getAllInstalls(function(aInstalls) {
           is(aInstalls.length, 1, "Should be one pending install");
           aInstalls[0].cancel();
@@ -410,26 +394,22 @@ function test_multiple() {
     "Restartless XPI": "restartless.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_url() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the install confirmation dialog
     wait_for_install_dialog(function(aWindow) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
+      wait_for_notification("addon-install-complete-notification", function(aPanel) {
         let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
         is(notification.button.label, "Restart Now", "Should have seen the right button");
         is(notification.getAttribute("label"),
            "XPI Test will be installed after you restart " + gApp + ".",
            "Should have seen the right message");
 
         AddonManager.getAllInstalls(function(aInstalls) {
           is(aInstalls.length, 1, "Should be one pending install");
           aInstalls[0].cancel();
@@ -480,23 +460,20 @@ function test_wronghost() {
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.addEventListener("load", function() {
     if (gBrowser.currentURI.spec != TESTROOT2 + "enabled.html")
       return;
 
     gBrowser.removeEventListener("load", arguments.callee, true);
 
     // Wait for the progress notification
-    wait_for_notification(function(aPanel) {
-      let notification = aPanel.childNodes[0];
-      is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
+    wait_for_progress_notification(function(aPanel) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
+      wait_for_notification("addon-install-failed-notification", function(aPanel) {
         let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-failed-notification", "Should have seen the install fail");
         is(notification.getAttribute("label"),
            "The add-on downloaded from example.com could not be installed " +
            "because it appears to be corrupt.",
            "Should have seen the right message");
 
         wait_for_notification_close(runNextTest);
         gBrowser.removeTab(gBrowser.selectedTab);
       });
@@ -504,26 +481,22 @@ function test_wronghost() {
 
     gBrowser.loadURI(TESTROOT + "corrupt.xpi");
   }, true);
   gBrowser.loadURI(TESTROOT2 + "enabled.html");
 },
 
 function test_reload() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the install confirmation dialog
     wait_for_install_dialog(function(aWindow) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
+      wait_for_notification("addon-install-complete-notification", function(aPanel) {
         let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
         is(notification.button.label, "Restart Now", "Should have seen the right button");
         is(notification.getAttribute("label"),
            "XPI Test will be installed after you restart " + gApp + ".",
            "Should have seen the right message");
 
         function test_fail() {
           ok(false, "Reloading should not have hidden the notification");
         }
@@ -561,26 +534,22 @@ function test_reload() {
     "Unsigned XPI": "unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_theme() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the install confirmation dialog
     wait_for_install_dialog(function(aWindow) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
+      wait_for_notification("addon-install-complete-notification", function(aPanel) {
         let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
         is(notification.button.label, "Restart Now", "Should have seen the right button");
         is(notification.getAttribute("label"),
            "Theme Test will be installed after you restart " + gApp + ".",
            "Should have seen the right message");
 
         AddonManager.getAddonByID("{972ce4c6-7e08-4474-a285-3208198ce6fd}", function(aAddon) {
           ok(aAddon.userDisabled, "Should be switching away from the default theme.");
           // Undo the pending theme switch
@@ -608,28 +577,23 @@ function test_theme() {
     "Theme XPI": "theme.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_renotify_blocked() {
   // Wait for the blocked notification
-  wait_for_notification(function(aPanel) {
+  wait_for_notification("addon-install-blocked-notification", function(aPanel) {
     let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-install-blocked-notification", "Should have seen the install blocked");
 
     wait_for_notification_close(function () {
       info("Timeouts after this probably mean bug 589954 regressed");
       executeSoon(function () {
-        wait_for_notification(function(aPanel) {
-          let notification = aPanel.childNodes[0];
-          is(notification.id, "addon-install-blocked-notification",
-             "Should have seen the install blocked - 2nd time");
-
+        wait_for_notification("addon-install-blocked-notification", function(aPanel) {
           AddonManager.getAllInstalls(function(aInstalls) {
           is(aInstalls.length, 2, "Should be two pending installs");
             aInstalls[0].cancel();
             aInstalls[1].cancel();
 
             info("Closing browser tab");
             wait_for_notification_close(runNextTest);
             gBrowser.removeTab(gBrowser.selectedTab);
@@ -648,45 +612,33 @@ function test_renotify_blocked() {
     "XPI": "unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_renotify_installed() {
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
-    let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+  wait_for_progress_notification(function(aPanel) {
     // Wait for the install confirmation dialog
     wait_for_install_dialog(function(aWindow) {
       // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
-        let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
-
+      wait_for_notification("addon-install-complete-notification", function(aPanel) {
         // Dismiss the notification
         wait_for_notification_close(function () {
           // Install another
           executeSoon(function () {
             // Wait for the progress notification
-            wait_for_notification(function(aPanel) {
-              let notification = aPanel.childNodes[0];
-              is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
+            wait_for_progress_notification(function(aPanel) {
               // Wait for the install confirmation dialog
               wait_for_install_dialog(function(aWindow) {
                 info("Timeouts after this probably mean bug 589954 regressed");
 
                 // Wait for the complete notification
-                wait_for_notification(function(aPanel) {
-                  let notification = aPanel.childNodes[0];
-                  is(notification.id, "addon-install-complete-notification", "Should have seen the second install complete");
-
+                wait_for_notification("addon-install-complete-notification", function(aPanel) {
                   AddonManager.getAllInstalls(function(aInstalls) {
                   is(aInstalls.length, 1, "Should be one pending installs");
                     aInstalls[0].cancel();
 
                     Services.perms.remove("example.com", "install");
                     wait_for_notification_close(runNextTest);
                     gBrowser.removeTab(gBrowser.selectedTab);
                   });
@@ -714,96 +666,111 @@ function test_renotify_installed() {
   var triggers = encodeURIComponent(JSON.stringify({
     "XPI": "unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_cancel_restart() {
+  function complete_install(callback) {
+    let url = TESTROOT + "slowinstall.sjs?continue=true"
+    NetUtil.asyncFetch(url, callback || (() => {}));
+  }
+
   // Wait for the progress notification
-  wait_for_notification(function(aPanel) {
+  wait_for_notification(PROGRESS_NOTIFICATION, function(aPanel) {
     let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
     // Close the notification
     let anchor = document.getElementById("addons-notification-icon");
     anchor.click();
     // Reopen the notification
     anchor.click();
 
     ok(PopupNotifications.isPanelOpen, "Notification should still be open");
     is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
     isnot(notification, aPanel.childNodes[0], "Should have reconstructed the notification UI");
     notification = aPanel.childNodes[0];
     is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
     let button = document.getAnonymousElementByAttribute(notification, "anonid", "cancel");
 
-    // Cancel the download
-    EventUtils.synthesizeMouse(button, 2, 2, {});
+    // Wait for the install to fully cancel
+    let install = notification.notification.options.installs[0];
+    install.addListener({
+      onDownloadCancelled: function() {
+        install.removeListener(this);
 
-    // Notification should have changed to cancelled
-    notification = aPanel.childNodes[0];
-    is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
+        executeSoon(function() {
+          ok(PopupNotifications.isPanelOpen, "Notification should still be open");
+          is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
+          isnot(notification, aPanel.childNodes[0], "Should have reconstructed the notification UI");
+          notification = aPanel.childNodes[0];
+          is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
+
+          // Wait for the install confirmation dialog
+          wait_for_install_dialog(function(aWindow) {
+            // Wait for the complete notification
+            wait_for_notification("addon-install-complete-notification", function(aPanel) {
+              let notification = aPanel.childNodes[0];
+              is(notification.button.label, "Restart Now", "Should have seen the right button");
+              is(notification.getAttribute("label"),
+                 "XPI Test will be installed after you restart " + gApp + ".",
+                 "Should have seen the right message");
 
-    // Wait for the install confirmation dialog
-    wait_for_install_dialog(function(aWindow) {
-      // Wait for the complete notification
-      wait_for_notification(function(aPanel) {
-        let notification = aPanel.childNodes[0];
-        is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
-        is(notification.button.label, "Restart Now", "Should have seen the right button");
-        is(notification.getAttribute("label"),
-           "XPI Test will be installed after you restart " + gApp + ".",
-           "Should have seen the right message");
+              AddonManager.getAllInstalls(function(aInstalls) {
+                is(aInstalls.length, 1, "Should be one pending install");
+                aInstalls[0].cancel();
+
+                Services.perms.remove("example.com", "install");
+                wait_for_notification_close(runNextTest);
+                gBrowser.removeTab(gBrowser.selectedTab);
+              });
+            });
+
+            aWindow.document.documentElement.acceptDialog();
+          });
 
-        AddonManager.getAllInstalls(function(aInstalls) {
-          is(aInstalls.length, 1, "Should be one pending install");
-          aInstalls[0].cancel();
+          // Restart the download
+          EventUtils.synthesizeMouseAtCenter(notification.button, {});
 
-          Services.perms.remove("example.com", "install");
-          wait_for_notification_close(runNextTest);
-          gBrowser.removeTab(gBrowser.selectedTab);
+          // Should be back to a progress notification
+          ok(PopupNotifications.isPanelOpen, "Notification should still be open");
+          is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
+          notification = aPanel.childNodes[0];
+          is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
+
+          complete_install();
         });
-      });
-
-      aWindow.document.documentElement.acceptDialog();
+      }
     });
 
-    // Restart the download
-    EventUtils.synthesizeMouse(notification.button, 20, 10, {});
-
-    // Should be back to a progress notification
-    ok(PopupNotifications.isPanelOpen, "Notification should still be open");
-    is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
-    notification = aPanel.childNodes[0];
-    is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
+    // Cancel the download
+    EventUtils.synthesizeMouseAtCenter(button, {});
   });
 
   var pm = Services.perms;
   pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(JSON.stringify({
-    "XPI": "unsigned.xpi"
+    "XPI": "slowinstall.sjs?file=unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_failed_security() {
   Services.prefs.setBoolPref(PREF_INSTALL_REQUIREBUILTINCERTS, false);
 
   setup_redirect({
     "Location": TESTROOT + "unsigned.xpi"
   });
 
   // Wait for the blocked notification
-  wait_for_notification(function(aPanel) {
+  wait_for_notification("addon-install-blocked-notification", function(aPanel) {
     let notification = aPanel.childNodes[0];
-    is(notification.id, "addon-install-blocked-notification", "Should have seen the install blocked");
 
     // Click on Allow
     EventUtils.synthesizeMouse(notification.button, 20, 10, {});
 
     // Notification should have changed to progress notification
     ok(PopupNotifications.isPanelOpen, "Notification should still be open");
     is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
     notification = aPanel.childNodes[0];
--- a/browser/base/content/test/social/head.js
+++ b/browser/base/content/test/social/head.js
@@ -162,41 +162,46 @@ function runSocialTestWithProvider(manif
           callback(finishSocialTest);
         }, "providers added and enabled");
       }
     });
   });
 }
 
 function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
-  let testIter = Iterator(tests);
+  let testIter = (function*() {
+    for (let name in tests) {
+      if (tests.hasOwnProperty(name)) {
+        yield [name, tests[name]];
+      }
+    }
+  })();
   let providersAtStart = Social.providers.length;
   info("runSocialTests: start test run with " + providersAtStart + " providers");
   window.focus();
 
   PopupNotifications.transitionsEnabled = false;
 
   if (cbPreTest === undefined) {
     cbPreTest = function(cb) {cb()};
   }
   if (cbPostTest === undefined) {
     cbPostTest = function(cb) {cb()};
   }
 
   function runNextTest() {
-    let name, func;
-    try {
-      [name, func] = testIter.next();
-    } catch (err if err instanceof StopIteration) {
+    let result = testIter.next();
+    if (result.done) {
       // out of items:
       (cbFinish || defaultFinishChecks)();
       is(providersAtStart, Social.providers.length,
          "runSocialTests: finish test run with " + Social.providers.length + " providers");
       return;
     }
+    let [name, func] = result.value;
     // We run on a timeout as the frameworker also makes use of timeouts, so
     // this helps keep the debug messages sane.
     executeSoon(function() {
       function cleanupAndRunNextTest() {
         info("sub-test " + name + " complete");
         cbPostTest(runNextTest);
       }
       cbPreTest(function() {
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -508,18 +508,21 @@ loop.panel = (function(_, mozL10n) {
       );
     }
   });
 
   /**
    * FxA sign in/up link component.
    */
   var AuthLink = React.createClass({displayName: "AuthLink",
+    mixins: [sharedMixins.WindowCloseMixin],
+
     handleSignUpLinkClick: function() {
       navigator.mozLoop.logInToFxA();
+      this.closeWindow();
     },
 
     render: function() {
       if (!navigator.mozLoop.fxAEnabled || navigator.mozLoop.userProfile) {
         return null;
       }
       return (
         React.createElement("p", {className: "signin-link"}, 
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -508,18 +508,21 @@ loop.panel = (function(_, mozL10n) {
       );
     }
   });
 
   /**
    * FxA sign in/up link component.
    */
   var AuthLink = React.createClass({
+    mixins: [sharedMixins.WindowCloseMixin],
+
     handleSignUpLinkClick: function() {
       navigator.mozLoop.logInToFxA();
+      this.closeWindow();
     },
 
     render: function() {
       if (!navigator.mozLoop.fxAEnabled || navigator.mozLoop.userProfile) {
         return null;
       }
       return (
         <p className="signin-link">
--- a/browser/components/loop/content/shared/js/feedbackViews.js
+++ b/browser/components/loop/content/shared/js/feedbackViews.js
@@ -177,33 +177,34 @@ loop.shared.views.FeedbackView = (functi
     },
 
     getInitialState: function() {
       return {countdown: WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS};
     },
 
     componentDidMount: function() {
       this._timer = setInterval(function() {
+      if (this.state.countdown == 1) {
+        clearInterval(this._timer);
+        if (this.props.onAfterFeedbackReceived) {
+          this.props.onAfterFeedbackReceived();
+        }
+        return;
+      }
         this.setState({countdown: this.state.countdown - 1});
       }.bind(this), 1000);
     },
 
     componentWillUnmount: function() {
       if (this._timer) {
         clearInterval(this._timer);
       }
     },
 
     render: function() {
-      if (this.state.countdown < 1) {
-        clearInterval(this._timer);
-        if (this.props.onAfterFeedbackReceived) {
-          this.props.onAfterFeedbackReceived();
-        }
-      }
       return (
         React.createElement(FeedbackLayout, {title: l10n.get("feedback_thank_you_heading")}, 
           React.createElement("p", {className: "info thank-you"}, 
             l10n.get("feedback_window_will_close_in2", {
               countdown: this.state.countdown,
               num: this.state.countdown
             }))
         )
--- a/browser/components/loop/content/shared/js/feedbackViews.jsx
+++ b/browser/components/loop/content/shared/js/feedbackViews.jsx
@@ -177,33 +177,34 @@ loop.shared.views.FeedbackView = (functi
     },
 
     getInitialState: function() {
       return {countdown: WINDOW_AUTOCLOSE_TIMEOUT_IN_SECONDS};
     },
 
     componentDidMount: function() {
       this._timer = setInterval(function() {
+      if (this.state.countdown == 1) {
+        clearInterval(this._timer);
+        if (this.props.onAfterFeedbackReceived) {
+          this.props.onAfterFeedbackReceived();
+        }
+        return;
+      }
         this.setState({countdown: this.state.countdown - 1});
       }.bind(this), 1000);
     },
 
     componentWillUnmount: function() {
       if (this._timer) {
         clearInterval(this._timer);
       }
     },
 
     render: function() {
-      if (this.state.countdown < 1) {
-        clearInterval(this._timer);
-        if (this.props.onAfterFeedbackReceived) {
-          this.props.onAfterFeedbackReceived();
-        }
-      }
       return (
         <FeedbackLayout title={l10n.get("feedback_thank_you_heading")}>
           <p className="info thank-you">{
             l10n.get("feedback_window_will_close_in2", {
               countdown: this.state.countdown,
               num: this.state.countdown
             })}</p>
         </FeedbackLayout>
--- a/browser/components/loop/test/desktop-local/panel_test.js
+++ b/browser/components/loop/test/desktop-local/panel_test.js
@@ -248,40 +248,60 @@ describe("loop.panel", function() {
 
           expect(callTab.getDOMNode().classList.contains("selected"))
             .to.be.true;
         });
       });
     });
 
     describe("AuthLink", function() {
+
+      beforeEach(function() {
+        navigator.mozLoop.calls = { clearCallInProgress: function() {} };
+      });
+
+      afterEach(function() {
+        delete navigator.mozLoop.logInToFxA;
+        delete navigator.mozLoop.calls;
+        navigator.mozLoop.fxAEnabled = true;
+      });
+
       it("should trigger the FxA sign in/up process when clicking the link",
         function() {
           navigator.mozLoop.loggedInToFxA = false;
           navigator.mozLoop.logInToFxA = sandbox.stub();
 
           var view = createTestPanelView();
 
           TestUtils.Simulate.click(
             view.getDOMNode().querySelector(".signin-link a"));
 
           sinon.assert.calledOnce(navigator.mozLoop.logInToFxA);
         });
 
+      it("should close the panel after clicking the link",
+        function() {
+          navigator.mozLoop.loggedInToFxA = false;
+          navigator.mozLoop.logInToFxA = sandbox.stub();
+
+          var view = createTestPanelView();
+
+          TestUtils.Simulate.click(
+            view.getDOMNode().querySelector(".signin-link a"));
+
+          sinon.assert.calledOnce(fakeWindow.close);
+        });
+
       it("should be hidden if FxA is not enabled",
         function() {
           navigator.mozLoop.fxAEnabled = false;
           var view = TestUtils.renderIntoDocument(
             React.createElement(loop.panel.AuthLink));
           expect(view.getDOMNode()).to.be.null;
       });
-
-      afterEach(function() {
-        navigator.mozLoop.fxAEnabled = true;
-      });
     });
 
     describe("SettingsDropdown", function() {
       beforeEach(function() {
         navigator.mozLoop.logInToFxA = sandbox.stub();
         navigator.mozLoop.logOutFromFxA = sandbox.stub();
         navigator.mozLoop.openFxASettings = sandbox.stub();
       });
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -83,31 +83,35 @@
   <vbox id="trackingprotectionbox" hidden="true">
     <hbox align="center">
       <checkbox id="trackingProtection"
                 preference="privacy.trackingprotection.enabled"
                 accesskey="&trackingProtection.accesskey;"
                 label="&trackingProtection.label;" />
       <image id="trackingProtectionImage"/>
     </hbox>
-    <label id="trackingProtectionLearnMore"
-           class="text-link"
-           value="&trackingProtectionLearnMore.label;"/>
-    <separator/>
+    <hbox align="center"
+          class="indent">
+      <label id="trackingProtectionLearnMore"
+             class="text-link"
+             value="&trackingProtectionLearnMore.label;"/>
+    </hbox>
   </vbox>
-  <checkbox id="privacyDoNotTrackCheckbox"
-            label="&dntTrackingNotOkay.label2;"
-            accesskey="&dntTrackingNotOkay.accesskey;"
-            preference="privacy.donottrackheader.enabled"/>
-  <separator class="thin"/>
   <vbox>
-    <hbox pack="end">
-      <spacer flex="1"/>
-      <label class="text-link" id="doNotTrackInfo"
-            href="https://www.mozilla.org/dnt">
+    <hbox align="center">
+      <checkbox id="privacyDoNotTrackCheckbox"
+                label="&dntTrackingNotOkay.label2;"
+                accesskey="&dntTrackingNotOkay.accesskey;"
+                preference="privacy.donottrackheader.enabled"/>
+    </hbox>
+    <hbox align="center"
+          class="indent">
+      <label id="doNotTrackInfo"
+             class="text-link"
+             href="https://www.mozilla.org/dnt">
         &doNotTrackInfo.label;
       </label>
     </hbox>
   </vbox>
 </groupbox>
 
 <!-- History -->
 <groupbox id="historyGroup" data-category="panePrivacy" hidden="true">
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -90,34 +90,40 @@
     <groupbox id="trackingGroup" align="start">
       <caption label="&tracking.label;"/>
       <vbox id="trackingprotectionbox" hidden="true">
         <hbox align="center">
           <checkbox id="trackingProtection"
                     preference="privacy.trackingprotection.enabled"
                     accesskey="&trackingProtection.accesskey;"
                     label="&trackingProtection.label;" />
-          <image id="trackingProtectionImage" src="chrome://browser/skin/bad-content-blocked-16.png"/>
+          <image id="trackingProtectionImage"
+                 src="chrome://browser/skin/bad-content-blocked-16.png"/>
         </hbox>
-        <label id="trackingProtectionLearnMore"
-               class="text-link"
-               value="&trackingProtectionLearnMore.label;"/>
-        <separator/>
+        <hbox align="center"
+              class="indent">
+          <label id="trackingProtectionLearnMore"
+                 class="text-link"
+                 value="&trackingProtectionLearnMore.label;"/>
+        </hbox>
       </vbox>
-      <checkbox id="privacyDoNotTrackCheckbox"
-                label="&dntTrackingNotOkay.label2;"
-                accesskey="&dntTrackingNotOkay.accesskey;"
-                preference="privacy.donottrackheader.enabled"/>
-      <separator class="thin"/>
       <vbox>
-        <hbox pack="end">
-          <spacer flex="1"/>
-          <label class="text-link" id="doNotTrackInfo"
-                href="https://www.mozilla.org/dnt"
-                value="&doNotTrackInfo.label;"/>
+        <hbox align="center">
+          <checkbox id="privacyDoNotTrackCheckbox"
+                    label="&dntTrackingNotOkay.label2;"
+                    accesskey="&dntTrackingNotOkay.accesskey;"
+                    preference="privacy.donottrackheader.enabled"/>
+        </hbox>
+        <hbox align="center"
+              class="indent">
+          <label id="doNotTrackInfo"
+                 class="text-link"
+                 href="https://www.mozilla.org/dnt">
+            &doNotTrackInfo.label;
+          </label>
         </hbox>
       </vbox>
 
     </groupbox>
 
     <!-- History -->
     <groupbox id="historyGroup">
       <caption label="&history.label;"/>
--- a/browser/components/preferences/sync.js
+++ b/browser/components/preferences/sync.js
@@ -4,33 +4,38 @@
 
 Components.utils.import("resource://services-sync/main.js");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
   return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
 });
 
+XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
+  "resource://gre/modules/FxAccounts.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "fxaMigrator",
+  "resource://services-sync/FxaMigrator.jsm");
+
 const PAGE_NO_ACCOUNT = 0;
 const PAGE_HAS_ACCOUNT = 1;
 const PAGE_NEEDS_UPDATE = 2;
 const PAGE_PLEASE_WAIT = 3;
 const FXA_PAGE_LOGGED_OUT = 4;
 const FXA_PAGE_LOGGED_IN = 5;
 
 // Indexes into the "login status" deck.
 // We are in a successful verified state - everything should work!
 const FXA_LOGIN_VERIFIED = 0;
 // We have logged in to an unverified account.
 const FXA_LOGIN_UNVERIFIED = 1;
 // We are logged in locally, but the server rejected our credentials.
 const FXA_LOGIN_FAILED = 2;
 
 let gSyncPane = {
-  _stringBundle: null,
   prefArray: ["engine.bookmarks", "engine.passwords", "engine.prefs",
               "engine.tabs", "engine.history"],
 
   get page() {
     return document.getElementById("weavePrefsDeck").selectedIndex;
   },
 
   set page(val) {
@@ -84,44 +89,60 @@ let gSyncPane = {
 
   _init: function () {
     let topics = ["weave:service:login:error",
                   "weave:service:login:finish",
                   "weave:service:start-over:finish",
                   "weave:service:setup-complete",
                   "weave:service:logout:finish",
                   FxAccountsCommon.ONVERIFIED_NOTIFICATION];
+    let migrateTopic = "fxa-migration:state-changed";
 
     // Add the observers now and remove them on unload
     //XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
     //        of `this`. Fix in a followup. (bug 583347)
     topics.forEach(function (topic) {
       Weave.Svc.Obs.add(topic, this.updateWeavePrefs, this);
     }, this);
+    // The FxA migration observer is a special case.
+    Weave.Svc.Obs.add(migrateTopic, this.updateMigrationState, this);
+
     window.addEventListener("unload", function() {
-      topics.forEach(function (topic) {
+      topics.forEach(topic => {
         Weave.Svc.Obs.remove(topic, this.updateWeavePrefs, this);
-      }, gSyncPane);
-    }, false);
+      });
+      Weave.Svc.Obs.remove(migrateTopic, this.updateMigrationState, this);
+    }.bind(this), false);
 
-    this._stringBundle =
-      Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties");
+    XPCOMUtils.defineLazyGetter(this, '_stringBundle', () => {
+      return Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties");
+    });
+
+    XPCOMUtils.defineLazyGetter(this, '_accountsStringBundle', () => {
+      return Services.strings.createBundle("chrome://browser/locale/accounts.properties");
+    });
+
     this.updateWeavePrefs();
   },
 
   updateWeavePrefs: function () {
+    // ask the migration module to broadcast its current state (and nothing will
+    // happen if it's not loaded - which is good, as that means no migration
+    // is pending/necessary) - we don't want to suck that module in just to
+    // find there's nothing to do.
+    Services.obs.notifyObservers(null, "fxa-migration:state-request", null);
+
     let service = Components.classes["@mozilla.org/weave/service;1"]
                   .getService(Components.interfaces.nsISupports)
                   .wrappedJSObject;
     // service.fxAccountsEnabled is false iff sync is already configured for
     // the legacy provider.
     if (service.fxAccountsEnabled) {
       // determine the fxa status...
       this.page = PAGE_PLEASE_WAIT;
-      Components.utils.import("resource://gre/modules/FxAccounts.jsm");
       fxAccounts.getSignedInUser().then(data => {
         if (!data) {
           this.page = FXA_PAGE_LOGGED_OUT;
           return;
         }
         this.page = FXA_PAGE_LOGGED_IN;
         // We are logged in locally, but maybe we are in a state where the
         // server rejected our credentials (eg, password changed on the server)
@@ -170,16 +191,88 @@ let gSyncPane = {
     } else {
       this.page = PAGE_HAS_ACCOUNT;
       document.getElementById("accountName").value = Weave.Service.identity.account;
       document.getElementById("syncComputerName").value = Weave.Service.clientsEngine.localName;
       document.getElementById("tosPP-normal").hidden = this._usingCustomServer;
     }
   },
 
+  updateMigrationState: function(subject, state) {
+    let selIndex;
+    let container = document.getElementById("sync-migration");
+    switch (state) {
+      case fxaMigrator.STATE_USER_FXA: {
+        let sb = this._accountsStringBundle;
+        // There are 2 cases here - no email address means it is an offer on
+        // the first device (so the user is prompted to create an account).
+        // If there is an email address it is the "join the party" flow, so the
+        // user is prompted to sign in with the address they previously used.
+        let email = subject ? subject.QueryInterface(Components.interfaces.nsISupportsString).data : null;
+        let elt = document.getElementById("sync-migrate-upgrade-description");
+        elt.textContent = email ?
+                          sb.formatStringFromName("signInAfterUpgradeOnOtherDevice.description",
+                                                  [email], 1) :
+                          sb.GetStringFromName("needUserLong");
+
+        // The "upgrade" button.
+        let button = document.getElementById("sync-migrate-upgrade");
+        button.setAttribute("label",
+                            sb.GetStringFromName(email
+                                                 ? "signInAfterUpgradeOnOtherDevice.label"
+                                                 : "upgradeToFxA.label"));
+        button.setAttribute("accesskey",
+                            sb.GetStringFromName(email
+                                                 ? "signInAfterUpgradeOnOtherDevice.accessKey"
+                                                 : "upgradeToFxA.accessKey"));
+        // The "unlink" button - this is only shown for first migration
+        button = document.getElementById("sync-migrate-unlink");
+        if (email) {
+          button.hidden = true;
+        } else {
+          button.setAttribute("label", sb.GetStringFromName("unlinkMigration.label"));
+          button.setAttribute("accesskey", sb.GetStringFromName("unlinkMigration.accessKey"));
+        }
+        selIndex = 0;
+        break;
+      }
+      case fxaMigrator.STATE_USER_FXA_VERIFIED: {
+        let sb = this._accountsStringBundle;
+        let email = subject.QueryInterface(Components.interfaces.nsISupportsString).data;
+        let label = sb.formatStringFromName("needVerifiedUserLong", [email], 1);
+        let elt = document.getElementById("sync-migrate-verify-description");
+        elt.textContent = label;
+        // The "resend" button.
+        let button = document.getElementById("sync-migrate-resend");
+        button.setAttribute("label", sb.GetStringFromName("resendVerificationEmail.label"));
+        button.setAttribute("accesskey", sb.GetStringFromName("resendVerificationEmail.accessKey"));
+        // The "forget" button.
+        button = document.getElementById("sync-migrate-forget");
+        button.setAttribute("label", sb.GetStringFromName("forgetMigration.label"));
+        button.setAttribute("accesskey", sb.GetStringFromName("forgetMigration.accessKey"));
+        selIndex = 1;
+        break;
+      }
+      default:
+        if (state) { // |null| is expected, but everything else is not.
+          Cu.reportError("updateMigrationState has unknown state: " + state);
+        }
+        if (!container.hidden) {
+          window.innerHeight -= container.clientHeight;
+          container.hidden = true;
+        }
+        return;
+    }
+    document.getElementById("sync-migration-deck").selectedIndex = selIndex;
+    if (container.hidden) {
+      container.hidden = false;
+      window.innerHeight += container.clientHeight;
+    }
+  },
+
   startOver: function (showDialog) {
     if (showDialog) {
       let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
                   Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL + 
                   Services.prompt.BUTTON_POS_1_DEFAULT;
       let buttonChoice =
         Services.prompt.confirmEx(window,
                                   this._stringBundle.GetStringFromName("syncUnlink.title"),
@@ -277,17 +370,16 @@ let gSyncPane = {
   },
 
   manageFirefoxAccount: function() {
     let url = Services.prefs.getCharPref("identity.fxaccounts.settings.uri");
     this.openContentInBrowser(url);
   },
 
   verifyFirefoxAccount: function() {
-    Components.utils.import("resource://gre/modules/FxAccounts.jsm");
     fxAccounts.resendVerificationEmail().then(() => {
       fxAccounts.getSignedInUser().then(data => {
         let sb = Services.strings.createBundle("chrome://browser/locale/accounts.properties");
         let title = sb.GetStringFromName("verificationSentTitle");
         let heading = sb.formatStringFromName("verificationSentHeading",
                                               [data.email], 1);
         let description = sb.GetStringFromName("verificationSentDescription");
 
@@ -318,17 +410,16 @@ let gSyncPane = {
                         (ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL) +
                         ps.BUTTON_POS_1_DEFAULT;
       let pressed = Services.prompt.confirmEx(window, title, body, buttonFlags,
                                               continueLabel, null, null, null, {});
       if (pressed != 0) { // 0 is the "continue" button
         return;
       }
     }
-    Components.utils.import('resource://gre/modules/FxAccounts.jsm');
     fxAccounts.signOut().then(() => {
       this.updateWeavePrefs();
     });
   },
 
   openQuotaDialog: function () {
     let win = Services.wm.getMostRecentWindow("Sync:ViewQuota");
     if (win) {
@@ -351,10 +442,48 @@ let gSyncPane = {
       window.openDialog("chrome://browser/content/sync/addDevice.xul",
                         "syncAddDevice", "centerscreen,chrome,resizable=no");
     }
   },
 
   resetSync: function () {
     this.openSetup("reset");
   },
+
+  // click handlers for the FxA migration.
+  migrateUpgrade: function() {
+    fxaMigrator.getFxAccountCreationOptions().then(({url, options}) => {
+      this.openContentInBrowser(url, options);
+    });
+  },
+
+  migrateForget: function() {
+    fxaMigrator.forgetFxAccount();
+  },
+
+  migrateResend: function() {
+    fxaMigrator.resendVerificationMail(window);
+  },
+
+  // When the "Unlink" button in the migration header is selected we display
+  // a slightly different message.
+  startOverMigration: function () {
+    let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
+                Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL +
+                Services.prompt.BUTTON_POS_1_DEFAULT;
+    let sb = this._accountsStringBundle;
+    let buttonChoice =
+      Services.prompt.confirmEx(window,
+                                sb.GetStringFromName("unlinkVerificationTitle"),
+                                sb.GetStringFromName("unlinkVerificationDescription"),
+                                flags,
+                                sb.GetStringFromName("unlinkVerificationConfirm"),
+                                null, null, null, {});
+
+    // If the user selects cancel, just bail
+    if (buttonChoice == 1)
+      return;
+
+    Weave.Service.startOver();
+    this.updateWeavePrefs();
+  },
 };
 
--- a/browser/components/preferences/sync.xul
+++ b/browser/components/preferences/sync.xul
@@ -31,16 +31,40 @@
     </preferences>
 
 
     <script type="application/javascript"
             src="chrome://browser/content/preferences/sync.js"/>
     <script type="application/javascript"
             src="chrome://browser/content/sync/utils.js"/>
 
+      <vbox id="sync-migration" flex="1" hidden="true">
+
+        <deck id="sync-migration-deck">
+          <!-- When we are in the "need FxA user" state -->
+          <hbox align="center">
+            <description id="sync-migrate-upgrade-description" flex="1"/>
+            <spacer flex="1"/>
+            <button id="sync-migrate-unlink"
+                    onclick="event.stopPropagation(); gSyncPane.startOverMigration();"/>
+            <button id="sync-migrate-upgrade"
+                    onclick="event.stopPropagation(); gSyncPane.migrateUpgrade();"/>
+          </hbox>
+
+          <!-- When we are in the "need the user to be verified" state -->
+          <hbox align="center">
+            <description id="sync-migrate-verify-description" flex="1"/>
+            <spacer flex="1"/>
+            <button id="sync-migrate-forget"
+                    onclick="event.stopPropagation(); gSyncPane.migrateForget();"/>
+            <button id="sync-migrate-resend"
+                    onclick="event.stopPropagation(); gSyncPane.migrateResend();"/>
+          </hbox>
+        </deck>
+      </vbox>
 
       <deck id="weavePrefsDeck">
 
         <!-- These panels are for the "legacy" sync provider -->
         <vbox id="noAccount" align="center">
           <spacer flex="1"/>
           <description id="syncDesc">
             &weaveDesc.label;
--- a/browser/devtools/fontinspector/font-inspector.js
+++ b/browser/devtools/fontinspector/font-inspector.js
@@ -93,18 +93,19 @@ FontInspector.prototype = {
         !this.inspector.selection.isConnected() ||
         !this.inspector.selection.isElementNode() ||
         this.chromeDoc.body.classList.contains("dim")) {
       return;
     }
 
     this.chromeDoc.querySelector("#all-fonts").innerHTML = "";
 
-    let fillStyle = (Services.prefs.getCharPref("devtools.theme") == "light") ?
-        "black" : "white";
+    // Assume light theme colors as the default (see also bug 1118179).
+    let fillStyle = (Services.prefs.getCharPref("devtools.theme") == "dark") ?
+        "white" : "black";
     let options = {
       includePreviews: true,
       previewFillStyle: fillStyle
     }
     let fonts = [];
     if (showAllFonts){
       fonts = yield this.pageStyle.getAllUsedFontFaces(options)
                       .then(null, console.error);
--- a/browser/devtools/performance/performance-controller.js
+++ b/browser/devtools/performance/performance-controller.js
@@ -28,16 +28,18 @@ devtools.lazyRequireGetter(this, "Memory
 devtools.lazyRequireGetter(this, "Waterfall",
   "devtools/timeline/waterfall", true);
 devtools.lazyRequireGetter(this, "MarkerDetails",
   "devtools/timeline/marker-details", true);
 devtools.lazyRequireGetter(this, "CallView",
   "devtools/profiler/tree-view", true);
 devtools.lazyRequireGetter(this, "ThreadNode",
   "devtools/profiler/tree-model", true);
+devtools.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
+  "devtools/timeline/global", true);
 
 devtools.lazyImporter(this, "CanvasGraphUtils",
   "resource:///modules/devtools/Graphs.jsm");
 devtools.lazyImporter(this, "LineGraphWidget",
   "resource:///modules/devtools/Graphs.jsm");
 
 // Events emitted by various objects in the panel.
 const EVENTS = {
--- a/browser/devtools/performance/views/details-waterfall.js
+++ b/browser/devtools/performance/views/details-waterfall.js
@@ -11,17 +11,17 @@ let WaterfallView = {
    * Sets up the view with event binding.
    */
   initialize: Task.async(function *() {
     this._onRecordingStarted = this._onRecordingStarted.bind(this);
     this._onRecordingStopped = this._onRecordingStopped.bind(this);
     this._onMarkerSelected = this._onMarkerSelected.bind(this);
     this._onResize = this._onResize.bind(this);
 
-    this.graph = new Waterfall($("#waterfall-graph"), $("#details-pane"));
+    this.graph = new Waterfall($("#waterfall-graph"), $("#details-pane"), TIMELINE_BLUEPRINT);
     this.markerDetails = new MarkerDetails($("#waterfall-details"), $("#waterfall-view > splitter"));
 
     this.graph.on("selected", this._onMarkerSelected);
     this.graph.on("unselected", this._onMarkerSelected);
     this.markerDetails.on("resize", this._onResize);
 
     PerformanceController.on(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
     PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
--- a/browser/devtools/performance/views/overview.js
+++ b/browser/devtools/performance/views/overview.js
@@ -75,17 +75,17 @@ let OverviewView = {
     this.framerateGraph.fixedHeight = FRAMERATE_GRAPH_HEIGHT;
     yield this.framerateGraph.ready();
   }),
 
   /**
    * Sets up the markers overivew graph.
    */
   _showMarkersGraph: Task.async(function *() {
-    this.markersOverview = new MarkersOverview($("#markers-overview"));
+    this.markersOverview = new MarkersOverview($("#markers-overview"), TIMELINE_BLUEPRINT);
     this.markersOverview.headerHeight = MARKERS_GRAPH_HEADER_HEIGHT;
     this.markersOverview.bodyHeight = MARKERS_GRAPH_BODY_HEIGHT;
     this.markersOverview.groupPadding = MARKERS_GROUP_VERTICAL_PADDING;
     yield this.markersOverview.ready();
 
     CanvasGraphUtils.linkAnimation(this.framerateGraph, this.markersOverview);
     CanvasGraphUtils.linkSelection(this.framerateGraph, this.markersOverview);
   }),
--- a/browser/devtools/timeline/widgets/waterfall.js
+++ b/browser/devtools/timeline/widgets/waterfall.js
@@ -70,17 +70,17 @@ function Waterfall(parent, container, bl
   this._parent.appendChild(this._listContents);
 
   this.setupKeys();
 
   this._isRTL = this._getRTL();
 
   // Lazy require is a bit slow, and these are hot objects.
   this._l10n = L10N;
-  this._blueprint = blueprint
+  this._blueprint = blueprint;
   this._setNamedTimeout = setNamedTimeout;
   this._clearNamedTimeout = clearNamedTimeout;
 
   // Selected row index. By default, we want the first
   // row to be selected.
   this._selectedRowIdx = 0;
 
   // Default rowCount
--- a/browser/themes/linux/preferences/preferences.css
+++ b/browser/themes/linux/preferences/preferences.css
@@ -184,9 +184,30 @@ label.small {
   margin: 5px;
   line-height: 1.2em;
 }
 
 #noFxaAccount > label:first-child {
   margin-bottom: 0.6em;
 }
 
+/**
+ * Sync migration
+ */
+#sync-migration {
+  border: 1px solid rgba(0, 0, 0, 0.32);
+  background-color: InfoBackground;
+  color: InfoText;
+  text-shadow: none;
+  margin: 5px 0 0 0;
+  animation: fadein 3000ms;
+}
+
+#sync-migration description {
+  margin: 8px;
+}
+
+@keyframes fadein {
+  from { opacity: 0; }
+  to   { opacity: 1; }
+}
+
 %endif
--- a/browser/themes/osx/preferences/preferences.css
+++ b/browser/themes/osx/preferences/preferences.css
@@ -245,9 +245,30 @@ html|a.inline-link:-moz-focusring {
   margin: 12px 4px;
   line-height: 1.2em;
 }
 
 #noFxaAccount > label:first-child {
   margin-bottom: 0.6em;
 }
 
+/**
+ * Sync migration
+ */
+#sync-migration {
+  border: 1px solid rgba(0, 0, 0, 0.32);
+  background-color: InfoBackground;
+  color: InfoText;
+  text-shadow: none;
+  margin: 5px 0 0 0;
+  animation: fadein 3000ms;
+}
+
+#sync-migration description {
+  margin: 8px;
+}
+
+@keyframes fadein {
+  from { opacity: 0; }
+  to   { opacity: 1; }
+}
+
 %endif
--- a/browser/themes/windows/preferences/preferences.css
+++ b/browser/themes/windows/preferences/preferences.css
@@ -171,9 +171,30 @@ label.small {
   margin: 6px;
   line-height: 1.2em;
 }
 
 #noFxaAccount > label:first-child {
   margin-bottom: 0.6em;
 }
 
+/**
+ * Sync migration
+ */
+#sync-migration {
+  border: 1px solid rgba(0, 0, 0, 0.32);
+  background-color: InfoBackground;
+  color: InfoText;
+  text-shadow: none;
+  margin: 5px 0 0 0;
+  animation: fadein 3000ms;
+}
+
+#sync-migration description {
+  margin: 8px;
+}
+
+@keyframes fadein {
+  from { opacity: 0; }
+  to   { opacity: 1; }
+}
+
 %endif
--- a/configure.in
+++ b/configure.in
@@ -1877,26 +1877,16 @@ case "$host" in
     ;;
 
 *)
     HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O2}"
     ;;
 esac
 
-dnl Check for using a custom <inttypes.h> implementation
-dnl ========================================================
-AC_MSG_CHECKING(for custom <inttypes.h> implementation)
-if test "$MOZ_CUSTOM_INTTYPES_H"; then
-  AC_DEFINE_UNQUOTED(MOZ_CUSTOM_INTTYPES_H, "$MOZ_CUSTOM_INTTYPES_H")
-  AC_MSG_RESULT(using $MOZ_CUSTOM_INTTYPES_H)
-else
-  AC_MSG_RESULT(none specified)
-fi
-
 dnl Get mozilla version from central milestone file
 MOZILLA_VERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir`
 MOZILLA_UAVERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir -uaversion`
 MOZILLA_SYMBOLVERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir -symbolversion`
 
 dnl Get version of various core apps from the version files.
 FIREFOX_VERSION=`cat $_topsrcdir/browser/config/version.txt`
 
--- a/dom/animation/AnimationPlayer.cpp
+++ b/dom/animation/AnimationPlayer.cpp
@@ -128,59 +128,61 @@ AnimationPlayer::SetSource(Animation* aS
   if (mSource) {
     mSource->SetParentTime(GetCurrentTime());
   }
 }
 
 void
 AnimationPlayer::Tick()
 {
-  // FIXME (bug 1112969): Check if we are pending but have lost access to the
-  // pending player tracker. If that's the case we should probably trigger the
-  // animation now.
+  // Since we are not guaranteed to get only one call per refresh driver tick,
+  // it's possible that mPendingReadyTime is set to a time in the future.
+  // In that case, we should wait until the next refresh driver tick before
+  // resuming.
+  if (mIsPending &&
+      !mPendingReadyTime.IsNull() &&
+      mPendingReadyTime.Value() <= mTimeline->GetCurrentTime().Value()) {
+    ResumeAt(mPendingReadyTime.Value());
+    mPendingReadyTime.SetNull();
+  }
+
+  if (IsPossiblyOrphanedPendingPlayer()) {
+    MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
+               "Orphaned pending players should have an active timeline");
+    ResumeAt(mTimeline->GetCurrentTime().Value());
+  }
 
   UpdateSourceContent();
 }
 
 void
+AnimationPlayer::StartOnNextTick(const Nullable<TimeDuration>& aReadyTime)
+{
+  // Normally we expect the play state to be pending but it's possible that,
+  // due to the handling of possibly orphaned players in Tick() [coming
+  // in a later patch in this series], this player got started whilst still
+  // being in another document's pending player map.
+  if (PlayState() != AnimationPlayState::Pending) {
+    return;
+  }
+
+  // If aReadyTime.IsNull() we'll detect this in Tick() where we check for
+  // orphaned players and trigger this animation anyway
+  mPendingReadyTime = aReadyTime;
+}
+
+void
 AnimationPlayer::StartNow()
 {
-  // This method is only expected to be called for an animation that is
-  // waiting to play. We can easily adapt it to handle other states
-  // but it's currently not necessary.
   MOZ_ASSERT(PlayState() == AnimationPlayState::Pending,
              "Expected to start a pending player");
-  MOZ_ASSERT(!mHoldTime.IsNull(),
-             "A player in the pending state should have a resolved hold time");
-
-  Nullable<TimeDuration> readyTime = mTimeline->GetCurrentTime();
+  MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
+             "Expected an active timeline");
 
-  // FIXME (bug 1096776): If readyTime.IsNull(), we should return early here.
-  // This will leave mIsPending = true but the caller will remove us from the
-  // PendingPlayerTracker if we were added there.
-  // Then, in Tick(), if we have:
-  // - a resolved timeline, and
-  // - mIsPending = true, and
-  // - *no* document or we are *not* in the PendingPlayerTracker
-  // then we should call StartNow.
-  //
-  // For now, however, we don't support inactive/missing timelines so
-  // |readyTime| should be resolved.
-  MOZ_ASSERT(!readyTime.IsNull(), "Missing or inactive timeline");
-
-  mStartTime.SetValue(readyTime.Value() - mHoldTime.Value());
-  mHoldTime.SetNull();
-  mIsPending = false;
-
-  UpdateSourceContent();
-  PostUpdate();
-
-  if (mReady) {
-    mReady->MaybeResolve(this);
-  }
+  ResumeAt(mTimeline->GetCurrentTime().Value());
 }
 
 void
 AnimationPlayer::Cancel()
 {
   if (mIsPending) {
     CancelPendingPlay();
     if (mReady) {
@@ -265,24 +267,17 @@ AnimationPlayer::DoPlay()
 
   // Clear ready promise. We'll create a new one lazily.
   mReady = nullptr;
 
   mIsPending = true;
 
   nsIDocument* doc = GetRenderedDocument();
   if (!doc) {
-    // If we have no rendered document (e.g. because the source content's
-    // target element is orphaned), then treat the animation as ready and
-    // start it immediately. It is probably preferable to make playing
-    // *always* asynchronous (e.g. by setting some additional state that
-    // marks this player as pending and queueing a runnable to resolve the
-    // start time). That situation, however, is currently rare enough that
-    // we don't bother for now.
-    StartNow();
+    StartOnNextTick(Nullable<TimeDuration>());
     return;
   }
 
   PendingPlayerTracker* tracker = doc->GetOrCreatePendingPlayerTracker();
   tracker->AddPlayPending(*this);
 
   // We may have updated the current time when we set the hold time above
   // so notify source content.
@@ -309,16 +304,38 @@ AnimationPlayer::DoPause()
   mIsRunningOnCompositor = false;
 
   // Bug 1109390 - check for null result here and go to pending state
   mHoldTime = GetCurrentTime();
   mStartTime.SetNull();
 }
 
 void
+AnimationPlayer::ResumeAt(const TimeDuration& aResumeTime)
+{
+  // This method is only expected to be called for a player that is
+  // waiting to play. We can easily adapt it to handle other states
+  // but it's currently not necessary.
+  MOZ_ASSERT(PlayState() == AnimationPlayState::Pending,
+             "Expected to resume a pending player");
+  MOZ_ASSERT(!mHoldTime.IsNull(),
+             "A player in the pending state should have a resolved hold time");
+
+  mStartTime.SetValue(aResumeTime - mHoldTime.Value());
+  mHoldTime.SetNull();
+  mIsPending = false;
+
+  UpdateSourceContent();
+
+  if (mReady) {
+    mReady->MaybeResolve(this);
+  }
+}
+
+void
 AnimationPlayer::UpdateSourceContent()
 {
   if (mSource) {
     mSource->SetParentTime(GetCurrentTime());
   }
 }
 
 void
@@ -350,16 +367,66 @@ AnimationPlayer::CancelPendingPlay()
   if (doc) {
     PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
     if (tracker) {
       tracker->RemovePlayPending(*this);
     }
   }
 
   mIsPending = false;
+  mPendingReadyTime.SetNull();
+}
+
+bool
+AnimationPlayer::IsPossiblyOrphanedPendingPlayer() const
+{
+  // Check if we are pending but might never start because we are not being
+  // tracked.
+  //
+  // This covers the following cases:
+  //
+  // * We started playing but our source content's target element was orphaned
+  //   or bound to a different document.
+  //   (note that for the case of our source content changing we should handle
+  //   that in SetSource)
+  // * We started playing but our timeline became inactive.
+  //   In this case the pending player tracker will drop us from its hashmap
+  //   when we have been painted.
+  // * When we started playing we couldn't find a PendingPlayerTracker to
+  //   register with (perhaps the source content had no document) so we simply
+  //   set mIsPending in DoPlay and relied on this method to catch us on the
+  //   next tick.
+
+  // If we're not pending we're ok.
+  if (!mIsPending) {
+    return false;
+  }
+
+  // If we have a pending ready time then we will be started on the next
+  // tick.
+  if (!mPendingReadyTime.IsNull()) {
+    return false;
+  }
+
+  // If we don't have an active timeline then we shouldn't start until
+  // we do.
+  if (!mTimeline || mTimeline->GetCurrentTime().IsNull()) {
+    return false;
+  }
+
+  // If we have no rendered document, or we're not in our rendered document's
+  // PendingPlayerTracker then there's a good chance no one is tracking us.
+  //
+  // If we're wrong and another document is tracking us then, at worst, we'll
+  // simply start the animation one tick too soon. That's better than never
+  // starting the animation and is unlikely.
+  nsIDocument* doc = GetRenderedDocument();
+  return !doc ||
+         !doc->GetPendingPlayerTracker() ||
+         !doc->GetPendingPlayerTracker()->IsWaitingToPlay(*this);
 }
 
 StickyTimeDuration
 AnimationPlayer::SourceContentEnd() const
 {
   if (!mSource) {
     return StickyTimeDuration(0);
   }
--- a/dom/animation/AnimationPlayer.h
+++ b/dom/animation/AnimationPlayer.h
@@ -91,37 +91,69 @@ public:
   // in future we will likely have to flush style in
   // CSSAnimationPlayer::PauseFromJS so we leave it for now.
   void PauseFromJS() { Pause(); }
 
   void SetSource(Animation* aSource);
   void Tick();
 
   /**
-   * Sets the start time of a player that is waiting to play to the current
-   * time of its timeline.
-   *
-   * This will reset the pending flag if the call succeeded. The caller is
-   * responsible for removing the player from the PendingPlayerTracker though.
-   *
    * Typically, when a player is played, it does not start immediately but is
    * added to a table of pending players on the document of its source content.
-   * In the meantime it sets its hold time to the time from which should
-   * begin playback.
+   * In the meantime it sets its hold time to the time from which playback
+   * should begin.
    *
    * When the document finishes painting, any pending players in its table
-   * are started by calling this method.
+   * are marked as being ready to start by calling StartOnNextTick.
+   * The moment when the paint completed is also recorded, converted to a
+   * timeline time, and passed to StartOnTick. This is so that when these
+   * players do start, they can be timed from the point when painting
+   * completed.
+   *
+   * After calling StartOnNextTick, players remain in the pending state until
+   * the next refresh driver tick. At that time they transition out of the
+   * pending state using the time passed to StartOnNextTick as the effective
+   * time at which they resumed.
    *
    * This approach means that any setup time required for performing the
    * initial paint of an animation such as layerization is not deducted from
    * the running time of the animation. Without this we can easily drop the
    * first few frames of an animation, or, on slower devices, the whole
    * animation.
+   *
+   * Furthermore:
+   *
+   * - Starting the player immediately when painting finishes is problematic
+   *   because the start time of the player will be ahead of its timeline
+   *   (since the timeline time is based on the refresh driver time).
+   *   That's a problem because the player is playing but its timing suggests
+   *   it starts in the future. We could update the timeline to match the start
+   *   time of the player but then we'd also have to update the timing and style
+   *   of all animations connected to that timeline or else be stuck in an
+   *   inconsistent state until the next refresh driver tick.
+   *
+   * - If we simply use the refresh driver time on its next tick, the lag
+   *   between triggering an animation and its effective start is unacceptably
+   *   long.
+   *
+   * Note that the caller of this method is responsible for removing the player
+   * from any PendingPlayerTracker it may have been added to.
    */
+  void StartOnNextTick(const Nullable<TimeDuration>& aReadyTime);
+
+  // Testing only: Start a pending player using the current timeline time.
+  // This is used to support existing tests that expect animations to begin
+  // immediately. Ideally we would rewrite the those tests and get rid of this
+  // method, but there are a lot of them.
+  //
+  // As with StartOnNextTick, the caller of this method is responsible for
+  // removing the player from any PendingPlayerTracker it may have been added
+  // to.
   void StartNow();
+
   void Cancel();
 
   const nsString& Name() const {
     return mSource ? mSource->Name() : EmptyString();
   }
 
   bool IsPaused() const { return PlayState() == AnimationPlayState::Paused; }
   bool IsRunning() const;
@@ -150,36 +182,40 @@ public:
   // is running and has source content to sample).
   void ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
                     nsCSSPropertySet& aSetProperties,
                     bool& aNeedsRefreshes);
 
 protected:
   void DoPlay();
   void DoPause();
+  void ResumeAt(const TimeDuration& aResumeTime);
 
   void UpdateSourceContent();
   void FlushStyle() const;
   void PostUpdate();
   // Remove this player from the pending player tracker and resets mIsPending
   // as necessary. The caller is responsible for resolving or aborting the
   // mReady promise as necessary.
   void CancelPendingPlay();
+
+  bool IsPossiblyOrphanedPendingPlayer() const;
   StickyTimeDuration SourceContentEnd() const;
 
   nsIDocument* GetRenderedDocument() const;
   nsPresContext* GetPresContext() const;
   virtual css::CommonAnimationManager* GetAnimationManager() const = 0;
   AnimationPlayerCollection* GetCollection() const;
 
   nsRefPtr<AnimationTimeline> mTimeline;
   nsRefPtr<Animation> mSource;
   // The beginning of the delay period.
   Nullable<TimeDuration> mStartTime; // Timeline timescale
   Nullable<TimeDuration> mHoldTime;  // Player timescale
+  Nullable<TimeDuration> mPendingReadyTime; // Timeline timescale
 
   // A Promise that is replaced on each call to Play() (and in future Pause())
   // and fulfilled when Play() is successfully completed.
   // This object is lazily created by GetReady.
   nsRefPtr<Promise> mReady;
 
   // Indicates if the player is in the pending state. We use this rather
   // than checking if this player is tracked by a PendingPlayerTracker.
--- a/dom/animation/AnimationTimeline.cpp
+++ b/dom/animation/AnimationTimeline.cpp
@@ -33,49 +33,16 @@ AnimationTimeline::GetCurrentTime() cons
 }
 
 Nullable<double>
 AnimationTimeline::GetCurrentTimeAsDouble() const
 {
   return AnimationUtils::TimeDurationToDouble(GetCurrentTime());
 }
 
-void
-AnimationTimeline::FastForward(const TimeStamp& aTimeStamp)
-{
-  // If we have already been fast-forwarded to an equally or more
-  // recent time, ignore this call.
-  if (!mFastForwardTime.IsNull() && aTimeStamp <= mFastForwardTime) {
-    return;
-  }
-
-  // If the refresh driver is under test control then its values have little
-  // connection to TimeStamp values and it doesn't make sense to fast-forward
-  // the timeline to a TimeStamp value.
-  //
-  // Furthermore, when the refresh driver is under test control,
-  // nsDOMWindowUtils::AdvanceTimeAndRefresh automatically starts any
-  // pending animation players so we don't need to fast-forward the timeline
-  // anyway.
-  nsRefreshDriver* refreshDriver = GetRefreshDriver();
-  if (refreshDriver && refreshDriver->IsTestControllingRefreshesEnabled()) {
-    return;
-  }
-
-  MOZ_ASSERT(!refreshDriver || aTimeStamp >= refreshDriver->MostRecentRefresh(),
-             "aTimeStamp must be >= the refresh driver time");
-
-  // FIXME: For all animations attached to this timeline, we should mark
-  // their target elements as needing restyling. Otherwise, tasks that run
-  // in between now and the next refresh driver tick might see inconsistencies
-  // between the timing of an animation and the computed style of its target.
-
-  mFastForwardTime = aTimeStamp;
-}
-
 TimeStamp
 AnimationTimeline::GetCurrentTimeStamp() const
 {
   nsRefreshDriver* refreshDriver = GetRefreshDriver();
   TimeStamp refreshTime = refreshDriver
                           ? refreshDriver->MostRecentRefresh()
                           : TimeStamp();
 
@@ -92,45 +59,16 @@ AnimationTimeline::GetCurrentTimeStamp()
       result = timing->GetNavigationStartTimeStamp();
       // Also, let this time represent the current refresh time. This way
       // we'll save it as the last refresh time and skip looking up
       // navigation timing each time.
       refreshTime = result;
     }
   }
 
-  // The timeline may have been fast-forwarded to account for animations
-  // that begin playing between ticks of the refresh driver. If so, we should
-  // use the fast-forward time unless we've already gone past that time.
-  //
-  // (If the refresh driver were ever to go backwards then we would need to
-  //  ignore the fast-forward time in that case to prevent the timeline getting
-  //  "stuck" until the refresh driver caught up. However, the only time the
-  //  refresh driver goes backwards is when it is restored from test control
-  //  and FastForward makes sure we don't set the fast foward time when we
-  //  are under test control.)
-  MOZ_ASSERT(refreshTime.IsNull() || mLastRefreshDriverTime.IsNull() ||
-             refreshTime >= mLastRefreshDriverTime ||
-             mFastForwardTime.IsNull(),
-             "The refresh driver time should not go backwards when the"
-             " fast-forward time is set");
-
-  // We need to check if mFastForwardTime is ahead of the refresh driver
-  // time. This is because mFastForwardTime can still be set after the next
-  // refresh driver tick since we don't clear mFastForwardTime on a call to
-  // Tick() as we aren't currently guaranteed to get only one call to Tick()
-  // per refresh-driver tick.
-  if (result.IsNull() ||
-       (!mFastForwardTime.IsNull() && mFastForwardTime > result)) {
-    result = mFastForwardTime;
-  } else {
-    // Make sure we continue to ignore the fast-forward time.
-    mFastForwardTime = TimeStamp();
-  }
-
   if (!refreshTime.IsNull()) {
     mLastRefreshDriverTime = refreshTime;
   }
 
   return result;
 }
 
 Nullable<TimeDuration>
--- a/dom/animation/AnimationTimeline.h
+++ b/dom/animation/AnimationTimeline.h
@@ -7,19 +7,19 @@
 #define mozilla_dom_AnimationTimeline_h
 
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/TimeStamp.h"
 #include "js/TypeDecls.h"
 #include "nsIDocument.h"
+#include "nsRefreshDriver.h"
 
 struct JSContext;
-class nsRefreshDriver;
 
 namespace mozilla {
 namespace dom {
 
 class AnimationTimeline MOZ_FINAL : public nsWrapperCache
 {
 public:
   explicit AnimationTimeline(nsIDocument* aDocument)
@@ -42,47 +42,43 @@ public:
 
   // AnimationTimeline methods
   Nullable<TimeDuration> GetCurrentTime() const;
 
   // Wrapper functions for AnimationTimeline DOM methods when called from
   // script.
   Nullable<double> GetCurrentTimeAsDouble() const;
 
+  // Converts a TimeStamp to the equivalent value in timeline time.
+  // Note that when IsUnderTestControl() is true, there is no correspondence
+  // between timeline time and wallclock time. In such a case, passing a
+  // timestamp from TimeStamp::Now() to this method will not return a
+  // meaningful result.
   Nullable<TimeDuration> ToTimelineTime(const TimeStamp& aTimeStamp) const;
   TimeStamp ToTimeStamp(const TimeDuration& aTimelineTime) const;
 
-  // Force the timeline to advance to |aTimeStamp|.
-  //
-  // Normally the timeline uses the refresh driver time but when we have
-  // animations that are timed from when their first frame is rendered we need
-  // to bring the timeline forward to that moment. If we don't, calling
-  // IsRunning() will incorrectly return false (because GetCurrentTime() will
-  // return a negative time) until the next refresh driver tick causes the
-  // timeline to catch up.
-  //
-  // |aTimeStamp| must be greater or equal to the current refresh driver
-  // time for the document with which this timeline is associated unless the
-  // refresh driver is under test control, in which case this method will
-  // be a no-op.
-  void FastForward(const TimeStamp& aTimeStamp);
-
   nsRefreshDriver* GetRefreshDriver() const;
+  // Returns true if this timeline is driven by a refresh driver that is
+  // under test control. In such a case, there is no correspondence between
+  // TimeStamp values returned by the refresh driver and wallclock time.
+  // As a result, passing a value from TimeStamp::Now() to ToTimelineTime()
+  // would not return a meaningful result.
+  bool IsUnderTestControl() const
+  {
+    nsRefreshDriver* refreshDriver = GetRefreshDriver();
+    return refreshDriver && refreshDriver->IsTestControllingRefreshesEnabled();
+  }
 
 protected:
   TimeStamp GetCurrentTimeStamp() const;
 
   nsCOMPtr<nsIDocument> mDocument;
 
   // The most recently used refresh driver time. This is used in cases where
   // we don't have a refresh driver (e.g. because we are in a display:none
   // iframe).
   mutable TimeStamp mLastRefreshDriverTime;
-
-  // The time to which the timeline has been forced-to in order to account for
-  // animations that are started in-between frames.
-  mutable TimeStamp mFastForwardTime;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_AnimationTimeline_h
--- a/dom/animation/PendingPlayerTracker.cpp
+++ b/dom/animation/PendingPlayerTracker.cpp
@@ -41,40 +41,52 @@ PendingPlayerTracker::IsWaitingToPlay(do
   return mPlayPendingSet.Contains(const_cast<dom::AnimationPlayer*>(&aPlayer));
 }
 
 PLDHashOperator
 StartPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
                   void* aReadyTime)
 {
   dom::AnimationPlayer* player = aKey->GetKey();
+  dom::AnimationTimeline* timeline = player->Timeline();
 
-  // For animations that are waiting until their first frame has rendered
-  // before starting, we record the moment when they finish painting
-  // as the "ready time" and make any pending layer animations start at
-  // that time.
-  //
-  // Here we fast-forward the player's timeline to the same "ready time" and
-  // then tell the player to start at the timeline's current time.
-  //
-  // Redundant calls to FastForward with the same ready time are ignored by
-  // AnimationTimeline.
-  dom::AnimationTimeline* timeline = player->Timeline();
-  timeline->FastForward(*static_cast<const TimeStamp*>(aReadyTime));
+  // When the timeline's refresh driver is under test control, its values
+  // have no correspondance to wallclock times so we shouldn't try to convert
+  // aReadyTime (which is a wallclock time) to a timeline value. Instead, the
+  // animation player will be started when the refresh driver is next
+  // advanced since this will trigger a call to StartPendingPlayersNow.
+  if (timeline->IsUnderTestControl()) {
+    return PL_DHASH_NEXT;
+  }
+
+  Nullable<TimeDuration> readyTime =
+    timeline->ToTimelineTime(*static_cast<const TimeStamp*>(aReadyTime));
+  player->StartOnNextTick(readyTime);
 
-  player->StartNow();
+  return PL_DHASH_REMOVE;
+}
 
+void
+PendingPlayerTracker::StartPendingPlayersOnNextTick(const TimeStamp& aReadyTime)
+{
+  mPlayPendingSet.EnumerateEntries(StartPlayerAtTime,
+                                   const_cast<TimeStamp*>(&aReadyTime));
+}
+
+PLDHashOperator
+StartPlayerNow(nsRefPtrHashKey<dom::AnimationPlayer>* aKey, void*)
+{
+  aKey->GetKey()->StartNow();
   return PL_DHASH_NEXT;
 }
 
 void
-PendingPlayerTracker::StartPendingPlayers(const TimeStamp& aReadyTime)
+PendingPlayerTracker::StartPendingPlayersNow()
 {
-  mPlayPendingSet.EnumerateEntries(StartPlayerAtTime,
-                                   const_cast<TimeStamp*>(&aReadyTime));
+  mPlayPendingSet.EnumerateEntries(StartPlayerNow, nullptr);
   mPlayPendingSet.Clear();
 }
 
 void
 PendingPlayerTracker::EnsurePaintIsScheduled()
 {
   if (!mDocument) {
     return;
--- a/dom/animation/PendingPlayerTracker.h
+++ b/dom/animation/PendingPlayerTracker.h
@@ -24,19 +24,18 @@ public:
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PendingPlayerTracker)
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PendingPlayerTracker)
 
   void AddPlayPending(dom::AnimationPlayer& aPlayer);
   void RemovePlayPending(dom::AnimationPlayer& aPlayer);
   bool IsWaitingToPlay(dom::AnimationPlayer const& aPlayer) const;
 
-  // Causes any pending players to resume at |aReadyTime| by first
-  // fast-forwarding their timeline to the corresponding time.
-  void StartPendingPlayers(const TimeStamp& aReadyTime);
+  void StartPendingPlayersOnNextTick(const TimeStamp& aReadyTime);
+  void StartPendingPlayersNow();
   bool HasPendingPlayers() const { return mPlayPendingSet.Count() > 0; }
 
 private:
   ~PendingPlayerTracker() { }
 
   void EnsurePaintIsScheduled();
 
   typedef nsTHashtable<nsRefPtrHashKey<dom::AnimationPlayer>>
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -2,23 +2,21 @@
 support-files =
   testcommon.js
 
 [animation-timeline/test_animation-timeline.html]
 skip-if = buildapp == 'mulet'
 [css-animations/test_animations-dynamic-changes.html]
 [css-animations/test_animation-effect-name.html]
 [css-animations/test_animation-pausing.html]
-skip-if = os == "win" || (os == "mac" && os_version == "10.8") # disabled until bug 1112480 lands
 [css-animations/test_animation-player-playstate.html]
 [css-animations/test_animation-player-ready.html]
 [css-animations/test_animation-target.html]
 [css-animations/test_element-get-animation-players.html]
 skip-if = buildapp == 'mulet'
 [css-transitions/test_animation-effect-name.html]
 [css-transitions/test_animation-pausing.html]
-skip-if = os == "win" # bug 1117955, to be restored in bug 1112480
 [css-transitions/test_animation-player-ready.html]
 [css-transitions/test_animation-target.html]
 [css-transitions/test_element-get-animation-players.html]
 skip-if = buildapp == 'mulet'
 [mozilla/test_deferred_start.html]
 skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') # bug 1113425
--- a/dom/animation/test/mozilla/test_deferred_start.html
+++ b/dom/animation/test/mozilla/test_deferred_start.html
@@ -55,28 +55,31 @@ async_test(function(t) {
     var player = div.getAnimationPlayers()[0];
 
     player.ready.then(function() {
       promiseCallbackDone = true;
     }).catch(function() {
       assert_unreached('ready promise was rejected');
     });
 
-  }).then(waitForFrame).then(t.step_func(function() {
+  // We need to wait for up to two frames since the animation may not start
+  // until the beginning of the next refresh driver tick and it won't queue
+  // the ready Promise callback until that point.
+  }).then(waitForFrame).then(waitForFrame).then(t.step_func(function() {
     assert_true(promiseCallbackDone,
                 'ready promise callback was called before the next'
                 + ' requestAnimationFrame callback');
     t.done();
   }));
 }, 'AnimationPlayer.ready is resolved for an empty animation');
 
 // Test that compositor animations with delays get synced correctly
 //
 // NOTE: It is important that we DON'T use
-// SpecialWindows.DOMWindowUtils.advanceTimeAndRefresh here since that takes
+// SpecialPowers.DOMWindowUtils.advanceTimeAndRefresh here since that takes
 // us through a different code path.
 async_test(function(t) {
   // This test only applies to compositor animations
   const OMTAPrefKey = 'layers.offmainthreadcomposition.async-animations';
   var omtaEnabled = SpecialPowers.DOMWindowUtils.layerManagerRemote &&
                     SpecialPowers.getBoolPref(OMTAPrefKey);
   if (!omtaEnabled) {
     t.done();
--- a/dom/base/DOMCursor.h
+++ b/dom/base/DOMCursor.h
@@ -37,22 +37,22 @@ public:
 
   void Reset();
   void FireDone();
 
 protected:
   ~DOMCursor() {}
 
 private:
-  DOMCursor() MOZ_DELETE;
+  DOMCursor() = delete;
   // Calling Then() on DOMCursor is a mistake, since the DOMCursor object
   // should not have a .then() method from JS' point of view.
   already_AddRefed<mozilla::dom::Promise>
   Then(JSContext* aCx, AnyCallback* aResolveCallback,
-       AnyCallback* aRejectCallback, ErrorResult& aRv) MOZ_DELETE;
+       AnyCallback* aRejectCallback, ErrorResult& aRv) = delete;
 
   nsCOMPtr<nsICursorContinueCallback> mCallback;
   bool mFinished;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/base/DOMMatrix.h
+++ b/dom/base/DOMMatrix.h
@@ -129,19 +129,19 @@ protected:
   nsCOMPtr<nsISupports>     mParent;
   nsAutoPtr<gfx::Matrix>    mMatrix2D;
   nsAutoPtr<gfx::Matrix4x4> mMatrix3D;
 
   ~DOMMatrixReadOnly()
   {
   }
 private:
-  DOMMatrixReadOnly() MOZ_DELETE;
-  DOMMatrixReadOnly(const DOMMatrixReadOnly&) MOZ_DELETE;
-  DOMMatrixReadOnly& operator=(const DOMMatrixReadOnly&) MOZ_DELETE;
+  DOMMatrixReadOnly() = delete;
+  DOMMatrixReadOnly(const DOMMatrixReadOnly&) = delete;
+  DOMMatrixReadOnly& operator=(const DOMMatrixReadOnly&) = delete;
 };
 
 class DOMMatrix MOZ_FINAL : public DOMMatrixReadOnly
 {
 public:
   explicit DOMMatrix(nsISupports* aParent)
     : DOMMatrixReadOnly(aParent)
   {}
--- a/dom/base/NodeInfo.h
+++ b/dom/base/NodeInfo.h
@@ -201,18 +201,18 @@ public:
    * Retrieve a pointer to the document that owns this node info.
    */
   nsIDocument* GetDocument() const
   {
     return mDocument;
   }
 
 private:
-  NodeInfo() MOZ_DELETE; 
-  NodeInfo(const NodeInfo& aOther) MOZ_DELETE;
+  NodeInfo() = delete; 
+  NodeInfo(const NodeInfo& aOther) = delete;
 
   // NodeInfo is only constructed by nsNodeInfoManager which is a friend class.
   // aName and aOwnerManager may not be null.
   NodeInfo(nsIAtom* aName, nsIAtom* aPrefix, int32_t aNamespaceID,
            uint16_t aNodeType, nsIAtom* aExtraName,
            nsNodeInfoManager* aOwnerManager);
 
   ~NodeInfo();
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -307,18 +307,18 @@ private:
 
   // Track state between the old and new error reporting modes.
   bool mOwnErrorReporting;
   bool mOldAutoJSAPIOwnsErrorReporting;
   Maybe<JSErrorReporter> mOldErrorReporter;
 
   void InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread);
 
-  AutoJSAPI(const AutoJSAPI&) MOZ_DELETE;
-  AutoJSAPI& operator= (const AutoJSAPI&) MOZ_DELETE;
+  AutoJSAPI(const AutoJSAPI&) = delete;
+  AutoJSAPI& operator= (const AutoJSAPI&) = delete;
 };
 
 /*
  * A class that represents a new script entry point.
  */
 class AutoEntryScript : public AutoJSAPI,
                         protected ScriptSettingsStackEntry {
 public:
--- a/dom/base/WebSocket.h
+++ b/dom/base/WebSocket.h
@@ -153,18 +153,18 @@ private: // constructor && distructor
   // outgoing not sent messages then this method keeps the object alive
   // when js doesn't have strong references to it.
   void UpdateMustKeepAlive();
   // ATTENTION, when calling this method the object can be released
   // (and possibly collected).
   void DontKeepAliveAnyMore();
 
 private:
-  WebSocket(const WebSocket& x) MOZ_DELETE;   // prevent bad usage
-  WebSocket& operator=(const WebSocket& x) MOZ_DELETE;
+  WebSocket(const WebSocket& x) = delete;   // prevent bad usage
+  WebSocket& operator=(const WebSocket& x) = delete;
 
   void Send(nsIInputStream* aMsgStream,
             const nsACString& aMsgString,
             uint32_t aMsgLength,
             bool aIsBinary,
             ErrorResult& aRv);
 
   void AssertIsOnTargetThread() const;
--- a/dom/base/nsAttrAndChildArray.h
+++ b/dom/base/nsAttrAndChildArray.h
@@ -124,18 +124,18 @@ public:
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   bool HasMappedAttrs() const
   {
     return MappedAttrCount();
   }
 
 private:
-  nsAttrAndChildArray(const nsAttrAndChildArray& aOther) MOZ_DELETE;
-  nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) MOZ_DELETE;
+  nsAttrAndChildArray(const nsAttrAndChildArray& aOther) = delete;
+  nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) = delete;
 
   void Clear();
 
   uint32_t NonMappedAttrCount() const;
   uint32_t MappedAttrCount() const;
 
   // Returns a non-null zero-refcount object.
   nsMappedAttributes*
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -90,17 +90,17 @@ public:
 
   inline DOMHighResTimeStamp TimeStampToDOMHighRes(mozilla::TimeStamp aStamp)
   {
     mozilla::TimeDuration duration = aStamp - mNavigationStartTimeStamp;
     return duration.ToMilliseconds();
   }
 
 private:
-  nsDOMNavigationTiming(const nsDOMNavigationTiming &) MOZ_DELETE;
+  nsDOMNavigationTiming(const nsDOMNavigationTiming &) = delete;
   ~nsDOMNavigationTiming();
 
   void Clear();
 
   nsCOMPtr<nsIURI> mUnloadedURI;
   nsCOMPtr<nsIURI> mLoadedURI;
 
   nsDOMPerformanceNavigationType mNavigationType;
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2670,34 +2670,33 @@ ComputeAnimationValue(nsCSSProperty aPro
   return true;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
-  nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
-
   // Before we advance the time, we should trigger any animations that are
   // waiting to start. This is because there are many tests that call this
   // which expect animations to start immediately. Ideally, we should make
   // all these tests do an asynchronous wait on the corresponding animation
   // player's 'ready' promise before continuing. Then we could remove the
   // special handling here and the code path followed when testing would
   // more closely match the code path during regular operation. Filed as
   // bug 1112957.
   nsCOMPtr<nsIDocument> doc = GetDocument();
   if (doc) {
     PendingPlayerTracker* tracker = doc->GetPendingPlayerTracker();
     if (tracker) {
-      tracker->StartPendingPlayers(driver->MostRecentRefresh());
+      tracker->StartPendingPlayersNow();
     }
   }
 
+  nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
   driver->AdvanceTimeAndRefresh(aMilliseconds);
 
   RefPtr<LayerTransactionChild> transaction = GetLayerTransaction();
   if (transaction && transaction->IPCOpen()) {
     transaction->SendSetTestSampleTime(driver->MostRecentRefresh());
   }
 
   return NS_OK;
--- a/dom/base/test/csp/test_CSP_referrerdirective.html
+++ b/dom/base/test/csp/test_CSP_referrerdirective.html
@@ -42,17 +42,17 @@ var testData = {
   'origin':  { 'csp': "script-src * 'unsafe-inline'; referrer origin",
           'expected': {  'sameorigin': 'origin',
                         'crossorigin': 'origin',
                           'downgrade': 'origin' }},
 
   'origin-when-crossorigin':  { 'csp': "script-src * 'unsafe-inline'; referrer origin-when-crossorigin",
           'expected': {  'sameorigin': 'full',
                         'crossorigin': 'origin',
-                          'downgrade': 'none' }},
+                          'downgrade': 'origin' }},
 
   'unsafe-url':  { 'csp': "script-src * 'unsafe-inline'; referrer unsafe-url",
           'expected': {  'sameorigin': 'full',
                         'crossorigin': 'full',
                           'downgrade': 'full' }},
 
   'none':   { 'csp': "script-src * 'unsafe-inline'; referrer no-referrer",
           'expected': {  'sameorigin': 'none',
--- a/dom/base/test/test_bug704320.html
+++ b/dom/base/test/test_bug704320.html
@@ -21,144 +21,164 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 
 var testIframeUrls = [
   // HTTP to HTTP
   'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade',
   'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer',
   'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url',
   'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=origin',
+  'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-crossorigin',
   // HTTP to HTTPS
   'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade',
   'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer',
   'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url',
   'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=origin',
+  'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=origin-when-crossorigin',
   // HTTPS to HTTP
   'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=no-referrer-when-downgrade',
   'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=no-referrer',
   'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url',
   'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=origin',
+  'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=origin-when-crossorigin',
   // HTTPS to HTTPS
   'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade',
   'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer',
   'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url',
-  'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin'
+  'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin',
+  'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-crossorigin'
 ];
 
 var expectedResults = {
   // From docshell/base/nsDocShell.cpp:
   //   "If the document containing the hyperlink being audited was not retrieved
   //    over an encrypted connection and its address does not have the same
   //    origin as "ping URL", send a referrer."
   'link-ping': {
     // Same-origin
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': '',
       'origin': '',
+      'origin-when-crossorigin': '',
       'no-referrer-when-downgrade': ''
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url',
       'origin': 'http://example.com',
+      'origin-when-crossorigin': 'http://example.com',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade'
     },
     // Encrypted and not same-origin
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': '',
       'origin': '',
+      'origin-when-crossorigin': '',
       'no-referrer-when-downgrade': ''
     },
     // Encrypted
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': '',
       'origin': '',
+      'origin-when-crossorigin': '',
       'no-referrer-when-downgrade': ''
     }
   },
   // form is tested in a 2nd level iframe.
   'form': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url&type=form',
       'origin': 'http://example.com',
+      'origin-when-crossorigin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-crossorigin&type=form',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=form'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url&type=form',
       'origin': 'http://example.com',
+      'origin-when-crossorigin': 'http://example.com',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=form'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url&type=form',
       'origin': 'https://example.com',
+      'origin-when-crossorigin': 'https://example.com',
       'no-referrer-when-downgrade': ''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url&type=form',
       'origin': 'https://example.com',
+      'origin-when-crossorigin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-crossorigin&type=form',
       'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=form'
     }
   },
   // window.location is tested in a 2nd level iframe.
   'window.location': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url&type=window.location',
       'origin': 'http://example.com',
+      'origin-when-crossorigin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-crossorigin&type=window.location',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=window.location'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url&type=window.location',
       'origin': 'http://example.com',
+      'origin-when-crossorigin': 'http://example.com',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url&type=window.location',
       'origin': 'https://example.com',
+      'origin-when-crossorigin': 'https://example.com',
       'no-referrer-when-downgrade': ''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url&type=window.location',
       'origin': 'https://example.com',
+      'origin-when-crossorigin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-crossorigin&type=window.location',
       'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location'
     }
   },
   'default': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url',
       'origin': 'http://example.com',
+      'origin-when-crossorigin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-crossorigin',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url',
       'origin': 'http://example.com',
+      'origin-when-crossorigin': 'http://example.com',
       'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url',
       'origin': 'https://example.com',
+      'origin-when-crossorigin': 'https://example.com',
       'no-referrer-when-downgrade': ''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url',
       'origin': 'https://example.com',
+      'origin-when-crossorigin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-crossorigin',
       'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade'
     }
   }
 };
 
 function runit() {
   var url = 'bug704320.sjs?action=get-test-results';
   var xhr = new XMLHttpRequest();
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -166,18 +166,18 @@ public:
   }
 
   // If we ever decide to add conversion operators for optional arrays
   // like the ones Nullable has, we'll need to ensure that Maybe<> has
   // the boolean before the actual data.
 
 private:
   // Forbid copy-construction and assignment
-  Optional_base(const Optional_base& other) MOZ_DELETE;
-  const Optional_base &operator=(const Optional_base &other) MOZ_DELETE;
+  Optional_base(const Optional_base& other) = delete;
+  const Optional_base &operator=(const Optional_base &other) = delete;
 
 protected:
   Maybe<InternalType> mImpl;
 };
 
 template<typename T>
 class Optional : public Optional_base<T, T>
 {
@@ -256,19 +256,19 @@ public:
   }
 };
 
 // A specialization of Optional for JS::Value to make sure no one ever uses it.
 template<>
 class Optional<JS::Value>
 {
 private:
-  Optional() MOZ_DELETE;
+  Optional() = delete;
 
-  explicit Optional(JS::Value aValue) MOZ_DELETE;
+  explicit Optional(JS::Value aValue) = delete;
 };
 
 // A specialization of Optional for NonNull that lets us get a T& from Value()
 template<typename U> class NonNull;
 template<typename T>
 class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> >
 {
 public:
@@ -349,18 +349,18 @@ public:
   const nsAString& Value() const
   {
     MOZ_ASSERT(WasPassed());
     return *mStr;
   }
 
 private:
   // Forbid copy-construction and assignment
-  Optional(const Optional& other) MOZ_DELETE;
-  const Optional &operator=(const Optional &other) MOZ_DELETE;
+  Optional(const Optional& other) = delete;
+  const Optional &operator=(const Optional &other) = delete;
 
   bool mPassed;
   const nsAString* mStr;
 };
 
 template<class T>
 class NonNull
 {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1917,18 +1917,18 @@ struct FakeString {
 private:
   nsString::char_type* mData;
   nsString::size_type mLength;
   uint32_t mFlags;
 
   static const size_t sInlineCapacity = 64;
   nsString::char_type mInlineStorage[sInlineCapacity];
 
-  FakeString(const FakeString& other) MOZ_DELETE;
-  void operator=(const FakeString& other) MOZ_DELETE;
+  FakeString(const FakeString& other) = delete;
+  void operator=(const FakeString& other) = delete;
 
   void SetData(nsString::char_type* aData) {
     MOZ_ASSERT(mFlags == nsString::F_TERMINATED);
     mData = const_cast<nsString::char_type*>(aData);
   }
 
   // A class to use for our static asserts to ensure our object layout
   // matches that of nsString.
@@ -2057,122 +2057,122 @@ public:
 // Class used to trace sequences, with specializations for various
 // sequence types.
 template<typename T,
          bool isDictionary=IsBaseOf<DictionaryBase, T>::value,
          bool isTypedArray=IsBaseOf<AllTypedArraysBase, T>::value,
          bool isOwningUnion=IsBaseOf<AllOwningUnionBase, T>::value>
 class SequenceTracer
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 };
 
 // sequence<object> or sequence<object?>
 template<>
 class SequenceTracer<JSObject*, false, false, false>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, JSObject** objp, JSObject** end) {
     for (; objp != end; ++objp) {
       JS_CallUnbarrieredObjectTracer(trc, objp, "sequence<object>");
     }
   }
 };
 
 // sequence<any>
 template<>
 class SequenceTracer<JS::Value, false, false, false>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, JS::Value* valp, JS::Value* end) {
     for (; valp != end; ++valp) {
       JS_CallUnbarrieredValueTracer(trc, valp, "sequence<any>");
     }
   }
 };
 
 // sequence<sequence<T>>
 template<typename T>
 class SequenceTracer<Sequence<T>, false, false, false>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, Sequence<T>* seqp, Sequence<T>* end) {
     for (; seqp != end; ++seqp) {
       DoTraceSequence(trc, *seqp);
     }
   }
 };
 
 // sequence<sequence<T>> as return value
 template<typename T>
 class SequenceTracer<nsTArray<T>, false, false, false>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, nsTArray<T>* seqp, nsTArray<T>* end) {
     for (; seqp != end; ++seqp) {
       DoTraceSequence(trc, *seqp);
     }
   }
 };
 
 // sequence<someDictionary>
 template<typename T>
 class SequenceTracer<T, true, false, false>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, T* dictp, T* end) {
     for (; dictp != end; ++dictp) {
       dictp->TraceDictionary(trc);
     }
   }
 };
 
 // sequence<SomeTypedArray>
 template<typename T>
 class SequenceTracer<T, false, true, false>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, T* arrayp, T* end) {
     for (; arrayp != end; ++arrayp) {
       arrayp->TraceSelf(trc);
     }
   }
 };
 
 // sequence<SomeOwningUnion>
 template<typename T>
 class SequenceTracer<T, false, false, true>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, T* arrayp, T* end) {
     for (; arrayp != end; ++arrayp) {
       arrayp->TraceUnion(trc);
     }
   }
 };
 
 // sequence<T?> with T? being a Nullable<T>
 template<typename T>
 class SequenceTracer<Nullable<T>, false, false, false>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, Nullable<T>* seqp,
                             Nullable<T>* end) {
     for (; seqp != end; ++seqp) {
       if (!seqp->IsNull()) {
         // Pretend like we actually have a length-one sequence here so
         // we can do template instantiation correctly for T.
@@ -2202,17 +2202,17 @@ void TraceMozMap(JSTracer* trc, MozMap<T
 {
   map.EnumerateValues(TraceMozMapValue<T>, trc);
 }
 
 // sequence<MozMap>
 template<typename T>
 class SequenceTracer<MozMap<T>, false, false, false>
 {
-  explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
+  explicit SequenceTracer() = delete; // Should never be instantiated
 
 public:
   static void TraceSequence(JSTracer* trc, MozMap<T>* seqp, MozMap<T>* end) {
     for (; seqp != end; ++seqp) {
       seqp->EnumerateValues(TraceMozMapValue<T>, trc);
     }
   }
 };
@@ -3113,17 +3113,17 @@ template<class T>
 inline T*
 StrongOrRawPtr(T* aPtr)
 {
   return aPtr;
 }
 
 template<class T, template<typename> class SmartPtr, class S>
 inline void
-StrongOrRawPtr(SmartPtr<S>&& aPtr) MOZ_DELETE;
+StrongOrRawPtr(SmartPtr<S>&& aPtr) = delete;
 
 inline
 JSObject*
 GetErrorPrototype(JSContext* aCx, JS::Handle<JSObject*> aForObj)
 {
   return JS_GetErrorPrototype(aCx);
 }
 
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -126,18 +126,18 @@ private:
     mCallback = aCallback;
     if (aIncumbentGlobal) {
       mIncumbentGlobal = aIncumbentGlobal;
       mIncumbentJSGlobal = aIncumbentGlobal->GetGlobalJSObject();
     }
     mozilla::HoldJSObjects(this);
   }
 
-  CallbackObject(const CallbackObject&) MOZ_DELETE;
-  CallbackObject& operator =(const CallbackObject&) MOZ_DELETE;
+  CallbackObject(const CallbackObject&) = delete;
+  CallbackObject& operator =(const CallbackObject&) = delete;
 
 protected:
   void DropJSObjects()
   {
     MOZ_ASSERT_IF(mIncumbentJSGlobal, mCallback);
     if (mCallback) {
       mCallback = nullptr;
       mIncumbentJSGlobal = nullptr;
@@ -176,17 +176,17 @@ protected:
 
     JSContext* GetContext() const
     {
       return mCx;
     }
 
   private:
     // We better not get copy-constructed
-    CallSetup(const CallSetup&) MOZ_DELETE;
+    CallSetup(const CallSetup&) = delete;
 
     bool ShouldRethrowException(JS::Handle<JS::Value> aException);
 
     // Members which can go away whenever
     JSContext* mCx;
 
     // Caller's compartment. This will only have a sensible value if
     // mExceptionHandling == eRethrowContentExceptions.
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -9498,18 +9498,18 @@ class CGClass(CGThing):
 
         if self.disallowCopyConstruction:
             class DisallowedCopyConstructor(object):
                 def __init__(self):
                     self.visibility = "private"
 
                 def declare(self, cgClass):
                     name = cgClass.getNameString()
-                    return ("%s(const %s&) MOZ_DELETE;\n"
-                            "void operator=(const %s) MOZ_DELETE;\n" % (name, name, name))
+                    return ("%s(const %s&) = delete;\n"
+                            "void operator=(const %s) = delete;\n" % (name, name, name))
 
             disallowedCopyConstructors = [DisallowedCopyConstructor()]
         else:
             disallowedCopyConstructors = []
 
         order = [self.enums, self.unions,
                  self.typedefs, self.members,
                  self.constructors + disallowedCopyConstructors,
--- a/dom/bindings/ErrorResult.h
+++ b/dom/bindings/ErrorResult.h
@@ -153,17 +153,17 @@ private:
 #ifdef DEBUG
   // Used to keep track of codepaths that might throw JS exceptions,
   // for assertion purposes.
   bool mMightHaveUnreportedJSException;
 #endif
 
   // Not to be implemented, to make sure people always pass this by
   // reference, not by value.
-  ErrorResult(const ErrorResult&) MOZ_DELETE;
+  ErrorResult(const ErrorResult&) = delete;
 };
 
 /******************************************************************************
  ** Macros for checking results
  ******************************************************************************/
 
 #define ENSURE_SUCCESS(res, ret)                                          \
   do {                                                                    \
--- a/dom/bindings/TypedArray.h
+++ b/dom/bindings/TypedArray.h
@@ -48,17 +48,17 @@ public:
       JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mTypedObj");
     }
     if (mWrappedObj) {
       JS_CallUnbarrieredObjectTracer(trc, &mTypedObj, "TypedArray.mWrappedObj");
     }
   }
 
 private:
-  TypedArrayObjectStorage(const TypedArrayObjectStorage&) MOZ_DELETE;
+  TypedArrayObjectStorage(const TypedArrayObjectStorage&) = delete;
 };
 
 /*
  * Various typed array classes for argument conversion.  We have a base class
  * that has a way of initializing a TypedArray from an existing typed array, and
  * a subclass of the base class that supports creation of a relevant typed array
  * or array buffer object.
  */
@@ -128,17 +128,17 @@ public:
   {
     MOZ_ASSERT(inited());
     MOZ_ASSERT(!mComputed);
     GetLengthAndData(mTypedObj, &mLength, &mData);
     mComputed = true;
   }
 
 private:
-  TypedArray_base(const TypedArray_base&) MOZ_DELETE;
+  TypedArray_base(const TypedArray_base&) = delete;
 };
 
 
 template<typename T,
          JSObject* UnwrapArray(JSObject*),
          T* GetData(JSObject*, const JS::AutoCheckCannotGC&),
          void GetLengthAndData(JSObject*, uint32_t*, T**),
          JSObject* CreateNew(JSContext*, uint32_t)>
@@ -183,17 +183,17 @@ private:
     if (data) {
       JS::AutoCheckCannotGC nogc;
       T* buf = static_cast<T*>(GetData(obj, nogc));
       memcpy(buf, data, length*sizeof(T));
     }
     return obj;
   }
 
-  TypedArray(const TypedArray&) MOZ_DELETE;
+  TypedArray(const TypedArray&) = delete;
 };
 
 typedef TypedArray<int8_t, js::UnwrapInt8Array, JS_GetInt8ArrayData,
                    js::GetInt8ArrayLengthAndData, JS_NewInt8Array>
         Int8Array;
 typedef TypedArray<uint8_t, js::UnwrapUint8Array, JS_GetUint8ArrayData,
                    js::GetUint8ArrayLengthAndData, JS_NewUint8Array>
         Uint8Array;
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -863,226 +863,226 @@ public:
   int8_t EnforcedByte();
   void SetClampedByte(int8_t);
   int8_t ClampedByte();
 
 private:
   // We add signatures here that _could_ start matching if the codegen
   // got data types wrong.  That way if it ever does we'll have a call
   // to these private deleted methods and compilation will fail.
-  void SetReadonlyByte(int8_t) MOZ_DELETE;
+  void SetReadonlyByte(int8_t) = delete;
   template<typename T>
-  void SetWritableByte(T) MOZ_DELETE;
+  void SetWritableByte(T) = delete;
   template<typename T>
-  void PassByte(T) MOZ_DELETE;
-  void PassNullableByte(Nullable<int8_t>&) MOZ_DELETE;
+  void PassByte(T) = delete;
+  void PassNullableByte(Nullable<int8_t>&) = delete;
   template<typename T>
-  void PassOptionalByte(const Optional<T>&) MOZ_DELETE;
+  void PassOptionalByte(const Optional<T>&) = delete;
   template<typename T>
-  void PassOptionalByteWithDefault(T) MOZ_DELETE;
-  void PassVariadicByte(Sequence<int8_t>&) MOZ_DELETE;
+  void PassOptionalByteWithDefault(T) = delete;
+  void PassVariadicByte(Sequence<int8_t>&) = delete;
 
-  void SetReadonlyShort(int16_t) MOZ_DELETE;
+  void SetReadonlyShort(int16_t) = delete;
   template<typename T>
-  void SetWritableShort(T) MOZ_DELETE;
+  void SetWritableShort(T) = delete;
   template<typename T>
-  void PassShort(T) MOZ_DELETE;
+  void PassShort(T) = delete;
   template<typename T>
-  void PassOptionalShort(const Optional<T>&) MOZ_DELETE;
+  void PassOptionalShort(const Optional<T>&) = delete;
   template<typename T>
-  void PassOptionalShortWithDefault(T) MOZ_DELETE;
+  void PassOptionalShortWithDefault(T) = delete;
 
-  void SetReadonlyLong(int32_t) MOZ_DELETE;
+  void SetReadonlyLong(int32_t) = delete;
   template<typename T>
-  void SetWritableLong(T) MOZ_DELETE;
+  void SetWritableLong(T) = delete;
   template<typename T>
-  void PassLong(T) MOZ_DELETE;
+  void PassLong(T) = delete;
   template<typename T>
-  void PassOptionalLong(const Optional<T>&) MOZ_DELETE;
+  void PassOptionalLong(const Optional<T>&) = delete;
   template<typename T>
-  void PassOptionalLongWithDefault(T) MOZ_DELETE;
+  void PassOptionalLongWithDefault(T) = delete;
 
-  void SetReadonlyLongLong(int64_t) MOZ_DELETE;
+  void SetReadonlyLongLong(int64_t) = delete;
   template<typename T>
-  void SetWritableLongLong(T) MOZ_DELETE;
+  void SetWritableLongLong(T) = delete;
   template<typename T>
-  void PassLongLong(T) MOZ_DELETE;
+  void PassLongLong(T) = delete;
   template<typename T>
-  void PassOptionalLongLong(const Optional<T>&) MOZ_DELETE;
+  void PassOptionalLongLong(const Optional<T>&) = delete;
   template<typename T>
-  void PassOptionalLongLongWithDefault(T) MOZ_DELETE;
+  void PassOptionalLongLongWithDefault(T) = delete;
 
-  void SetReadonlyOctet(uint8_t) MOZ_DELETE;
+  void SetReadonlyOctet(uint8_t) = delete;
   template<typename T>
-  void SetWritableOctet(T) MOZ_DELETE;
+  void SetWritableOctet(T) = delete;
   template<typename T>
-  void PassOctet(T) MOZ_DELETE;
+  void PassOctet(T) = delete;
   template<typename T>
-  void PassOptionalOctet(const Optional<T>&) MOZ_DELETE;
+  void PassOptionalOctet(const Optional<T>&) = delete;
   template<typename T>
-  void PassOptionalOctetWithDefault(T) MOZ_DELETE;
+  void PassOptionalOctetWithDefault(T) = delete;
 
-  void SetReadonlyUnsignedShort(uint16_t) MOZ_DELETE;
+  void SetReadonlyUnsignedShort(uint16_t) = delete;
   template<typename T>
-  void SetWritableUnsignedShort(T) MOZ_DELETE;
+  void SetWritableUnsignedShort(T) = delete;
   template<typename T>
-  void PassUnsignedShort(T) MOZ_DELETE;
+  void PassUnsignedShort(T) = delete;
   template<typename T>
-  void PassOptionalUnsignedShort(const Optional<T>&) MOZ_DELETE;
+  void PassOptionalUnsignedShort(const Optional<T>&) = delete;
   template<typename T>
-  void PassOptionalUnsignedShortWithDefault(T) MOZ_DELETE;
+  void PassOptionalUnsignedShortWithDefault(T) = delete;
 
-  void SetReadonlyUnsignedLong(uint32_t) MOZ_DELETE;
+  void SetReadonlyUnsignedLong(uint32_t) = delete;
   template<typename T>
-  void SetWritableUnsignedLong(T) MOZ_DELETE;
+  void SetWritableUnsignedLong(T) = delete;
   template<typename T>
-  void PassUnsignedLong(T) MOZ_DELETE;
+  void PassUnsignedLong(T) = delete;
   template<typename T>
-  void PassOptionalUnsignedLong(const Optional<T>&) MOZ_DELETE;
+  void PassOptionalUnsignedLong(const Optional<T>&) = delete;
   template<typename T>
-  void PassOptionalUnsignedLongWithDefault(T) MOZ_DELETE;
+  void PassOptionalUnsignedLongWithDefault(T) = delete;
 
-  void SetReadonlyUnsignedLongLong(uint64_t) MOZ_DELETE;
+  void SetReadonlyUnsignedLongLong(uint64_t) = delete;
   template<typename T>
-  void SetWritableUnsignedLongLong(T) MOZ_DELETE;
+  void SetWritableUnsignedLongLong(T) = delete;
   template<typename T>
-  void PassUnsignedLongLong(T) MOZ_DELETE;
+  void PassUnsignedLongLong(T) = delete;
   template<typename T>
-  void PassOptionalUnsignedLongLong(const Optional<T>&) MOZ_DELETE;
+  void PassOptionalUnsignedLongLong(const Optional<T>&) = delete;
   template<typename T>
-  void PassOptionalUnsignedLongLongWithDefault(T) MOZ_DELETE;
+  void PassOptionalUnsignedLongLongWithDefault(T) = delete;
 
   // Enforce that only const things are passed for sequences
-  void PassSequence(Sequence<int32_t> &) MOZ_DELETE;
-  void PassNullableSequence(Nullable< Sequence<int32_t> >&) MOZ_DELETE;
-  void PassOptionalNullableSequenceWithDefaultValue(Nullable< Sequence<int32_t> >&) MOZ_DELETE;
-  void PassSequenceOfAny(JSContext*, Sequence<JS::Value>&) MOZ_DELETE;
-  void PassNullableSequenceOfAny(JSContext*, Nullable<Sequence<JS::Value> >&) MOZ_DELETE;
-  void PassOptionalSequenceOfAny(JSContext*, Optional<Sequence<JS::Value> >&) MOZ_DELETE;
-  void PassOptionalNullableSequenceOfAny(JSContext*, Optional<Nullable<Sequence<JS::Value> > >&) MOZ_DELETE;
-  void PassOptionalSequenceOfAnyWithDefaultValue(JSContext*, Nullable<Sequence<JS::Value> >&) MOZ_DELETE;
-  void PassSequenceOfSequenceOfAny(JSContext*, Sequence<Sequence<JS::Value> >&) MOZ_DELETE;
-  void PassSequenceOfNullableSequenceOfAny(JSContext*, Sequence<Nullable<Sequence<JS::Value> > >&) MOZ_DELETE;
-  void PassNullableSequenceOfNullableSequenceOfAny(JSContext*, Nullable<Sequence<Nullable<Sequence<JS::Value> > > >&) MOZ_DELETE;
-  void PassOptionalNullableSequenceOfNullableSequenceOfAny(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JS::Value> > > > >&) MOZ_DELETE;
-  void PassSequenceOfObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
-  void PassSequenceOfNullableObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
-  void PassOptionalNullableSequenceOfNullableSequenceOfObject(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&) MOZ_DELETE;
-  void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&) MOZ_DELETE;
+  void PassSequence(Sequence<int32_t> &) = delete;
+  void PassNullableSequence(Nullable< Sequence<int32_t> >&) = delete;
+  void PassOptionalNullableSequenceWithDefaultValue(Nullable< Sequence<int32_t> >&) = delete;
+  void PassSequenceOfAny(JSContext*, Sequence<JS::Value>&) = delete;
+  void PassNullableSequenceOfAny(JSContext*, Nullable<Sequence<JS::Value> >&) = delete;
+  void PassOptionalSequenceOfAny(JSContext*, Optional<Sequence<JS::Value> >&) = delete;
+  void PassOptionalNullableSequenceOfAny(JSContext*, Optional<Nullable<Sequence<JS::Value> > >&) = delete;
+  void PassOptionalSequenceOfAnyWithDefaultValue(JSContext*, Nullable<Sequence<JS::Value> >&) = delete;
+  void PassSequenceOfSequenceOfAny(JSContext*, Sequence<Sequence<JS::Value> >&) = delete;
+  void PassSequenceOfNullableSequenceOfAny(JSContext*, Sequence<Nullable<Sequence<JS::Value> > >&) = delete;
+  void PassNullableSequenceOfNullableSequenceOfAny(JSContext*, Nullable<Sequence<Nullable<Sequence<JS::Value> > > >&) = delete;
+  void PassOptionalNullableSequenceOfNullableSequenceOfAny(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JS::Value> > > > >&) = delete;
+  void PassSequenceOfObject(JSContext*, Sequence<JSObject*>&) = delete;
+  void PassSequenceOfNullableObject(JSContext*, Sequence<JSObject*>&) = delete;
+  void PassOptionalNullableSequenceOfNullableSequenceOfObject(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&) = delete;
+  void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&) = delete;
 
   // Enforce that only const things are passed for optional
-  void PassOptionalByte(Optional<int8_t>&) MOZ_DELETE;
-  void PassOptionalNullableByte(Optional<Nullable<int8_t> >&) MOZ_DELETE;
-  void PassOptionalShort(Optional<int16_t>&) MOZ_DELETE;
-  void PassOptionalLong(Optional<int32_t>&) MOZ_DELETE;
-  void PassOptionalLongLong(Optional<int64_t>&) MOZ_DELETE;
-  void PassOptionalOctet(Optional<uint8_t>&) MOZ_DELETE;
-  void PassOptionalUnsignedShort(Optional<uint16_t>&) MOZ_DELETE;
-  void PassOptionalUnsignedLong(Optional<uint32_t>&) MOZ_DELETE;
-  void PassOptionalUnsignedLongLong(Optional<uint64_t>&) MOZ_DELETE;
-  void PassOptionalSelf(Optional<TestInterface*> &) MOZ_DELETE;
-  void PassOptionalNonNullSelf(Optional<NonNull<TestInterface> >&) MOZ_DELETE;
+  void PassOptionalByte(Optional<int8_t>&) = delete;
+  void PassOptionalNullableByte(Optional<Nullable<int8_t> >&) = delete;
+  void PassOptionalShort(Optional<int16_t>&) = delete;
+  void PassOptionalLong(Optional<int32_t>&) = delete;
+  void PassOptionalLongLong(Optional<int64_t>&) = delete;
+  void PassOptionalOctet(Optional<uint8_t>&) = delete;
+  void PassOptionalUnsignedShort(Optional<uint16_t>&) = delete;
+  void PassOptionalUnsignedLong(Optional<uint32_t>&) = delete;
+  void PassOptionalUnsignedLongLong(Optional<uint64_t>&) = delete;
+  void PassOptionalSelf(Optional<TestInterface*> &) = delete;
+  void PassOptionalNonNullSelf(Optional<NonNull<TestInterface> >&) = delete;
   void PassOptionalOther(Optional<IndirectlyImplementedInterface*>&);
   void PassOptionalNonNullOther(Optional<NonNull<IndirectlyImplementedInterface> >&);
-  void PassOptionalExternal(Optional<TestExternalInterface*>&) MOZ_DELETE;
-  void PassOptionalNonNullExternal(Optional<TestExternalInterface*>&) MOZ_DELETE;
-  void PassOptionalSequence(Optional<Sequence<int32_t> >&) MOZ_DELETE;
-  void PassOptionalNullableSequence(Optional<Nullable<Sequence<int32_t> > >&) MOZ_DELETE;
-  void PassOptionalObjectSequence(Optional<Sequence<OwningNonNull<TestInterface> > >&) MOZ_DELETE;
-  void PassOptionalArrayBuffer(Optional<ArrayBuffer>&) MOZ_DELETE;
-  void PassOptionalNullableArrayBuffer(Optional<ArrayBuffer*>&) MOZ_DELETE;
-  void PassOptionalEnum(Optional<TestEnum>&) MOZ_DELETE;
-  void PassOptionalCallback(JSContext*, Optional<OwningNonNull<TestCallback> >&) MOZ_DELETE;
-  void PassOptionalNullableCallback(JSContext*, Optional<nsRefPtr<TestCallback> >&) MOZ_DELETE;
-  void PassOptionalAny(Optional<JS::Handle<JS::Value> >&) MOZ_DELETE;
+  void PassOptionalExternal(Optional<TestExternalInterface*>&) = delete;
+  void PassOptionalNonNullExternal(Optional<TestExternalInterface*>&) = delete;
+  void PassOptionalSequence(Optional<Sequence<int32_t> >&) = delete;
+  void PassOptionalNullableSequence(Optional<Nullable<Sequence<int32_t> > >&) = delete;
+  void PassOptionalObjectSequence(Optional<Sequence<OwningNonNull<TestInterface> > >&) = delete;
+  void PassOptionalArrayBuffer(Optional<ArrayBuffer>&) = delete;
+  void PassOptionalNullableArrayBuffer(Optional<ArrayBuffer*>&) = delete;
+  void PassOptionalEnum(Optional<TestEnum>&) = delete;
+  void PassOptionalCallback(JSContext*, Optional<OwningNonNull<TestCallback> >&) = delete;
+  void PassOptionalNullableCallback(JSContext*, Optional<nsRefPtr<TestCallback> >&) = delete;
+  void PassOptionalAny(Optional<JS::Handle<JS::Value> >&) = delete;
 
   // And test that string stuff is always const
-  void PassString(nsAString&) MOZ_DELETE;
-  void PassNullableString(nsAString&) MOZ_DELETE;
-  void PassOptionalString(Optional<nsAString>&) MOZ_DELETE;
-  void PassOptionalStringWithDefaultValue(nsAString&) MOZ_DELETE;
-  void PassOptionalNullableString(Optional<nsAString>&) MOZ_DELETE;
-  void PassOptionalNullableStringWithDefaultValue(nsAString&) MOZ_DELETE;
-  void PassVariadicString(Sequence<nsString>&) MOZ_DELETE;
+  void PassString(nsAString&) = delete;
+  void PassNullableString(nsAString&) = delete;
+  void PassOptionalString(Optional<nsAString>&) = delete;
+  void PassOptionalStringWithDefaultValue(nsAString&) = delete;
+  void PassOptionalNullableString(Optional<nsAString>&) = delete;
+  void PassOptionalNullableStringWithDefaultValue(nsAString&) = delete;
+  void PassVariadicString(Sequence<nsString>&) = delete;
 
   // cstrings should be const as well
-  void PassByteString(nsCString&) MOZ_DELETE;
-  void PassNullableByteString(nsCString&) MOZ_DELETE;
-  void PassOptionalByteString(Optional<nsCString>&) MOZ_DELETE;
-  void PassOptionalNullableByteString(Optional<nsCString>&) MOZ_DELETE;
-  void PassVariadicByteString(Sequence<nsCString>&) MOZ_DELETE;
+  void PassByteString(nsCString&) = delete;
+  void PassNullableByteString(nsCString&) = delete;
+  void PassOptionalByteString(Optional<nsCString>&) = delete;
+  void PassOptionalNullableByteString(Optional<nsCString>&) = delete;
+  void PassVariadicByteString(Sequence<nsCString>&) = delete;
 
   // Make sure dictionary arguments are always const
-  void PassDictionary(JSContext*, Dict&) MOZ_DELETE;
-  void PassOtherDictionary(GrandparentDict&) MOZ_DELETE;
-  void PassSequenceOfDictionaries(JSContext*, Sequence<Dict>&) MOZ_DELETE;
-  void PassDictionaryOrLong(JSContext*, Dict&) MOZ_DELETE;
-  void PassDictContainingDict(JSContext*, DictContainingDict&) MOZ_DELETE;
-  void PassDictContainingSequence(DictContainingSequence&) MOZ_DELETE;
+  void PassDictionary(JSContext*, Dict&) = delete;
+  void PassOtherDictionary(GrandparentDict&) = delete;
+  void PassSequenceOfDictionaries(JSContext*, Sequence<Dict>&) = delete;
+  void PassDictionaryOrLong(JSContext*, Dict&) = delete;
+  void PassDictContainingDict(JSContext*, DictContainingDict&) = delete;
+  void PassDictContainingSequence(DictContainingSequence&) = delete;
 
   // Make sure various nullable things are always const
-  void PassNullableEnum(Nullable<TestEnum>&) MOZ_DELETE;
+  void PassNullableEnum(Nullable<TestEnum>&) = delete;
 
   // Make sure unions are always const
-  void PassUnion(JSContext*, ObjectOrLong& arg) MOZ_DELETE;
-  void PassUnionWithNullable(JSContext*, ObjectOrNullOrLong& arg) MOZ_DELETE;
-  void PassNullableUnion(JSContext*, Nullable<ObjectOrLong>&) MOZ_DELETE;
-  void PassOptionalUnion(JSContext*, Optional<ObjectOrLong>&) MOZ_DELETE;
-  void PassOptionalNullableUnion(JSContext*, Optional<Nullable<ObjectOrLong> >&) MOZ_DELETE;
-  void PassOptionalNullableUnionWithDefaultValue(JSContext*, Nullable<ObjectOrLong>&) MOZ_DELETE;
+  void PassUnion(JSContext*, ObjectOrLong& arg) = delete;
+  void PassUnionWithNullable(JSContext*, ObjectOrNullOrLong& arg) = delete;
+  void PassNullableUnion(JSContext*, Nullable<ObjectOrLong>&) = delete;
+  void PassOptionalUnion(JSContext*, Optional<ObjectOrLong>&) = delete;
+  void PassOptionalNullableUnion(JSContext*, Optional<Nullable<ObjectOrLong> >&) = delete;
+  void PassOptionalNullableUnionWithDefaultValue(JSContext*, Nullable<ObjectOrLong>&) = delete;
 
   // Make sure various date stuff is const as needed
-  void PassNullableDate(Nullable<Date>&) MOZ_DELETE;
-  void PassOptionalDate(Optional<Date>&) MOZ_DELETE;
-  void PassOptionalNullableDate(Optional<Nullable<Date> >&) MOZ_DELETE;
-  void PassOptionalNullableDateWithDefaultValue(Nullable<Date>&) MOZ_DELETE;
-  void PassDateSequence(Sequence<Date>&) MOZ_DELETE;
-  void PassNullableDateSequence(Sequence<Nullable<Date> >&) MOZ_DELETE;
+  void PassNullableDate(Nullable<Date>&) = delete;
+  void PassOptionalDate(Optional<Date>&) = delete;
+  void PassOptionalNullableDate(Optional<Nullable<Date> >&) = delete;
+  void PassOptionalNullableDateWithDefaultValue(Nullable<Date>&) = delete;
+  void PassDateSequence(Sequence<Date>&) = delete;
+  void PassNullableDateSequence(Sequence<Nullable<Date> >&) = delete;
 
   // Make sure variadics are const as needed
-  void PassVariadicAny(JSContext*, Sequence<JS::Value>&) MOZ_DELETE;
-  void PassVariadicObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
-  void PassVariadicNullableObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
+  void PassVariadicAny(JSContext*, Sequence<JS::Value>&) = delete;
+  void PassVariadicObject(JSContext*, Sequence<JSObject*>&) = delete;
+  void PassVariadicNullableObject(JSContext*, Sequence<JSObject*>&) = delete;
 
   // Ensure NonNull does not leak in
-  void PassSelf(NonNull<TestInterface>&) MOZ_DELETE;
-  void PassSelf(OwningNonNull<TestInterface>&) MOZ_DELETE;
-  void PassSelf(const NonNull<TestInterface>&) MOZ_DELETE;
-  void PassSelf(const OwningNonNull<TestInterface>&) MOZ_DELETE;
-  void PassOther(NonNull<IndirectlyImplementedInterface>&) MOZ_DELETE;
-  void PassOther(const NonNull<IndirectlyImplementedInterface>&) MOZ_DELETE;
-  void PassOther(OwningNonNull<IndirectlyImplementedInterface>&) MOZ_DELETE;
-  void PassOther(const OwningNonNull<IndirectlyImplementedInterface>&) MOZ_DELETE;
-  void PassCallbackInterface(OwningNonNull<TestCallbackInterface>&) MOZ_DELETE;
-  void PassCallbackInterface(const OwningNonNull<TestCallbackInterface>&) MOZ_DELETE;
-  void PassCallbackInterface(NonNull<TestCallbackInterface>&) MOZ_DELETE;
-  void PassCallbackInterface(const NonNull<TestCallbackInterface>&) MOZ_DELETE;
-  void PassCallback(OwningNonNull<TestCallback>&) MOZ_DELETE;
-  void PassCallback(const OwningNonNull<TestCallback>&) MOZ_DELETE;
-  void PassCallback(NonNull<TestCallback>&) MOZ_DELETE;
-  void PassCallback(const NonNull<TestCallback>&) MOZ_DELETE;
-  void PassString(const NonNull<nsAString>&) MOZ_DELETE;
-  void PassString(NonNull<nsAString>&) MOZ_DELETE;
-  void PassString(const OwningNonNull<nsAString>&) MOZ_DELETE;
-  void PassString(OwningNonNull<nsAString>&) MOZ_DELETE;
+  void PassSelf(NonNull<TestInterface>&) = delete;
+  void PassSelf(OwningNonNull<TestInterface>&) = delete;
+  void PassSelf(const NonNull<TestInterface>&) = delete;
+  void PassSelf(const OwningNonNull<TestInterface>&) = delete;
+  void PassOther(NonNull<IndirectlyImplementedInterface>&) = delete;
+  void PassOther(const NonNull<IndirectlyImplementedInterface>&) = delete;
+  void PassOther(OwningNonNull<IndirectlyImplementedInterface>&) = delete;
+  void PassOther(const OwningNonNull<IndirectlyImplementedInterface>&) = delete;
+  void PassCallbackInterface(OwningNonNull<TestCallbackInterface>&) = delete;
+  void PassCallbackInterface(const OwningNonNull<TestCallbackInterface>&) = delete;
+  void PassCallbackInterface(NonNull<TestCallbackInterface>&) = delete;
+  void PassCallbackInterface(const NonNull<TestCallbackInterface>&) = delete;
+  void PassCallback(OwningNonNull<TestCallback>&) = delete;
+  void PassCallback(const OwningNonNull<TestCallback>&) = delete;
+  void PassCallback(NonNull<TestCallback>&) = delete;
+  void PassCallback(const NonNull<TestCallback>&) = delete;
+  void PassString(const NonNull<nsAString>&) = delete;
+  void PassString(NonNull<nsAString>&) = delete;
+  void PassString(const OwningNonNull<nsAString>&) = delete;
+  void PassString(OwningNonNull<nsAString>&) = delete;
 };
 
 class TestIndexedGetterInterface : public nsISupports,
                                    public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
   uint32_t IndexedGetter(uint32_t, bool&);
-  uint32_t IndexedGetter(uint32_t&) MOZ_DELETE;
+  uint32_t IndexedGetter(uint32_t&) = delete;
   uint32_t Item(uint32_t&);
-  uint32_t Item(uint32_t, bool&) MOZ_DELETE;
+  uint32_t Item(uint32_t, bool&) = delete;
   uint32_t Length();
   void LegacyCall(JS::Handle<JS::Value>);
 };
 
 class TestNamedGetterInterface : public nsISupports,
                                  public nsWrapperCache
 {
 public:
@@ -1183,17 +1183,17 @@ class TestIndexedAndNamedGetterAndSetter
 {
 public:
   uint32_t IndexedGetter(uint32_t, bool&);
   uint32_t Item(uint32_t);
   void NamedGetter(const nsAString&, bool&, nsAString&);
   bool NameIsEnumerable(const nsAString&);
   void NamedItem(const nsAString&, nsAString&);
   void IndexedSetter(uint32_t, int32_t&);
-  void IndexedSetter(uint32_t, const nsAString&) MOZ_DELETE;
+  void IndexedSetter(uint32_t, const nsAString&) = delete;
   void NamedSetter(const nsAString&, const nsAString&);
   void Stringify(nsAString&);
   uint32_t Length();
   void GetSupportedNames(unsigned, nsTArray<nsString>&);
 };
 
 class TestCppKeywordNamedMethodsInterface : public nsISupports,
                                             public nsWrapperCache
@@ -1214,38 +1214,38 @@ class TestIndexedDeleterInterface : publ
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
   void IndexedDeleter(uint32_t, bool&);
-  void IndexedDeleter(uint32_t) MOZ_DELETE;
+  void IndexedDeleter(uint32_t) = delete;
   long IndexedGetter(uint32_t, bool&);
   uint32_t Length();
   void DelItem(uint32_t);
-  void DelItem(uint32_t, bool&) MOZ_DELETE;
+  void DelItem(uint32_t, bool&) = delete;
 };
 
 class TestIndexedDeleterWithRetvalInterface : public nsISupports,
                                               public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
   bool IndexedDeleter(uint32_t, bool&);
-  bool IndexedDeleter(uint32_t) MOZ_DELETE;
+  bool IndexedDeleter(uint32_t) = delete;
   long IndexedGetter(uint32_t, bool&);
   uint32_t Length();
   bool DelItem(uint32_t);
-  bool DelItem(uint32_t, bool&) MOZ_DELETE;
+  bool DelItem(uint32_t, bool&) = delete;
 };
 
 class TestNamedDeleterInterface : public nsISupports,
                                   public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
@@ -1263,21 +1263,21 @@ class TestNamedDeleterWithRetvalInterfac
 {
 public:
   NS_DECL_ISUPPORTS
 
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
   bool NamedDeleter(const nsAString&, bool&);
-  bool NamedDeleter(const nsAString&) MOZ_DELETE;
+  bool NamedDeleter(const nsAString&) = delete;
   long NamedGetter(const nsAString&, bool&);
   bool NameIsEnumerable(const nsAString&);
   bool DelNamedItem(const nsAString&);
-  bool DelNamedItem(const nsAString&, bool&) MOZ_DELETE;
+  bool DelNamedItem(const nsAString&, bool&) = delete;
   void GetSupportedNames(unsigned, nsTArray<nsString>&);
 };
 
 class TestIndexedAndNamedDeleterInterface : public nsISupports,
                                             public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
@@ -1285,21 +1285,21 @@ public:
   // We need a GetParentObject to make binding codegen happy
   virtual nsISupports* GetParentObject();
 
   void IndexedDeleter(uint32_t, bool&);
   long IndexedGetter(uint32_t, bool&);
   uint32_t Length();
 
   void NamedDeleter(const nsAString&, bool&);
-  void NamedDeleter(const nsAString&) MOZ_DELETE;
+  void NamedDeleter(const nsAString&) = delete;
   long NamedGetter(const nsAString&, bool&);
   bool NameIsEnumerable(const nsAString&);
   void DelNamedItem(const nsAString&);
-  void DelNamedItem(const nsAString&, bool&) MOZ_DELETE;
+  void DelNamedItem(const nsAString&, bool&) = delete;
   void GetSupportedNames(unsigned, nsTArray<nsString>&);
 };
 
 class TestParentInterface : public nsISupports,
                             public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -126,15 +126,15 @@ protected:
 
   CameraControlListener::CameraListenerConfiguration mCurrentConfiguration;
 
   CameraControlListener::PreviewState   mPreviewState;
   CameraControlListener::HardwareState  mHardwareState;
   nsresult                              mHardwareStateChangeReason;
 
 private:
-  CameraControlImpl(const CameraControlImpl&) MOZ_DELETE;
-  CameraControlImpl& operator=(const CameraControlImpl&) MOZ_DELETE;
+  CameraControlImpl(const CameraControlImpl&) = delete;
+  CameraControlImpl& operator=(const CameraControlImpl&) = delete;
 };
 
 } // namespace mozilla
 
 #endif // DOM_CAMERA_CAMERACONTROLIMPL_H
--- a/dom/camera/DOMCameraControl.h
+++ b/dom/camera/DOMCameraControl.h
@@ -229,17 +229,17 @@ protected:
 #ifdef MOZ_WIDGET_GONK
   // cached camera control, to improve start-up time
   static StaticRefPtr<ICameraControl> sCachedCameraControl;
   static nsresult sCachedCameraControlStartResult;
   static nsCOMPtr<nsITimer> sDiscardCachedCameraControlTimer;
 #endif
 
 private:
-  nsDOMCameraControl(const nsDOMCameraControl&) MOZ_DELETE;
-  nsDOMCameraControl& operator=(const nsDOMCameraControl&) MOZ_DELETE;
+  nsDOMCameraControl(const nsDOMCameraControl&) = delete;
+  nsDOMCameraControl& operator=(const nsDOMCameraControl&) = delete;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMCameraControl, NS_DOM_CAMERA_CONTROL_CID)
 
 } // namespace mozilla
 
 #endif // DOM_CAMERA_DOMCAMERACONTROL_H
--- a/dom/camera/DOMCameraControlListener.h
+++ b/dom/camera/DOMCameraControlListener.h
@@ -36,15 +36,15 @@ protected:
   virtual ~DOMCameraControlListener();
 
   nsMainThreadPtrHandle<nsISupports> mDOMCameraControl;
   CameraPreviewMediaStream* mStream;
 
   class DOMCallback;
 
 private:
-  DOMCameraControlListener(const DOMCameraControlListener&) MOZ_DELETE;
-  DOMCameraControlListener& operator=(const DOMCameraControlListener&) MOZ_DELETE;
+  DOMCameraControlListener(const DOMCameraControlListener&) = delete;
+  DOMCameraControlListener& operator=(const DOMCameraControlListener&) = delete;
 };
 
 } // namespace mozilla
 
 #endif // DOM_CAMERA_DOMCAMERACONTROLLISTENER_H
--- a/dom/camera/DOMCameraManager.h
+++ b/dom/camera/DOMCameraManager.h
@@ -81,20 +81,20 @@ public:
 #endif
 
 protected:
   void XpComShutdown();
   void Shutdown(uint64_t aWindowId);
   ~nsDOMCameraManager();
 
 private:
-  nsDOMCameraManager() MOZ_DELETE;
+  nsDOMCameraManager() = delete;
   explicit nsDOMCameraManager(nsPIDOMWindow* aWindow);
-  nsDOMCameraManager(const nsDOMCameraManager&) MOZ_DELETE;
-  nsDOMCameraManager& operator=(const nsDOMCameraManager&) MOZ_DELETE;
+  nsDOMCameraManager(const nsDOMCameraManager&) = delete;
+  nsDOMCameraManager& operator=(const nsDOMCameraManager&) = delete;
 
 protected:
   uint64_t mWindowId;
   uint32_t mPermission;
   nsCOMPtr<nsPIDOMWindow> mWindow;
   /**
    * 'sActiveWindows' is only ever accessed while in the Main Thread,
    * so it is not otherwise protected.
--- a/dom/camera/FallbackCameraControl.cpp
+++ b/dom/camera/FallbackCameraControl.cpp
@@ -63,11 +63,11 @@ protected:
   virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
                                       const StartRecordingOptions* aOptions = nullptr) MOZ_OVERRIDE
                                         { return NS_ERROR_NOT_INITIALIZED; }
   virtual nsresult StopRecordingImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; }
   virtual nsresult PushParametersImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; }
   virtual nsresult PullParametersImpl() MOZ_OVERRIDE { return NS_ERROR_NOT_INITIALIZED; }
 
 private:
-  FallbackCameraControl(const FallbackCameraControl&) MOZ_DELETE;
-  FallbackCameraControl& operator=(const FallbackCameraControl&) MOZ_DELETE;
+  FallbackCameraControl(const FallbackCameraControl&) = delete;
+  FallbackCameraControl& operator=(const FallbackCameraControl&) = delete;
 };
--- a/dom/camera/GonkCameraControl.h
+++ b/dom/camera/GonkCameraControl.h
@@ -188,18 +188,18 @@ protected:
 
   nsRefPtr<DeviceStorageFile> mVideoFile;
   nsString                  mFileFormat;
 
   // Guards against calling StartPreviewImpl() while in OnTakePictureComplete().
   ReentrantMonitor          mReentrantMonitor;
 
 private:
-  nsGonkCameraControl(const nsGonkCameraControl&) MOZ_DELETE;
-  nsGonkCameraControl& operator=(const nsGonkCameraControl&) MOZ_DELETE;
+  nsGonkCameraControl(const nsGonkCameraControl&) = delete;
+  nsGonkCameraControl& operator=(const nsGonkCameraControl&) = delete;
 };
 
 // camera driver callbacks
 void OnRateLimitPreview(nsGonkCameraControl* gc, bool aLimit);
 void OnTakePictureComplete(nsGonkCameraControl* gc, uint8_t* aData, uint32_t aLength);
 void OnTakePictureError(nsGonkCameraControl* gc);
 void OnAutoFocusComplete(nsGonkCameraControl* gc, bool aSuccess);
 void OnAutoFocusMoving(nsGonkCameraControl* gc, bool aIsMoving);
--- a/dom/camera/GonkCameraHwMgr.h
+++ b/dom/camera/GonkCameraHwMgr.h
@@ -119,15 +119,15 @@ protected:
   sp<Camera>                    mCamera;
   mozilla::nsGonkCameraControl* mTarget;
   sp<GonkNativeWindow>          mNativeWindow;
   sp<GonkCameraListener>        mListener;
   int                           mRawSensorOrientation;
   int                           mSensorOrientation;
 
 private:
-  GonkCameraHardware(const GonkCameraHardware&) MOZ_DELETE;
-  GonkCameraHardware& operator=(const GonkCameraHardware&) MOZ_DELETE;
+  GonkCameraHardware(const GonkCameraHardware&) = delete;
+  GonkCameraHardware& operator=(const GonkCameraHardware&) = delete;
 };
 
 } // namespace android
 
 #endif // GONK_IMPL_HW_MGR_H
--- a/dom/camera/TestGonkCameraControl.h
+++ b/dom/camera/TestGonkCameraControl.h
@@ -54,18 +54,18 @@ protected:
   virtual nsresult StartRecordingImpl(DeviceStorageFileDescriptor* aFileDescriptor,
                                       const StartRecordingOptions* aOptions = nullptr) MOZ_OVERRIDE;
   virtual nsresult StopRecordingImpl() MOZ_OVERRIDE;
 
   nsresult ForceMethodFailWithCodeInternal(const char* aFile, int aLine);
   nsresult ForceAsyncFailWithCodeInternal(const char* aFile, int aLine);
 
 private:
-  TestGonkCameraControl(const TestGonkCameraControl&) MOZ_DELETE;
-  TestGonkCameraControl& operator=(const TestGonkCameraControl&) MOZ_DELETE;
+  TestGonkCameraControl(const TestGonkCameraControl&) = delete;
+  TestGonkCameraControl& operator=(const TestGonkCameraControl&) = delete;
 };
 
 #define ForceMethodFailWithCode() ForceMethodFailWithCodeInternal(__FILE__, __LINE__)
 #define ForceAsyncFailWithCode()  ForceAsyncFailWithCodeInternal(__FILE__, __LINE__)
 
 } // namespace mozilla
 
 #endif // DOM_CAMERA_TESTGONKCAMERACONTROL_H
--- a/dom/camera/TestGonkCameraHardware.h
+++ b/dom/camera/TestGonkCameraHardware.h
@@ -60,17 +60,17 @@ protected:
   const nsCString GetExtraParameters();
   bool IsTestCaseInternal(const char* aTest, const char* aFile, int aLine);
   int TestCaseError(int aDefaultError);
 
   int StartAutoFocusMoving(bool aIsMoving);
   void InjectFakeSystemFailure();
 
 private:
-  TestGonkCameraHardware(const TestGonkCameraHardware&) MOZ_DELETE;
-  TestGonkCameraHardware& operator=(const TestGonkCameraHardware&) MOZ_DELETE;
+  TestGonkCameraHardware(const TestGonkCameraHardware&) = delete;
+  TestGonkCameraHardware& operator=(const TestGonkCameraHardware&) = delete;
 };
 
 #define IsTestCase(test)  IsTestCaseInternal((test), __FILE__, __LINE__)
 
 } // namespace android
 
 #endif // DOM_CAMERA_TESTGONKCAMERAHARDWARE_H
--- a/dom/canvas/ImageData.h
+++ b/dom/canvas/ImageData.h
@@ -74,17 +74,17 @@ public:
   }
 
   JSObject* WrapObject(JSContext* cx);
 
 private:
   void HoldData();
   void DropData();
 
-  ImageData() MOZ_DELETE;
+  ImageData() = delete;
 
   uint32_t mWidth, mHeight;
   JS::Heap<JSObject*> mData;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/cellbroadcast/CellBroadcast.h
+++ b/dom/cellbroadcast/CellBroadcast.h
@@ -36,17 +36,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSICELLBROADCASTLISTENER
 
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
 
   static already_AddRefed<CellBroadcast>
   Create(nsPIDOMWindow* aOwner, ErrorResult& aRv);
 
-  CellBroadcast() MOZ_DELETE;
+  CellBroadcast() = delete;
   CellBroadcast(nsPIDOMWindow *aWindow,
                 nsICellBroadcastService* aService);
 
   nsPIDOMWindow*
   GetParentObject() const { return GetOwner(); }
 
   virtual JSObject*
   WrapObject(JSContext* aCx) MOZ_OVERRIDE;
--- a/dom/encoding/EncodingUtils.h
+++ b/dom/encoding/EncodingUtils.h
@@ -134,15 +134,15 @@ public:
    *
    * @param      aEncoding, incoming label describing charset to be decoded.
    * @param      aOutGroup, returning corresponding language group.
    */
   static void LangGroupForEncoding(const nsACString& aEncoding,
                                    nsACString& aOutGroup);
 
 private:
-  EncodingUtils() MOZ_DELETE;
+  EncodingUtils() = delete;
 };
 
 } // dom
 } // mozilla
 
 #endif // mozilla_dom_encodingutils_h_
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -737,17 +737,19 @@ EventStateManager::PreHandleEvent(nsPres
         break;
       }
       ContentEventHandler handler(mPresContext);
       handler.OnQueryTextRect(aEvent->AsQueryContentEvent());
     }
     break;
   case NS_QUERY_EDITOR_RECT:
     {
-      // XXX remote event
+      if (RemoteQueryContentEvent(aEvent)) {
+        break;
+      }
       ContentEventHandler handler(mPresContext);
       handler.OnQueryEditorRect(aEvent->AsQueryContentEvent());
     }
     break;
   case NS_QUERY_CONTENT_STATE:
     {
       // XXX remote event
       ContentEventHandler handler(mPresContext);
--- a/dom/events/JSEventHandler.h
+++ b/dom/events/JSEventHandler.h
@@ -138,17 +138,17 @@ public:
   bool operator==(const TypedEventHandler& aOther) const
   {
     return
       Ptr() && aOther.Ptr() &&
       Ptr()->CallbackPreserveColor() == aOther.Ptr()->CallbackPreserveColor();
   }
 
 private:
-  void operator=(const TypedEventHandler&) MOZ_DELETE;
+  void operator=(const TypedEventHandler&) = delete;
 
   void ReleaseHandler()
   {
     nsISupports* ptr = Ptr();
     NS_IF_RELEASE(ptr);
   }
 
   void Assign(nsISupports* aHandler, HandlerType aType)
--- a/dom/fetch/FetchDriver.h
+++ b/dom/fetch/FetchDriver.h
@@ -35,19 +35,19 @@ public:
   explicit FetchDriver(InternalRequest* aRequest);
   NS_IMETHOD Fetch(FetchDriverObserver* aObserver);
 
 private:
   nsRefPtr<InternalRequest> mRequest;
   nsRefPtr<FetchDriverObserver> mObserver;
   uint32_t mFetchRecursionCount;
 
-  FetchDriver() MOZ_DELETE;
-  FetchDriver(const FetchDriver&) MOZ_DELETE;
-  FetchDriver& operator=(const FetchDriver&) MOZ_DELETE;
+  FetchDriver() = delete;
+  FetchDriver(const FetchDriver&) = delete;
+  FetchDriver& operator=(const FetchDriver&) = delete;
   ~FetchDriver();
 
   nsresult Fetch(bool aCORSFlag);
   nsresult ContinueFetch(bool aCORSFlag);
   nsresult BasicFetch();
   nsresult FailWithNetworkError();
   nsresult BeginResponse(InternalResponse* aResponse);
   nsresult SucceedWithResponse();
--- a/dom/fetch/Headers.h
+++ b/dom/fetch/Headers.h
@@ -48,17 +48,17 @@ private:
 
 public:
   explicit Headers(nsISupports* aOwner, InternalHeaders* aInternalHeaders)
     : mOwner(aOwner)
     , mInternalHeaders(aInternalHeaders)
   {
   }
 
-  explicit Headers(const Headers& aOther) MOZ_DELETE;
+  explicit Headers(const Headers& aOther) = delete;
 
   static bool PrefEnabled(JSContext* cx, JSObject* obj);
 
   static already_AddRefed<Headers>
   Constructor(const GlobalObject& aGlobal,
               const Optional<HeadersOrByteStringSequenceSequenceOrByteStringMozMap>& aInit,
               ErrorResult& aRv);
 
--- a/dom/fetch/Response.h
+++ b/dom/fetch/Response.h
@@ -29,17 +29,17 @@ class Response MOZ_FINAL : public nsISup
                          , public FetchBody<Response>
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Response)
 
 public:
   Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse);
 
-  Response(const Response& aOther) MOZ_DELETE;
+  Response(const Response& aOther) = delete;
 
   JSObject*
   WrapObject(JSContext* aCx) MOZ_OVERRIDE
   {
     return ResponseBinding::Wrap(aCx, this);
   }
 
   ResponseType
--- a/dom/html/test/forms/test_input_number_mouse_events.html
+++ b/dom/html/test/forms/test_input_number_mouse_events.html
@@ -89,31 +89,27 @@ function test() {
   is(input.value, 1, "Test that preventDefault() works for click on spin-down button");
   input.removeEventListener("mousedown", preventDefault, false);
 
   // Run the spin tests:
   runNextSpinTest();
 }
 
 function runNextSpinTest() {
-  try {
-    var [index, test] = spinTests.next();
-    test();
-  } catch(e) {
-    if (e == StopIteration) {
-      SimpleTest.finish();
-      return; // We're all done
-    }
-    throw e;
+  var test = spinTests.shift();
+  if (!test) {
+    SimpleTest.finish();
+    return;
   }
+  test();
 }
 
 const SETTIMEOUT_DELAY = 500;
 
-var spinTests = Iterator([
+var spinTests = [
   // Test spining when the mouse button is kept depressed on the spin-up
   // button, then moved over the spin-down button:
   function() {
     var inputEventCount = 0;
     input.value = 0;
     input.addEventListener("input", function(evt) {
       ++inputEventCount;
       if (inputEventCount == 3) {
@@ -187,14 +183,14 @@ var spinTests = Iterator([
           synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
           input.type = "number"; // restore
           runNextSpinTest();
         }, SETTIMEOUT_DELAY);
       }
     }, false);
     synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" });
   }
-]);
+];
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/html/test/forms/test_input_untrusted_key_events.html
+++ b/dom/html/test/forms/test_input_untrusted_key_events.html
@@ -12,22 +12,22 @@
   <input id="input">
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(runNextTest, window);
 
-const kTests = Iterator([
+const kTests = [
   { type: "text", value: "foo", key: "b", expectedNewValue: "foo" },
   { type: "number", value: "123", key: "4", expectedNewValue: "123" },
   { type: "number", value: "123", key: KeyEvent.DOM_VK_UP, expectedNewValue: "123" },
   { type: "number", value: "123", key: KeyEvent.DOM_VK_DOWN, expectedNewValue: "123" },
-]);
+];
 
 function sendUntrustedKeyEvent(eventType, keyCode, target) {
   var evt = document.createEvent("KeyboardEvent");
   var canBubbleArg = true;
   var cancelableArg = true;
   var viewArg = document.defaultView;
   var ctrlKeyArg = false;
   var altKeyArg = false;
@@ -65,24 +65,21 @@ function runNextTest() {
          " after being sent '" + previousTest.key + "' key events");
   }
 
   // reset flags
   gotEvents.keydown = false;
   gotEvents.keyup = false;
   gotEvents.keypress = false;
 
-  try {
-    var [index, test] = kTests.next();
-  } catch(e) {
-    if (e == StopIteration) {
-      SimpleTest.finish();
-      return; // We're all done
-    }
-    throw e;
+
+  var test = kTests.shift();
+  if (!test) {
+    SimpleTest.finish();
+    return; // We're all done
   }
 
   input.type = test.type;
   input.focus(); // make sure we still have focus after type change
   input.value = test.value;
 
   sendUntrustedKeyEvent("keydown", test.key, input);
   sendUntrustedKeyEvent("keyup", test.key, input);
--- a/dom/indexedDB/ActorsChild.h
+++ b/dom/indexedDB/ActorsChild.h
@@ -123,18 +123,18 @@ public:
 
     return mCurrentTransaction;
   }
 
 private:
   explicit ThreadLocal(const nsID& aBackgroundChildLoggingId);
   ~ThreadLocal();
 
-  ThreadLocal() MOZ_DELETE;
-  ThreadLocal(const ThreadLocal& aOther) MOZ_DELETE;
+  ThreadLocal() = delete;
+  ThreadLocal(const ThreadLocal& aOther) = delete;
 };
 
 class BackgroundFactoryChild MOZ_FINAL
   : public PBackgroundIDBFactoryChild
 {
   friend class mozilla::ipc::BackgroundChildImpl;
   friend class IDBFactory;
 
@@ -188,17 +188,17 @@ private:
                                    PBackgroundIDBFactoryRequestChild* aRequest)
                                    MOZ_OVERRIDE;
 
   virtual bool
   DeallocPBackgroundIDBDatabaseChild(PBackgroundIDBDatabaseChild* aActor)
                                      MOZ_OVERRIDE;
 
   bool
-  SendDeleteMe() MOZ_DELETE;
+  SendDeleteMe() = delete;
 };
 
 class BackgroundDatabaseChild;
 
 class BackgroundRequestChildBase
 {
 protected:
   nsRefPtr<IDBRequest> mRequest;
@@ -391,17 +391,17 @@ private:
   RecvVersionChange(const uint64_t& aOldVersion,
                     const NullableVersion& aNewVersion)
                     MOZ_OVERRIDE;
 
   virtual bool
   RecvInvalidate() MOZ_OVERRIDE;
 
   bool
-  SendDeleteMe() MOZ_DELETE;
+  SendDeleteMe() = delete;
 };
 
 class BackgroundVersionChangeTransactionChild;
 
 class BackgroundTransactionBase
 {
   friend class BackgroundVersionChangeTransactionChild;
 
@@ -491,17 +491,17 @@ private:
   virtual PBackgroundIDBCursorChild*
   AllocPBackgroundIDBCursorChild(const OpenCursorParams& aParams) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild* aActor)
                                    MOZ_OVERRIDE;
 
   bool
-  SendDeleteMe() MOZ_DELETE;
+  SendDeleteMe() = delete;
 };
 
 class BackgroundVersionChangeTransactionChild MOZ_FINAL
   : public BackgroundTransactionBase
   , public PBackgroundIDBVersionChangeTransactionChild
 {
   friend class BackgroundDatabaseChild;
 
@@ -547,17 +547,17 @@ private:
   virtual PBackgroundIDBCursorChild*
   AllocPBackgroundIDBCursorChild(const OpenCursorParams& aParams) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPBackgroundIDBCursorChild(PBackgroundIDBCursorChild* aActor)
                                    MOZ_OVERRIDE;
 
   bool
-  SendDeleteMe() MOZ_DELETE;
+  SendDeleteMe() = delete;
 };
 
 class BackgroundRequestChild MOZ_FINAL
   : public BackgroundRequestChildBase
   , public PBackgroundIDBRequestChild
 {
   friend class BackgroundTransactionChild;
   friend class BackgroundVersionChangeTransactionChild;
@@ -714,20 +714,20 @@ private:
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual bool
   RecvResponse(const CursorResponse& aResponse) MOZ_OVERRIDE;
 
   // Force callers to use SendContinueInternal.
   bool
-  SendContinue(const CursorRequestParams& aParams) MOZ_DELETE;
+  SendContinue(const CursorRequestParams& aParams) = delete;
 
   bool
-  SendDeleteMe() MOZ_DELETE;
+  SendDeleteMe() = delete;
 };
 
 // XXX This doesn't belong here. However, we're not yet porting MutableFile
 //     stuff to PBackground so this is necessary for the time being.
 void
 DispatchMutableFileResult(IDBRequest* aRequest,
                           nsresult aResultCode,
                           IDBMutableFile* aMutableFile);
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -3694,18 +3694,18 @@ private:
     mStatement = aStatement;
 
     if (mStatement) {
       mScoper.emplace(mStatement);
     }
   }
 
   // No funny business allowed.
-  CachedStatement(const CachedStatement&) MOZ_DELETE;
-  CachedStatement& operator=(const CachedStatement&) MOZ_DELETE;
+  CachedStatement(const CachedStatement&) = delete;
+  CachedStatement& operator=(const CachedStatement&) = delete;
 };
 
 class NormalTransaction MOZ_FINAL
   : public TransactionBase
   , public PBackgroundIDBTransactionParent
 {
   friend class Database;
 
@@ -4893,17 +4893,17 @@ private:
   Start(const OpenCursorParams& aParams);
 
   void
   SendResponseInternal(CursorResponse& aResponse,
                        const nsTArray<StructuredCloneFile>& aFiles);
 
   // Must call SendResponseInternal!
   bool
-  SendResponse(const CursorResponse& aResponse) MOZ_DELETE;
+  SendResponse(const CursorResponse& aResponse) = delete;
 
   // IPDL methods.
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual bool
   RecvDeleteMe() MOZ_OVERRIDE;
 
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -223,16 +223,33 @@ parent:
      * Notifies IME of mouse button event on a character in focused editor.
      *
      * Returns true if the mouse button event is consumd by IME.
      */
     prio(urgent) sync NotifyIMEMouseButtonEvent(IMENotification notification)
       returns (bool consumedByIME);
 
     /**
+     * Notifies chrome to currect editor rect
+     *
+     *  rect         Rect of current focused editor
+     */
+    prio(urgent) async NotifyIMEEditorRect(nsIntRect rect);
+
+    /**
+     * Notifies chrome to position change
+     *
+     *  editorRect   Rect of current focused editor
+     *  compositionRects     Rects of current composition string
+     */
+    prio(urgent) async NotifyIMEPositionChange(nsIntRect editorRect,
+                                               nsIntRect[] compositionRects,
+                                               nsIntRect caretRect);
+
+    /**
      * Instructs chrome to end any pending composition
      *
      *  cancel       PR_TRUE if composition should be cancelled
      *  composition  Text to commit before ending the composition
      *
      *  if cancel is PR_TRUE,
      *    widget should return empty string for composition
      *  if cancel is PR_FALSE,
--- a/dom/ipc/TabContext.h
+++ b/dom/ipc/TabContext.h
@@ -271,18 +271,18 @@ public:
   /**
    * If IsValid(), this function returns a reference to a TabContext
    * corresponding to the IPCTabContext passed to our constructor.  If
    * !IsValid(), this function crashes.
    */
   const TabContext& GetTabContext();
 
 private:
-  MaybeInvalidTabContext(const MaybeInvalidTabContext&) MOZ_DELETE;
-  MaybeInvalidTabContext& operator=(const MaybeInvalidTabContext&) MOZ_DELETE;
+  MaybeInvalidTabContext(const MaybeInvalidTabContext&) = delete;
+  MaybeInvalidTabContext& operator=(const MaybeInvalidTabContext&) = delete;
 
   const char* mInvalidReason;
   MutableTabContext mTabContext;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1484,16 +1484,46 @@ TabParent::RecvNotifyIMEMouseButtonEvent
     return true;
   }
   nsresult rv = widget->NotifyIME(aIMENotification);
   *aConsumedByIME = rv == NS_SUCCESS_EVENT_CONSUMED;
   return true;
 }
 
 bool
+TabParent::RecvNotifyIMEEditorRect(const nsIntRect& aRect)
+{
+  mIMEEditorRect = aRect;
+  return true;
+}
+
+bool
+TabParent::RecvNotifyIMEPositionChange(
+             const nsIntRect& aEditorRect,
+             const InfallibleTArray<nsIntRect>& aCompositionRects,
+             const nsIntRect& aCaretRect)
+{
+  mIMEEditorRect = aEditorRect;
+  mIMECompositionRects = aCompositionRects;
+  mIMECaretRect = aCaretRect;
+
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (!widget) {
+    return true;
+  }
+
+  const nsIMEUpdatePreference updatePreference =
+    widget->GetIMEUpdatePreference();
+  if (updatePreference.WantPositionChanged()) {
+    widget->NotifyIME(IMENotification(NOTIFY_IME_OF_POSITION_CHANGE));
+  }
+  return true;
+}
+
+bool
 TabParent::RecvRequestFocus(const bool& aCanRaise)
 {
   nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
   if (!fm) {
     return true;
   }
 
   nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
@@ -1628,16 +1658,18 @@ TabParent::RecvDispatchAfterKeyboardEven
  *  have out-of-bounds offsets, so that widget can request content without
  *  knowing the exact length of text. It's up to widget to handle cases when
  *  the returned offset/length are different from the queried offset/length.
  *
  * For NS_QUERY_TEXT_RECT, fail if cached offset/length aren't equals to input.
  *   Cocoa widget always queries selected offset, so it works on it.
  *
  * For NS_QUERY_CARET_RECT, fail if cached offset isn't equals to input
+ *
+ * For NS_QUERY_EDITOR_RECT, always success
  */
 bool
 TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
 {
   aEvent.mSucceeded = false;
   aEvent.mWasAsync = false;
   aEvent.mReply.mFocusedWidget = nsCOMPtr<nsIWidget>(GetWidget()).get();
 
@@ -1712,16 +1744,22 @@ TabParent::HandleQueryContentEvent(Widge
         break;
       }
 
       aEvent.mReply.mOffset = mIMECaretOffset;
       aEvent.mReply.mRect = mIMECaretRect - GetChildProcessOffset();
       aEvent.mSucceeded = true;
     }
     break;
+  case NS_QUERY_EDITOR_RECT:
+    {
+      aEvent.mReply.mRect = mIMEEditorRect - GetChildProcessOffset();
+      aEvent.mSucceeded = true;
+    }
+    break;
   }
   return true;
 }
 
 bool
 TabParent::SendCompositionEvent(WidgetCompositionEvent& event)
 {
   if (mIsDestroyed) {
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -173,16 +173,21 @@ public:
     virtual bool RecvNotifyIMESelection(const uint32_t& aSeqno,
                                         const uint32_t& aAnchor,
                                         const uint32_t& aFocus,
                                         const mozilla::WritingMode& aWritingMode,
                                         const bool& aCausedByComposition) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMETextHint(const nsString& aText) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
                                                bool* aConsumedByIME) MOZ_OVERRIDE;
+    virtual bool RecvNotifyIMEEditorRect(const nsIntRect& aRect) MOZ_OVERRIDE;
+    virtual bool RecvNotifyIMEPositionChange(
+                   const nsIntRect& aEditoRect,
+                   const InfallibleTArray<nsIntRect>& aCompositionRects,
+                   const nsIntRect& aCaretRect) MOZ_OVERRIDE;
     virtual bool RecvEndIMEComposition(const bool& aCancel,
                                        nsString* aComposition) MOZ_OVERRIDE;
     virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
                                      int32_t* aIMEOpen,
                                      intptr_t* aNativeIMEContext) MOZ_OVERRIDE;
     virtual bool RecvSetInputContext(const int32_t& aIMEEnabled,
                                      const int32_t& aIMEOpen,
                                      const nsString& aType,
@@ -393,16 +398,17 @@ protected:
     nsAutoString mIMECompositionText;
     uint32_t mIMECompositionStart;
     uint32_t mIMESeqno;
 
     uint32_t mIMECompositionRectOffset;
     InfallibleTArray<nsIntRect> mIMECompositionRects;
     uint32_t mIMECaretOffset;
     nsIntRect mIMECaretRect;
+    nsIntRect mIMEEditorRect;
 
     // The number of event series we're currently capturing.
     int32_t mEventCaptureDepth;
 
     nsIntRect mRect;
     nsIntSize mDimensions;
     ScreenOrientation mOrientation;
     float mDPI;
--- a/dom/media/AudioStreamTrack.h
+++ b/dom/media/AudioStreamTrack.h
@@ -14,18 +14,18 @@ namespace dom {
 
 class AudioStreamTrack : public MediaStreamTrack {
 public:
   AudioStreamTrack(DOMMediaStream* aStream, TrackID aTrackID)
     : MediaStreamTrack(aStream, aTrackID) {}
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
-  virtual AudioStreamTrack* AsAudioStreamTrack() { return this; }
+  virtual AudioStreamTrack* AsAudioStreamTrack() MOZ_OVERRIDE { return this; }
 
   // WebIDL
-  virtual void GetKind(nsAString& aKind) { aKind.AssignLiteral("audio"); }
+  virtual void GetKind(nsAString& aKind) MOZ_OVERRIDE { aKind.AssignLiteral("audio"); }
 };
 
 }
 }
 
 #endif /* AUDIOSTREAMTRACK_H_ */
--- a/dom/media/BufferMediaResource.h
+++ b/dom/media/BufferMediaResource.h
@@ -35,51 +35,51 @@ public:
 
 protected:
   virtual ~BufferMediaResource()
   {
     MOZ_COUNT_DTOR(BufferMediaResource);
   }
 
 private:
-  virtual nsresult Close() { return NS_OK; }
-  virtual void Suspend(bool aCloseImmediately) {}
-  virtual void Resume() {}
+  virtual nsresult Close() MOZ_OVERRIDE { return NS_OK; }
+  virtual void Suspend(bool aCloseImmediately) MOZ_OVERRIDE {}
+  virtual void Resume() MOZ_OVERRIDE {}
   // Get the current principal for the channel
-  virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal()
+  virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() MOZ_OVERRIDE
   {
     nsCOMPtr<nsIPrincipal> principal = mPrincipal;
     return principal.forget();
   }
-  virtual bool CanClone() { return false; }
-  virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder)
+  virtual bool CanClone() MOZ_OVERRIDE { return false; }
+  virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) MOZ_OVERRIDE
   {
     return nullptr;
   }
 
   // These methods are called off the main thread.
   // The mode is initially MODE_PLAYBACK.
-  virtual void SetReadMode(MediaCacheStream::ReadMode aMode) {}
-  virtual void SetPlaybackRate(uint32_t aBytesPerSecond) {}
-  virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
+  virtual void SetReadMode(MediaCacheStream::ReadMode aMode) MOZ_OVERRIDE {}
+  virtual void SetPlaybackRate(uint32_t aBytesPerSecond) MOZ_OVERRIDE {}
+  virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE
   {
     *aBytes = std::min(mLength - mOffset, aCount);
     memcpy(aBuffer, mBuffer + mOffset, *aBytes);
     mOffset += *aBytes;
     MOZ_ASSERT(mOffset <= mLength);
     return NS_OK;
   }
   virtual nsresult ReadAt(int64_t aOffset, char* aBuffer,
-                          uint32_t aCount, uint32_t* aBytes)
+                          uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE
   {
     nsresult rv = Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
     if (NS_FAILED(rv)) return rv;
     return Read(aBuffer, aCount, aBytes);
   }
-  virtual nsresult Seek(int32_t aWhence, int64_t aOffset)
+  virtual nsresult Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE
   {
     MOZ_ASSERT(aOffset <= UINT32_MAX);
     switch (aWhence) {
     case nsISeekableStream::NS_SEEK_SET:
       if (aOffset < 0 || aOffset > mLength) {
         return NS_ERROR_FAILURE;
       }
       mOffset = static_cast<uint32_t> (aOffset);
@@ -95,48 +95,46 @@ private:
         return NS_ERROR_FAILURE;
       }
       mOffset = mLength - aOffset;
       break;
     }
 
     return NS_OK;
   }
-  virtual void StartSeekingForMetadata() {}
-  virtual void EndSeekingForMetadata() {}
-  virtual int64_t Tell() { return mOffset; }
+  virtual int64_t Tell() MOZ_OVERRIDE { return mOffset; }
 
-  virtual void Pin() {}
-  virtual void Unpin() {}
-  virtual double GetDownloadRate(bool* aIsReliable) { *aIsReliable = false; return 0.; }
-  virtual int64_t GetLength() { return mLength; }
-  virtual int64_t GetNextCachedData(int64_t aOffset) { return aOffset; }
-  virtual int64_t GetCachedDataEnd(int64_t aOffset) { return mLength; }
-  virtual bool IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
-  virtual bool IsSuspendedByCache() { return false; }
-  virtual bool IsSuspended() { return false; }
+  virtual void Pin() MOZ_OVERRIDE {}
+  virtual void Unpin() MOZ_OVERRIDE {}
+  virtual double GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE { *aIsReliable = false; return 0.; }
+  virtual int64_t GetLength() MOZ_OVERRIDE { return mLength; }
+  virtual int64_t GetNextCachedData(int64_t aOffset) MOZ_OVERRIDE { return aOffset; }
+  virtual int64_t GetCachedDataEnd(int64_t aOffset) MOZ_OVERRIDE { return mLength; }
+  virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { return true; }
+  virtual bool IsSuspendedByCache() MOZ_OVERRIDE { return false; }
+  virtual bool IsSuspended() MOZ_OVERRIDE { return false; }
   virtual nsresult ReadFromCache(char* aBuffer,
                                  int64_t aOffset,
-                                 uint32_t aCount)
+                                 uint32_t aCount) MOZ_OVERRIDE
   {
     if (aOffset < 0) {
       return NS_ERROR_FAILURE;
     }
 
     uint32_t bytes = std::min(mLength - static_cast<uint32_t>(aOffset), aCount);
     memcpy(aBuffer, mBuffer + aOffset, bytes);
     return NS_OK;
   }
 
-  virtual nsresult Open(nsIStreamListener** aStreamListener)
+  virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE
   {
     return NS_ERROR_FAILURE;
   }
 
-  virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges)
+  virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE
   {
     aRanges.AppendElement(MediaByteRange(0, mLength));
     return NS_OK;
   }
 
   bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
 
   virtual const nsCString& GetContentType() const MOZ_OVERRIDE
--- a/dom/media/GraphDriver.h
+++ b/dom/media/GraphDriver.h
@@ -261,17 +261,17 @@ public:
   virtual void Resume() MOZ_OVERRIDE;
   virtual void Revive() MOZ_OVERRIDE;
   /**
    * Runs main control loop on the graph thread. Normally a single invocation
    * of this runs for the entire lifetime of the graph thread.
    */
   void RunThread();
   friend class MediaStreamGraphInitThreadRunnable;
-  uint32_t IterationDuration() {
+  virtual uint32_t IterationDuration() MOZ_OVERRIDE {
     return MEDIA_GRAPH_TARGET_PERIOD_MS;
   }
 
   virtual bool OnThread() MOZ_OVERRIDE { return !mThread || NS_GetCurrentThread() == mThread; }
 
 protected:
   nsCOMPtr<nsIThread> mThread;
 };
@@ -307,17 +307,17 @@ public:
   OfflineClockDriver(MediaStreamGraphImpl* aGraphImpl, GraphTime aSlice);
   virtual ~OfflineClockDriver();
   virtual void GetIntervalForIteration(GraphTime& aFrom,
                                        GraphTime& aTo) MOZ_OVERRIDE;
   virtual GraphTime GetCurrentTime() MOZ_OVERRIDE;
   virtual void WaitForNextIteration() MOZ_OVERRIDE;
   virtual void WakeUp() MOZ_OVERRIDE;
   virtual TimeStamp GetCurrentTimeStamp() MOZ_OVERRIDE;
-  virtual OfflineClockDriver* AsOfflineClockDriver() {
+  virtual OfflineClockDriver* AsOfflineClockDriver() MOZ_OVERRIDE {
     return this;
   }
 
 private:
   // Time, in GraphTime, for each iteration
   GraphTime mSlice;
 };
 
@@ -373,27 +373,27 @@ public:
    * called again. If it is less than aFrames, the stream will go in draining
    * mode, and this function will not be called again. */
   long DataCallback(AudioDataValue* aBuffer, long aFrames);
   /* This function is called by the underlying audio backend, but is only used
    * for informational purposes at the moment. */
   void StateCallback(cubeb_state aState);
   /* This is an approximation of the number of millisecond there are between two
    * iterations of the graph. */
-  uint32_t IterationDuration();
+  virtual uint32_t IterationDuration() MOZ_OVERRIDE;
 
   /* This function gets called when the graph has produced the audio frames for
    * this iteration. */
   virtual void MixerCallback(AudioDataValue* aMixedBuffer,
                              AudioSampleFormat aFormat,
                              uint32_t aChannels,
                              uint32_t aFrames,
                              uint32_t aSampleRate) MOZ_OVERRIDE;
 
-  virtual AudioCallbackDriver* AsAudioCallbackDriver() {
+  virtual AudioCallbackDriver* AsAudioCallbackDriver() MOZ_OVERRIDE {
     return this;
   }
 
   bool IsSwitchingDevice() {
 #ifdef XP_MACOSX
     return mSelfReference;
 #else
     return false;
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -611,17 +611,17 @@ public:
   // Set a flag indicating whether seeking is supported
   virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
 
   // Returns true if this media supports seeking. False for example for WebM
   // files without an index and chained ogg files.
   virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
   // Returns true if seeking is supported on a transport level (e.g. the server
   // supports range requests, we are playing a file, etc.).
-  virtual bool IsTransportSeekable();
+  virtual bool IsTransportSeekable() MOZ_OVERRIDE;
 
   // Return the time ranges that can be seeked into.
   virtual nsresult GetSeekable(dom::TimeRanges* aSeekable);
 
   // Set the end time of the media resource. When playback reaches
   // this point the media pauses. aTime is in seconds.
   virtual void SetFragmentEndTime(double aTime);
 
@@ -744,17 +744,17 @@ public:
   void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
   dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
 
   // Send a new set of metadata to the state machine, to be dispatched to the
   // main thread to be presented when the |currentTime| of the media is greater
   // or equal to aPublishTime.
   void QueueMetadata(int64_t aPublishTime,
                      nsAutoPtr<MediaInfo> aInfo,
-                     nsAutoPtr<MetadataTags> aTags);
+                     nsAutoPtr<MetadataTags> aTags) MOZ_OVERRIDE;
 
   int64_t GetSeekTime() { return mRequestedSeekTarget.mTime; }
   void ResetSeekTime() { mRequestedSeekTarget.Reset(); }
 
   /******
    * The following methods must only be called on the main
    * thread.
    ******/
@@ -770,21 +770,21 @@ public:
 
   // May be called by the reader to notify this decoder that the metadata from
   // the media file has been read. Call on the decode thread only.
   void OnReadMetadataCompleted() MOZ_OVERRIDE { }
 
   // Called when the metadata from the media file has been loaded by the
   // state machine. Call on the main thread only.
   virtual void MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
-                              nsAutoPtr<MetadataTags> aTags);
+                              nsAutoPtr<MetadataTags> aTags) MOZ_OVERRIDE;
 
   // Called when the first audio and/or video from the media file has been loaded
   // by the state machine. Call on the main thread only.
-  virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo);
+  virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo) MOZ_OVERRIDE;
 
   // Called from MetadataLoaded(). Creates audio tracks and adds them to its
   // owner's audio track list, and implies to video tracks respectively.
   // Call on the main thread only.
   void ConstructMediaTracks();
 
   // Removes all audio tracks and video tracks that are previously added into
   // the track list. Call on the main thread only.
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -592,28 +592,28 @@ public:
     if (mPort) {
       mPort->Destroy();
     }
     if (mSourceStream) {
       mSourceStream->Destroy();
     }
   }
 
-  virtual void Stop()
+  virtual void Stop() MOZ_OVERRIDE
   {
     if (mSourceStream) {
       mSourceStream->EndAllTrackAndFinish();
     }
   }
 
   // For gUM streams, we have a trackunion which assigns TrackIDs.  However, for a
   // single-source trackunion like we have here, the TrackUnion will assign trackids
   // that match the source's trackids, so we can avoid needing a mapping function.
   // XXX This will not handle more complex cases well.
-  virtual void StopTrack(TrackID aTrackID)
+  virtual void StopTrack(TrackID aTrackID) MOZ_OVERRIDE
   {
     if (mSourceStream) {
       mSourceStream->EndTrack(aTrackID);
       // We could override NotifyMediaStreamTrackEnded(), and maybe should, but it's
       // risky to do late in a release since that will affect all track ends, and not
       // just StopTrack()s.
       if (GetDOMTrackFor(aTrackID)) {
         mListener->StopTrack(aTrackID, !!GetDOMTrackFor(aTrackID)->AsAudioStreamTrack());
@@ -676,22 +676,22 @@ public:
     // We encapsulate the SourceMediaStream and TrackUnion into one entity, so
     // we can handle the disabling at the SourceMediaStream
 
     // We need to find the input track ID for output ID aID, so we let the TrackUnion
     // forward the request to the source and translate the ID
     GetStream()->AsProcessedStream()->ForwardTrackEnabled(aID, aEnabled);
   }
 
-  virtual DOMLocalMediaStream* AsDOMLocalMediaStream()
+  virtual DOMLocalMediaStream* AsDOMLocalMediaStream() MOZ_OVERRIDE
   {
     return this;
   }
 
-  virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID)
+  virtual MediaEngineSource* GetMediaEngine(TrackID aTrackID) MOZ_OVERRIDE
   {
     // MediaEngine supports only one video and on video track now and TrackID is
     // fixed in MediaEngine.
     if (aTrackID == kVideoTrack) {
       return mVideoSource;
     }
     else if (aTrackID == kAudioTrack) {
       return mAudioSource;
--- a/dom/media/MediaPromise.h
+++ b/dom/media/MediaPromise.h
@@ -215,22 +215,22 @@ protected:
       PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
                   resolved ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
                   runnable.get(), aPromise, this);
       DebugOnly<nsresult> rv = detail::DispatchMediaPromiseRunnable(mResponseTarget, runnable);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
 
   protected:
-    virtual void DoResolve(ResolveValueType aResolveValue)
+    virtual void DoResolve(ResolveValueType aResolveValue) MOZ_OVERRIDE
     {
       InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aResolveValue);
     }
 
-    virtual void DoReject(RejectValueType aRejectValue)
+    virtual void DoReject(RejectValueType aRejectValue) MOZ_OVERRIDE
     {
       InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aRejectValue);
     }
 
     virtual ~ThenValue() {}
 
   private:
     nsRefPtr<TargetType> mResponseTarget;
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -68,17 +68,17 @@ public:
     recorders.RemoveElement(aRecorder);
     if (recorders.IsEmpty()) {
       sUniqueInstance = nullptr;
     }
   }
 
   NS_METHOD
   CollectReports(nsIHandleReportCallback* aHandleReport,
-                 nsISupports* aData, bool aAnonymize)
+                 nsISupports* aData, bool aAnonymize) MOZ_OVERRIDE
   {
     int64_t amount = 0;
     RecordersArray& recorders = GetRecorders();
     for (size_t i = 0; i < recorders.Length(); ++i) {
       amount += recorders[i]->SizeOfExcludingThis(MallocSizeOf);
     }
 
   #define MEMREPORT(_path, _amount, _desc)                                    \
@@ -646,17 +646,17 @@ private:
     }
 
     if (mTrackUnionStream.get()) {
       mTrackUnionStream->Destroy();
       mTrackUnionStream = nullptr;
     }
   }
 
-  NS_IMETHODIMP Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData)
+  NS_IMETHODIMP Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     LOG(PR_LOG_DEBUG, ("Session.Observe XPCOM_SHUTDOWN %p", this));
     if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
       // Force stop Session to terminate Read Thread.
       mEncoder->Cancel();
       if (mReadThread) {
         mReadThread->Shutdown();
--- a/dom/media/MediaRecorder.h
+++ b/dom/media/MediaRecorder.h
@@ -102,29 +102,29 @@ public:
   IMPL_EVENT_HANDLER(stop)
   IMPL_EVENT_HANDLER(warning)
 
   NS_DECL_NSIDOCUMENTACTIVITY
 
 protected:
   virtual ~MediaRecorder();
 
-  MediaRecorder& operator = (const MediaRecorder& x) MOZ_DELETE;
+  MediaRecorder& operator = (const MediaRecorder& x) = delete;
   // Create dataavailable event with Blob data and it runs in main thread
   nsresult CreateAndDispatchBlobEvent(already_AddRefed<nsIDOMBlob>&& aBlob);
   // Creating a simple event to notify UA simple event.
   void DispatchSimpleEvent(const nsAString & aStr);
   // Creating a error event with message.
   void NotifyError(nsresult aRv);
   // Check if the recorder's principal is the subsume of mediaStream
   bool CheckPrincipal();
   // Set encoded MIME type.
   void SetMimeType(const nsString &aMimeType);
 
-  MediaRecorder(const MediaRecorder& x) MOZ_DELETE; // prevent bad usage
+  MediaRecorder(const MediaRecorder& x) = delete; // prevent bad usage
   // Remove session pointer.
   void RemoveSession(Session* aSession);
   // Functions for Session to query input source info.
   MediaStream* GetSourceMediaStream();
   nsIPrincipal* GetSourcePrincipal();
   // DOM wrapper for source media stream. Will be null when input is audio node.
   nsRefPtr<DOMMediaStream> mDOMStream;
   // Source audio node. Will be null when input is a media stream.
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -1194,70 +1194,70 @@ public:
     mSizeInitialized(false)
   {
   }
   ~FileMediaResource()
   {
   }
 
   // Main thread
-  virtual nsresult Open(nsIStreamListener** aStreamListener);
-  virtual nsresult Close();
-  virtual void     Suspend(bool aCloseImmediately) {}
-  virtual void     Resume() {}
-  virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
-  virtual bool     CanClone();
-  virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder);
-  virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount);
+  virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE;
+  virtual nsresult Close() MOZ_OVERRIDE;
+  virtual void     Suspend(bool aCloseImmediately) MOZ_OVERRIDE {}
+  virtual void     Resume() MOZ_OVERRIDE {}
+  virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() MOZ_OVERRIDE;
+  virtual bool     CanClone() MOZ_OVERRIDE;
+  virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) MOZ_OVERRIDE;
+  virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) MOZ_OVERRIDE;
 
   // These methods are called off the main thread.
 
   // Other thread
-  virtual void     SetReadMode(MediaCacheStream::ReadMode aMode) {}
-  virtual void     SetPlaybackRate(uint32_t aBytesPerSecond) {}
-  virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
+  virtual void     SetReadMode(MediaCacheStream::ReadMode aMode) MOZ_OVERRIDE {}
+  virtual void     SetPlaybackRate(uint32_t aBytesPerSecond) MOZ_OVERRIDE {}
+  virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE;
   virtual nsresult ReadAt(int64_t aOffset, char* aBuffer,
-                          uint32_t aCount, uint32_t* aBytes);
-  virtual nsresult Seek(int32_t aWhence, int64_t aOffset);
-  virtual int64_t  Tell();
+                          uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE;
+  virtual nsresult Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE;
+  virtual int64_t  Tell() MOZ_OVERRIDE;
 
   // Any thread
-  virtual void    Pin() {}
-  virtual void    Unpin() {}
-  virtual double  GetDownloadRate(bool* aIsReliable)
+  virtual void    Pin() MOZ_OVERRIDE {}
+  virtual void    Unpin() MOZ_OVERRIDE {}
+  virtual double  GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE
   {
     // The data's all already here
     *aIsReliable = true;
     return 100*1024*1024; // arbitray, use 100MB/s
   }
-  virtual int64_t GetLength() {
+  virtual int64_t GetLength() MOZ_OVERRIDE {
     MutexAutoLock lock(mLock);
 
     EnsureSizeInitialized();
     return mSizeInitialized ? mSize : 0;
   }
-  virtual int64_t GetNextCachedData(int64_t aOffset)
+  virtual int64_t GetNextCachedData(int64_t aOffset) MOZ_OVERRIDE
   {
     MutexAutoLock lock(mLock);
 
     EnsureSizeInitialized();
     return (aOffset < mSize) ? aOffset : -1;
   }
-  virtual int64_t GetCachedDataEnd(int64_t aOffset) {
+  virtual int64_t GetCachedDataEnd(int64_t aOffset) MOZ_OVERRIDE {
     MutexAutoLock lock(mLock);
 
     EnsureSizeInitialized();
     return std::max(aOffset, mSize);
   }
-  virtual bool    IsDataCachedToEndOfResource(int64_t aOffset) { return true; }
-  virtual bool    IsSuspendedByCache() { return true; }
-  virtual bool    IsSuspended() { return true; }
+  virtual bool    IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { return true; }
+  virtual bool    IsSuspendedByCache() MOZ_OVERRIDE { return true; }
+  virtual bool    IsSuspended() MOZ_OVERRIDE { return true; }
   virtual bool    IsTransportSeekable() MOZ_OVERRIDE { return true; }
 
-  nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges);
+  nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE;
 
   virtual size_t SizeOfExcludingThis(
                         MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
   {
     // Might be useful to track in the future:
     // - mInput
     return BaseMediaResource::SizeOfExcludingThis(aMallocSizeOf);
   }
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -425,17 +425,17 @@ protected:
   virtual ~MediaResource() {};
 
 private:
   void Destroy();
 };
 
 class BaseMediaResource : public MediaResource {
 public:
-  virtual nsIURI* URI() const { return mURI; }
+  virtual nsIURI* URI() const MOZ_OVERRIDE { return mURI; }
   virtual void SetLoadInBackground(bool aLoadInBackground) MOZ_OVERRIDE;
 
   virtual size_t SizeOfExcludingThis(
                   MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
   {
     // Might be useful to track in the future:
     // - mChannel
     // - mURI (possibly owned, looks like just a ref from mChannel)
@@ -559,56 +559,56 @@ public:
   // Ensure that the media cache writes any data held in its partial block.
   // Called on the main thread.
   virtual void FlushCache() MOZ_OVERRIDE;
 
   // Notify that the last data byte range was loaded.
   virtual void NotifyLastByteRange() MOZ_OVERRIDE;
 
   // Main thread
-  virtual nsresult Open(nsIStreamListener** aStreamListener);
-  virtual nsresult Close();
-  virtual void     Suspend(bool aCloseImmediately);
-  virtual void     Resume();
-  virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
+  virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE;
+  virtual nsresult Close() MOZ_OVERRIDE;
+  virtual void     Suspend(bool aCloseImmediately) MOZ_OVERRIDE;
+  virtual void     Resume() MOZ_OVERRIDE;
+  virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() MOZ_OVERRIDE;
   // Return true if the stream has been closed.
   bool IsClosed() const { return mCacheStream.IsClosed(); }
-  virtual bool     CanClone();
-  virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder);
+  virtual bool     CanClone() MOZ_OVERRIDE;
+  virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) MOZ_OVERRIDE;
   // Set statistics to be recorded to the object passed in. If not called,
   // |ChannelMediaResource| will create it's own statistics objects in |Open|.
   void RecordStatisticsTo(MediaChannelStatistics *aStatistics) MOZ_OVERRIDE {
     NS_ASSERTION(aStatistics, "Statistics param cannot be null!");
     MutexAutoLock lock(mLock);
     if (!mChannelStatistics) {
       mChannelStatistics = aStatistics;
     }
   }
-  virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount);
-  virtual void     EnsureCacheUpToDate();
+  virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) MOZ_OVERRIDE;
+  virtual void     EnsureCacheUpToDate() MOZ_OVERRIDE;
 
   // Other thread
-  virtual void     SetReadMode(MediaCacheStream::ReadMode aMode);
-  virtual void     SetPlaybackRate(uint32_t aBytesPerSecond);
-  virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes);
+  virtual void     SetReadMode(MediaCacheStream::ReadMode aMode) MOZ_OVERRIDE;
+  virtual void     SetPlaybackRate(uint32_t aBytesPerSecond) MOZ_OVERRIDE;
+  virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE;
   virtual nsresult ReadAt(int64_t offset, char* aBuffer,
-                          uint32_t aCount, uint32_t* aBytes);
-  virtual nsresult Seek(int32_t aWhence, int64_t aOffset);
-  virtual int64_t  Tell();
+                          uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE;
+  virtual nsresult Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE;
+  virtual int64_t  Tell() MOZ_OVERRIDE;
 
   // Any thread
-  virtual void    Pin();
-  virtual void    Unpin();
-  virtual double  GetDownloadRate(bool* aIsReliable);
-  virtual int64_t GetLength();
-  virtual int64_t GetNextCachedData(int64_t aOffset);
-  virtual int64_t GetCachedDataEnd(int64_t aOffset);
-  virtual bool    IsDataCachedToEndOfResource(int64_t aOffset);
-  virtual bool    IsSuspendedByCache();
-  virtual bool    IsSuspended();
+  virtual void    Pin() MOZ_OVERRIDE;
+  virtual void    Unpin() MOZ_OVERRIDE;
+  virtual double  GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE;
+  virtual int64_t GetLength() MOZ_OVERRIDE;
+  virtual int64_t GetNextCachedData(int64_t aOffset) MOZ_OVERRIDE;
+  virtual int64_t GetCachedDataEnd(int64_t aOffset) MOZ_OVERRIDE;
+  virtual bool    IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE;
+  virtual bool    IsSuspendedByCache() MOZ_OVERRIDE;
+  virtual bool    IsSuspended() MOZ_OVERRIDE;
   virtual bool    IsTransportSeekable() MOZ_OVERRIDE;
 
   virtual size_t SizeOfExcludingThis(
                       MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE {
     // Might be useful to track in the future:
     //   - mListener (seems minor)
     //   - mChannelStatistics (seems minor)
     //     owned if RecordStatisticsTo is not called
@@ -640,17 +640,17 @@ public:
 
     void Revoke() { mResource = nullptr; }
 
   private:
     nsRefPtr<ChannelMediaResource> mResource;
   };
   friend class Listener;
 
-  nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges);
+  virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE;
 
 protected:
   // These are called on the main thread by Listener.
   nsresult OnStartRequest(nsIRequest* aRequest);
   nsresult OnStopRequest(nsIRequest* aRequest, nsresult aStatus);
   nsresult OnDataAvailable(nsIRequest* aRequest,
                            nsIInputStream* aStream,
                            uint32_t aCount);
--- a/dom/media/MediaSegment.h
+++ b/dom/media/MediaSegment.h
@@ -138,44 +138,44 @@ protected:
 };
 
 /**
  * C is the implementation class subclassed from MediaSegmentBase.
  * C must contain a Chunk class.
  */
 template <class C, class Chunk> class MediaSegmentBase : public MediaSegment {
 public:
-  virtual MediaSegment* CreateEmptyClone() const
+  virtual MediaSegment* CreateEmptyClone() const MOZ_OVERRIDE
   {
     return new C();
   }
-  virtual void AppendFrom(MediaSegment* aSource)
+  virtual void AppendFrom(MediaSegment* aSource) MOZ_OVERRIDE
   {
     NS_ASSERTION(aSource->GetType() == C::StaticType(), "Wrong type");
     AppendFromInternal(static_cast<C*>(aSource));
   }
   void AppendFrom(C* aSource)
   {
     AppendFromInternal(aSource);
   }
   virtual void AppendSlice(const MediaSegment& aSource,
-                           StreamTime aStart, StreamTime aEnd)
+                           StreamTime aStart, StreamTime aEnd) MOZ_OVERRIDE
   {
     NS_ASSERTION(aSource.GetType() == C::StaticType(), "Wrong type");
     AppendSliceInternal(static_cast<const C&>(aSource), aStart, aEnd);
   }
   void AppendSlice(const C& aOther, StreamTime aStart, StreamTime aEnd)
   {
     AppendSliceInternal(aOther, aStart, aEnd);
   }
   /**
    * Replace the first aDuration ticks with null media data, because the data
    * will not be required again.
    */
-  virtual void ForgetUpTo(StreamTime aDuration)
+  virtual void ForgetUpTo(StreamTime aDuration) MOZ_OVERRIDE
   {
     if (mChunks.IsEmpty() || aDuration <= 0) {
       return;
     }
     if (mChunks[0].IsNull()) {
       StreamTime extraToForget = std::min(aDuration, mDuration) - mChunks[0].GetDuration();
       if (extraToForget > 0) {
         RemoveLeading(extraToForget, 1);
@@ -183,17 +183,17 @@ public:
         mDuration += extraToForget;
       }
       return;
     }
     RemoveLeading(aDuration, 0);
     mChunks.InsertElementAt(0)->SetNull(aDuration);
     mDuration += aDuration;
   }
-  virtual void FlushAfter(StreamTime aNewEnd)
+  virtual void FlushAfter(StreamTime aNewEnd) MOZ_OVERRIDE
   {
     if (mChunks.IsEmpty()) {
       return;
     }
 
     if (mChunks[0].IsNull()) {
       StreamTime extraToKeep = aNewEnd - mChunks[0].GetDuration();
       if (extraToKeep < 0) {
@@ -206,53 +206,53 @@ public:
       if (aNewEnd > mDuration) {
         NS_ASSERTION(aNewEnd <= mDuration, "can't add data in FlushAfter");
         return;
       }
       RemoveTrailing(aNewEnd, 0);
     }
     mDuration = aNewEnd;
   }
-  virtual void InsertNullDataAtStart(StreamTime aDuration)
+  virtual void InsertNullDataAtStart(StreamTime aDuration) MOZ_OVERRIDE
   {
     if (aDuration <= 0) {
       return;
     }
     if (!mChunks.IsEmpty() && mChunks[0].IsNull()) {
       mChunks[0].mDuration += aDuration;
     } else {
       mChunks.InsertElementAt(0)->SetNull(aDuration);
     }
 #ifdef MOZILLA_INTERNAL_API
     mChunks[0].mTimeStamp = mozilla::TimeStamp::Now();
 #endif
     mDuration += aDuration;
   }
-  virtual void AppendNullData(StreamTime aDuration)
+  virtual void AppendNullData(StreamTime aDuration) MOZ_OVERRIDE
   {
     if (aDuration <= 0) {
       return;
     }
     if (!mChunks.IsEmpty() && mChunks[mChunks.Length() - 1].IsNull()) {
       mChunks[mChunks.Length() - 1].mDuration += aDuration;
     } else {
       mChunks.AppendElement()->SetNull(aDuration);
     }
     mDuration += aDuration;
   }
-  virtual void ReplaceWithDisabled()
+  virtual void ReplaceWithDisabled() MOZ_OVERRIDE
   {
     if (GetType() != AUDIO) {
       MOZ_CRASH("Disabling unknown segment type");
     }
     StreamTime duration = GetDuration();
     Clear();
     AppendNullData(duration);
   }
-  virtual void Clear()
+  virtual void Clear() MOZ_OVERRIDE
   {
     mDuration = 0;
     mChunks.Clear();
   }
 
   class ChunkIterator {
   public:
     explicit ChunkIterator(MediaSegmentBase<C, Chunk>& aSegment)
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1708,27 +1708,28 @@ MediaStreamGraphImpl::RunInStableState(b
   }
 
   // Make sure we get a new current time in the next event loop task
   if (!aSourceIsMSG) {
     MOZ_ASSERT(mPostedRunInStableState);
     mPostedRunInStableState = false;
   }
 
-  for (uint32_t i = 0; i < runnables.Length(); ++i) {
-    runnables[i]->Run();
-  }
   for (uint32_t i = 0; i < controlMessagesToRunDuringShutdown.Length(); ++i) {
     controlMessagesToRunDuringShutdown[i]->RunDuringShutdown();
   }
 
 #ifdef DEBUG
   mCanRunMessagesSynchronously = mDetectedNotRunning &&
     mLifecycleState >= LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
 #endif
+
+  for (uint32_t i = 0; i < runnables.Length(); ++i) {
+    runnables[i]->Run();
+  }
 }
 
 
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 void
 MediaStreamGraphImpl::EnsureRunInStableState()
 {
--- a/dom/media/MediaStreamGraph.h
+++ b/dom/media/MediaStreamGraph.h
@@ -688,20 +688,20 @@ public:
     mLastConsumptionState(MediaStreamListener::NOT_CONSUMED),
     mMutex("mozilla::media::SourceMediaStream"),
     mUpdateKnownTracksTime(0),
     mPullEnabled(false),
     mUpdateFinished(false),
     mNeedsMixing(false)
   {}
 
-  virtual SourceMediaStream* AsSourceStream() { return this; }
+  virtual SourceMediaStream* AsSourceStream() MOZ_OVERRIDE { return this; }
 
   // Media graph thread only
-  virtual void DestroyImpl();
+  virtual void DestroyImpl() MOZ_OVERRIDE;
 
   // Call these on any thread.
   /**
    * Enable or disable pulling. When pulling is enabled, NotifyPull
    * gets called on MediaStreamListeners for this stream during the
    * MediaStreamGraph control loop. Pulling is initially disabled.
    * Due to unavoidable race conditions, after a call to SetPullEnabled(false)
    * it is still possible for a NotifyPull to occur.
@@ -1064,17 +1064,17 @@ public:
   void Finish();
   /**
    * Set the autofinish flag on this stream (defaults to false). When this flag
    * is set, and all input streams are in the finished state (including if there
    * are no input streams), this stream automatically enters the finished state.
    */
   void SetAutofinish(bool aAutofinish);
 
-  virtual ProcessedMediaStream* AsProcessedStream() { return this; }
+  virtual ProcessedMediaStream* AsProcessedStream() MOZ_OVERRIDE { return this; }
 
   friend class MediaStreamGraphImpl;
 
   // Do not call these from outside MediaStreamGraph.cpp!
   virtual void AddInput(MediaInputPort* aPort);
   virtual void RemoveInput(MediaInputPort* aPort)
   {
     mInputs.RemoveElement(aPort);
@@ -1082,17 +1082,17 @@ public:
   bool HasInputPort(MediaInputPort* aPort)
   {
     return mInputs.Contains(aPort);
   }
   uint32_t InputPortCount()
   {
     return mInputs.Length();
   }
-  virtual void DestroyImpl();
+  virtual void DestroyImpl() MOZ_OVERRIDE;
   /**
    * This gets called after we've computed the blocking states for all
    * streams (mBlocked is up to date up to mStateComputedTime).
    * Also, we've produced output for all streams up to this one. If this stream
    * is not in a cycle, then all its source streams have produced data.
    * Generate output from aFrom to aTo.
    * This will be called on streams that have finished. Most stream types should
    * just return immediately if IsFinishedOnGraphThread(), but some may wish to
--- a/dom/media/SelfRef.h
+++ b/dom/media/SelfRef.h
@@ -32,16 +32,16 @@ public:
     if (mHeld) {
       mHeld = false;
       t->Release();
     }
   }
 
   operator bool() const { return mHeld; }
 
-  SelfReference(const SelfReference& aOther) MOZ_DELETE;
-  void operator=(const SelfReference& aOther) MOZ_DELETE;
+  SelfReference(const SelfReference& aOther) = delete;
+  void operator=(const SelfReference& aOther) = delete;
 private:
   bool mHeld;
 };
 } // mozilla
 
 #endif // SELF_REF_H
--- a/dom/media/SharedThreadPool.h
+++ b/dom/media/SharedThreadPool.h
@@ -38,19 +38,19 @@ public:
   // Spins the event loop until all thread pools are shutdown.
   // *Must* be called on the main thread.
   static void SpinUntilShutdown();
 
   // We implement custom threadsafe AddRef/Release pair, that destroys the
   // the shared pool singleton when the refcount drops to 0. The addref/release
   // are implemented using locking, so it's not recommended that you use them
   // in a tight loop.
-  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
-  NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
-  NS_IMETHOD_(MozExternalRefCountType) Release(void);
+  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) MOZ_OVERRIDE;
+  NS_IMETHOD_(MozExternalRefCountType) AddRef(void) MOZ_OVERRIDE;
+  NS_IMETHOD_(MozExternalRefCountType) Release(void) MOZ_OVERRIDE;
 
   // Forward behaviour to wrapped thread pool implementation.
   NS_FORWARD_SAFE_NSITHREADPOOL(mPool);
   NS_FORWARD_SAFE_NSIEVENTTARGET(mEventTarget);
 
 private:
 
   // Creates necessary statics.
--- a/dom/media/VideoStreamTrack.h
+++ b/dom/media/VideoStreamTrack.h
@@ -14,18 +14,18 @@ namespace dom {
 
 class VideoStreamTrack : public MediaStreamTrack {
 public:
   VideoStreamTrack(DOMMediaStream* aStream, TrackID aTrackID)
     : MediaStreamTrack(aStream, aTrackID) {}
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
-  virtual VideoStreamTrack* AsVideoStreamTrack() { return this; }
+  virtual VideoStreamTrack* AsVideoStreamTrack() MOZ_OVERRIDE { return this; }
 
   // WebIDL
-  virtual void GetKind(nsAString& aKind) { aKind.AssignLiteral("video"); }
+  virtual void GetKind(nsAString& aKind) MOZ_OVERRIDE { aKind.AssignLiteral("video"); }
 };
 
 }
 }
 
 #endif /* VIDEOSTREAMTRACK_H_ */
--- a/dom/media/eme/CDMCallbackProxy.cpp
+++ b/dom/media/eme/CDMCallbackProxy.cpp
@@ -18,46 +18,46 @@
 namespace mozilla {
 
 CDMCallbackProxy::CDMCallbackProxy(CDMProxy* aProxy)
   : mProxy(aProxy)
 {
 
 }
 
-class NewSessionTask : public nsRunnable {
+class SetSessionIdTask : public nsRunnable {
 public:
-  NewSessionTask(CDMProxy* aProxy,
-                 uint32_t aPromiseId,
-                 const nsCString& aSessionId)
+  SetSessionIdTask(CDMProxy* aProxy,
+                   uint32_t aToken,
+                   const nsCString& aSessionId)
     : mProxy(aProxy)
-    , mPid(aPromiseId)
+    , mToken(aToken)
     , mSid(NS_ConvertUTF8toUTF16(aSessionId))
   {
   }
 
   NS_IMETHOD Run() {
-    mProxy->OnResolveNewSessionPromise(mPid, mSid);
+    mProxy->OnSetSessionId(mToken, mSid);
     return NS_OK;
   }
 
   nsRefPtr<CDMProxy> mProxy;
-  dom::PromiseId mPid;
+  uint32_t mToken;
   nsString mSid;
 };
 
 void
-CDMCallbackProxy::ResolveNewSessionPromise(uint32_t aPromiseId,
-                                           const nsCString& aSessionId)
+CDMCallbackProxy::SetSessionId(uint32_t aToken,
+                               const nsCString& aSessionId)
 {
   MOZ_ASSERT(mProxy->IsOnGMPThread());
 
-  nsRefPtr<nsIRunnable> task(new NewSessionTask(mProxy,
-                                                aPromiseId,
-                                                aSessionId));
+  nsRefPtr<nsIRunnable> task(new SetSessionIdTask(mProxy,
+                                                  aToken,
+                                                  aSessionId));
   NS_DispatchToMainThread(task);
 }
 
 class LoadSessionTask : public nsRunnable {
 public:
   LoadSessionTask(CDMProxy* aProxy,
                   uint32_t aPromiseId,
                   bool aSuccess)
--- a/dom/media/eme/CDMCallbackProxy.h
+++ b/dom/media/eme/CDMCallbackProxy.h
@@ -12,18 +12,18 @@
 #include "GMPDecryptorProxy.h"
 
 namespace mozilla {
 
 // Proxies call backs from the CDM on the GMP thread back to the MediaKeys
 // object on the main thread.
 class CDMCallbackProxy : public GMPDecryptorProxyCallback {
 public:
-  virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
-                                        const nsCString& aSessionId) MOZ_OVERRIDE;
+  virtual void SetSessionId(uint32_t aCreateSessionToken,
+                            const nsCString& aSessionId) MOZ_OVERRIDE;
 
   virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
                                          bool aSuccess) MOZ_OVERRIDE;
 
   virtual void ResolvePromise(uint32_t aPromiseId) MOZ_OVERRIDE;
 
   virtual void RejectPromise(uint32_t aPromiseId,
                              nsresult aException,
--- a/dom/media/eme/CDMCaps.h
+++ b/dom/media/eme/CDMCaps.h
@@ -106,15 +106,15 @@ private:
   nsTArray<UsableKey> mUsableKeyIds;
 
   nsTArray<WaitForKeys> mWaitForKeys;
 
   nsTArray<nsRefPtr<nsIRunnable>> mWaitForCaps;
   uint64_t mCaps;
 
   // It is not safe to copy this object.
-  CDMCaps(const CDMCaps&) MOZ_DELETE;
-  CDMCaps& operator=(const CDMCaps&) MOZ_DELETE;
+  CDMCaps(const CDMCaps&) = delete;
+  CDMCaps& operator=(const CDMCaps&) = delete;
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/eme/CDMProxy.cpp
+++ b/dom/media/eme/CDMProxy.cpp
@@ -133,26 +133,28 @@ CDMProxy::OnCDMCreated(uint32_t aPromise
   if (mKeys.IsNull()) {
     return;
   }
   MOZ_ASSERT(!GetNodeId().IsEmpty());
   mKeys->OnCDMCreated(aPromiseId, GetNodeId());
 }
 
 void
-CDMProxy::CreateSession(dom::SessionType aSessionType,
+CDMProxy::CreateSession(uint32_t aCreateSessionToken,
+                        dom::SessionType aSessionType,
                         PromiseId aPromiseId,
                         const nsAString& aInitDataType,
                         nsTArray<uint8_t>& aInitData)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mGMPThread);
 
   nsAutoPtr<CreateSessionData> data(new CreateSessionData());
   data->mSessionType = aSessionType;
+  data->mCreateSessionToken = aCreateSessionToken;
   data->mPromiseId = aPromiseId;
   data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
   data->mInitData = Move(aInitData);
 
   nsRefPtr<nsIRunnable> task(
     NS_NewRunnableMethodWithArg<nsAutoPtr<CreateSessionData>>(this, &CDMProxy::gmp_CreateSession, data));
   mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
@@ -169,17 +171,18 @@ ToGMPSessionType(dom::SessionType aSessi
 void
 CDMProxy::gmp_CreateSession(nsAutoPtr<CreateSessionData> aData)
 {
   MOZ_ASSERT(IsOnGMPThread());
   if (!mCDM) {
     RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
-  mCDM->CreateSession(aData->mPromiseId,
+  mCDM->CreateSession(aData->mCreateSessionToken,
+                      aData->mPromiseId,
                       aData->mInitDataType,
                       aData->mInitData,
                       ToGMPSessionType(aData->mSessionType));
 }
 
 void
 CDMProxy::LoadSession(PromiseId aPromiseId,
                       const nsAString& aSessionId)
@@ -379,24 +382,26 @@ CDMProxy::ResolvePromise(PromiseId aId)
 
 const nsCString&
 CDMProxy::GetNodeId() const
 {
   return mNodeId;
 }
 
 void
-CDMProxy::OnResolveNewSessionPromise(uint32_t aPromiseId,
-                                     const nsAString& aSessionId)
+CDMProxy::OnSetSessionId(uint32_t aCreateSessionToken,
+                         const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
-  mKeys->OnSessionCreated(aPromiseId, aSessionId);
+
+  nsRefPtr<dom::MediaKeySession> session(mKeys->GetPendingSession(aCreateSessionToken));
+  session->SetSessionId(aSessionId);
 }
 
 void
 CDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
--- a/dom/media/eme/CDMProxy.h
+++ b/dom/media/eme/CDMProxy.h
@@ -52,17 +52,18 @@ public:
             const nsAString& aOrigin,
             const nsAString& aTopLevelOrigin,
             bool aInPrivateBrowsing);
 
   // Main thread only.
   // Uses the CDM to create a key session.
   // Calls MediaKeys::OnSessionActivated() when session is created.
   // Assumes ownership of (Move()s) aInitData's contents.
-  void CreateSession(dom::SessionType aSessionType,
+  void CreateSession(uint32_t aCreateSessionToken,
+                     dom::SessionType aSessionType,
                      PromiseId aPromiseId,
                      const nsAString& aInitDataType,
                      nsTArray<uint8_t>& aInitData);
 
   // Main thread only.
   // Uses the CDM to load a presistent session stored on disk.
   // Calls MediaKeys::OnSessionActivated() when session is loaded.
   void LoadSession(PromiseId aPromiseId,
@@ -106,18 +107,18 @@ public:
 
   // Main thread only.
   void Terminated();
 
   // Threadsafe.
   const nsCString& GetNodeId() const;
 
   // Main thread only.
-  void OnResolveNewSessionPromise(uint32_t aPromiseId,
-                                  const nsAString& aSessionId);
+  void OnSetSessionId(uint32_t aCreateSessionToken,
+                      const nsAString& aSessionId);
 
   // Main thread only.
   void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess);
 
   // Main thread only.
   void OnSessionMessage(const nsAString& aSessionId,
                         nsTArray<uint8_t>& aMessage,
                         const nsAString& aDestinationURL);
@@ -184,16 +185,17 @@ private:
   // GMP thread only.
   void gmp_Shutdown();
 
   // Main thread only.
   void OnCDMCreated(uint32_t aPromiseId);
 
   struct CreateSessionData {
     dom::SessionType mSessionType;
+    uint32_t mCreateSessionToken;
     PromiseId mPromiseId;
     nsAutoCString mInitDataType;
     nsTArray<uint8_t> mInitData;
   };
   // GMP thread only.
   void gmp_CreateSession(nsAutoPtr<CreateSessionData> aData);
 
   struct SessionOpData {
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -25,35 +25,44 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(Media
                                    mClosed)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeySession)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(MediaKeySession, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(MediaKeySession, DOMEventTargetHelper)
 
+// Count of number of instances. Used to give each instance a
+// unique token.
+static uint32_t sMediaKeySessionNum = 0;
+
 MediaKeySession::MediaKeySession(nsPIDOMWindow* aParent,
                                  MediaKeys* aKeys,
                                  const nsAString& aKeySystem,
                                  SessionType aSessionType,
                                  ErrorResult& aRv)
   : DOMEventTargetHelper(aParent)
   , mKeys(aKeys)
   , mKeySystem(aKeySystem)
   , mSessionType(aSessionType)
+  , mToken(sMediaKeySessionNum++)
   , mIsClosed(false)
   , mUninitialized(true)
 {
   MOZ_ASSERT(aParent);
   mClosed = mKeys->MakePromise(aRv);
 }
 
-void MediaKeySession::Init(const nsAString& aSessionId)
+void MediaKeySession::SetSessionId(const nsAString& aSessionId)
 {
+  if (NS_WARN_IF(!mSessionId.IsEmpty())) {
+    return;
+  }
   mSessionId = aSessionId;
+  mKeys->OnSessionIdReady(this);
 }
 
 MediaKeySession::~MediaKeySession()
 {
 }
 
 MediaKeyError*
 MediaKeySession::GetError() const
@@ -117,19 +126,18 @@ MediaKeySession::GenerateRequest(const n
   nsTArray<uint8_t> data;
   if (aInitDataType.IsEmpty() ||
       !CopyArrayBufferViewOrArrayBufferData(aInitData, data)) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return promise.forget();
   }
 
   PromiseId pid = mKeys->StorePromise(promise);
-  mKeys->OnSessionPending(pid, this);
-
-  mKeys->GetCDMProxy()->CreateSession(mSessionType,
+  mKeys->GetCDMProxy()->CreateSession(Token(),
+                                      mSessionType,
                                       pid,
                                       aInitDataType, data);
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv)
@@ -147,21 +155,25 @@ MediaKeySession::Load(const nsAString& a
 
   if (!mUninitialized) {
     promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return promise.forget();
   }
 
   mUninitialized = false;
 
-  Init(aSessionId);
-  auto pid = mKeys->StorePromise(promise);
-  mKeys->OnSessionPending(pid, this);
+  // We now know the sessionId being loaded into this session. Remove the
+  // session from its owning MediaKey's set of sessions awaiting a sessionId.
+  nsRefPtr<MediaKeySession> session(mKeys->GetPendingSession(Token()));
+  MOZ_ASSERT(session == this, "Session should be awaiting id on its own token");
 
-  mKeys->GetCDMProxy()->LoadSession(pid, aSessionId);
+  // Associate with the known sessionId.
+  SetSessionId(aSessionId);
+
+  mKeys->GetCDMProxy()->LoadSession(mKeys->StorePromise(promise), aSessionId);
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv)
 {
   nsRefPtr<Promise> promise(mKeys->MakePromise(aRv));
@@ -290,10 +302,16 @@ MediaKeySession::DispatchKeysChange()
   if (IsClosed()) {
     return;
   }
   nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
     new AsyncEventDispatcher(this, NS_LITERAL_STRING("keyschange"), false);
   asyncDispatcher->PostDOMEvent();
 }
 
+uint32_t
+MediaKeySession::Token() const
+{
+  return mToken;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/eme/MediaKeySession.h
+++ b/dom/media/eme/MediaKeySession.h
@@ -38,17 +38,17 @@ public:
                                            DOMEventTargetHelper)
 public:
   MediaKeySession(nsPIDOMWindow* aParent,
                   MediaKeys* aKeys,
                   const nsAString& aKeySystem,
                   SessionType aSessionType,
                   ErrorResult& aRv);
 
-  void Init(const nsAString& aSessionId);
+  void SetSessionId(const nsAString& aSessionId);
 
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // Mark this as resultNotAddRefed to return raw pointers
   MediaKeyError* GetError() const;
 
   void GetKeySystem(nsString& aRetval) const;
 
@@ -85,26 +85,30 @@ public:
   void DispatchKeyError(uint32_t system_code);
 
   void DispatchKeysChange();
 
   void OnClosed();
 
   bool IsClosed() const;
 
+  // Process-unique identifier.
+  uint32_t Token() const;
+
 private:
   ~MediaKeySession();
 
   nsRefPtr<Promise> mClosed;
 
   nsRefPtr<MediaKeyError> mMediaKeyError;
   nsRefPtr<MediaKeys> mKeys;
   const nsString mKeySystem;
   nsString mSessionId;
   const SessionType mSessionType;
+  const uint32_t mToken;
   bool mIsClosed;
   bool mUninitialized;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -203,16 +203,38 @@ MediaKeys::RejectPromise(PromiseId aId, 
 
   if (mCreatePromiseId == aId) {
     // Note: This will probably destroy the MediaKeys object!
     Release();
   }
 }
 
 void
+MediaKeys::OnSessionIdReady(MediaKeySession* aSession)
+{
+  if (!aSession) {
+    NS_WARNING("Invalid MediaKeySession passed to OnSessionIdReady()");
+    return;
+  }
+  if (mKeySessions.Contains(aSession->GetSessionId())) {
+    NS_WARNING("MediaKeySession's made ready multiple times!");
+    return;
+  }
+  if (mPendingSessions.Contains(aSession->Token())) {
+    NS_WARNING("MediaKeySession made ready when it wasn't waiting to be ready!");
+    return;
+  }
+  if (aSession->GetSessionId().IsEmpty()) {
+    NS_WARNING("MediaKeySession with invalid sessionId passed to OnSessionIdReady()");
+    return;
+  }
+  mKeySessions.Put(aSession->GetSessionId(), aSession);
+}
+
+void
 MediaKeys::ResolvePromise(PromiseId aId)
 {
   nsRefPtr<Promise> promise(RetrievePromise(aId));
   if (!promise) {
     NS_WARNING("MediaKeys tried to resolve a non-existent promise");
     return;
   }
   if (mPendingSessions.Contains(aId)) {
@@ -341,80 +363,30 @@ MediaKeys::CreateSession(SessionType aSe
                          ErrorResult& aRv)
 {
   nsRefPtr<MediaKeySession> session = new MediaKeySession(GetParentObject(),
                                                           this,
                                                           mKeySystem,
                                                           aSessionType,
                                                           aRv);
 
-  return session.forget();
-}
-
-void
-MediaKeys::OnSessionPending(PromiseId aId, MediaKeySession* aSession)
-{
-  MOZ_ASSERT(mPromises.Contains(aId));
-  MOZ_ASSERT(!mPendingSessions.Contains(aId));
-  mPendingSessions.Put(aId, aSession);
-}
+  // Add session to the set of sessions awaiting their sessionId being ready.
+  mPendingSessions.Put(session->Token(), session);
 
-void
-MediaKeys::OnSessionCreated(PromiseId aId, const nsAString& aSessionId)
-{
-  nsRefPtr<Promise> promise(RetrievePromise(aId));
-  if (!promise) {
-    NS_WARNING("MediaKeys tried to resolve a non-existent promise");
-    return;
-  }
-  MOZ_ASSERT(mPendingSessions.Contains(aId));
-
-  nsRefPtr<MediaKeySession> session;
-  bool gotSession = mPendingSessions.Get(aId, getter_AddRefs(session));
-  // Session has completed creation/loading, remove it from mPendingSessions,
-  // and resolve the promise with it. We store it in mKeySessions, so we can
-  // find it again if we need to send messages to it etc.
-  mPendingSessions.Remove(aId);
-  if (!gotSession || !session) {
-    NS_WARNING("Received activation for non-existent session!");
-    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    return;
-  }
-
-  session->Init(aSessionId);
-  mKeySessions.Put(aSessionId, session);
-  promise->MaybeResolve(session);
+  return session.forget();
 }
 
 void
 MediaKeys::OnSessionLoaded(PromiseId aId, bool aSuccess)
 {
   nsRefPtr<Promise> promise(RetrievePromise(aId));
   if (!promise) {
     NS_WARNING("MediaKeys tried to resolve a non-existent promise");
     return;
   }
-  MOZ_ASSERT(mPendingSessions.Contains(aId));
-
-  nsRefPtr<MediaKeySession> session;
-  bool gotSession = mPendingSessions.Get(aId, getter_AddRefs(session));
-  // Session has completed creation/loading, remove it from mPendingSessions,
-  // and resolve the promise with it. We store it in mKeySessions, so we can
-  // find it again if we need to send messages to it etc.
-  mPendingSessions.Remove(aId);
-  if (!gotSession || !session) {
-    NS_WARNING("Received activation for non-existent session!");
-    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
-    return;
-  }
-
-  MOZ_ASSERT(!session->GetSessionId().IsEmpty() &&
-             !mKeySessions.Contains(session->GetSessionId()));
-
-  mKeySessions.Put(session->GetSessionId(), session);
   promise->MaybeResolve(aSuccess);
 }
 
 void
 MediaKeys::OnSessionClosed(MediaKeySession* aSession)
 {
   nsAutoString id;
   aSession->GetSessionId(id);
@@ -424,16 +396,25 @@ MediaKeys::OnSessionClosed(MediaKeySessi
 already_AddRefed<MediaKeySession>
 MediaKeys::GetSession(const nsAString& aSessionId)
 {
   nsRefPtr<MediaKeySession> session;
   mKeySessions.Get(aSessionId, getter_AddRefs(session));
   return session.forget();
 }
 
+already_AddRefed<MediaKeySession>
+MediaKeys::GetPendingSession(uint32_t aToken)
+{
+  nsRefPtr<MediaKeySession> session;
+  mPendingSessions.Get(aToken, getter_AddRefs(session));
+  mPendingSessions.Remove(aToken);
+  return session.forget();
+}
+
 const nsCString&
 MediaKeys::GetNodeId() const
 {
   MOZ_ASSERT(NS_IsMainThread());
   return mNodeId;
 }
 
 bool
--- a/dom/media/eme/MediaKeys.h
+++ b/dom/media/eme/MediaKeys.h
@@ -69,25 +69,31 @@ public:
                                                   ErrorResult& aRv);
 
   // JavaScript: MediaKeys.SetServerCertificate()
   already_AddRefed<Promise> SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aServerCertificate,
                                                  ErrorResult& aRv);
 
   already_AddRefed<MediaKeySession> GetSession(const nsAString& aSessionId);
 
-  // Called once a Create() operation succeeds.
+  // Removes and returns MediaKeySession from the set of sessions awaiting
+  // their sessionId to be assigned.
+  already_AddRefed<MediaKeySession> GetPendingSession(uint32_t aToken);
+
+  // Called once a Init() operation succeeds.
   void OnCDMCreated(PromiseId aId, const nsACString& aNodeId);
-  // Called when GenerateRequest or Load have been called on a MediaKeySession
-  // and we are waiting for its initialisation to finish.
-  void OnSessionPending(PromiseId aId, MediaKeySession* aSession);
-  // Called once a CreateSession succeeds.
-  void OnSessionCreated(PromiseId aId, const nsAString& aSessionId);
+
+  // Called once the CDM generates a sessionId while servicing a
+  // MediaKeySession.generateRequest() or MediaKeySession.load() call,
+  // once the sessionId of a MediaKeySession is known.
+  void OnSessionIdReady(MediaKeySession* aSession);
+
   // Called once a LoadSession succeeds.
   void OnSessionLoaded(PromiseId aId, bool aSuccess);
+
   // Called once a session has closed.
   void OnSessionClosed(MediaKeySession* aSession);
 
   CDMProxy* GetCDMProxy() { return mProxy; }
 
   // Makes a new promise, or nullptr on failure.
   already_AddRefed<Promise> MakePromise(ErrorResult& aRv);
   // Stores promise in mPromises, returning an ID that can be used to retrieve
--- a/dom/media/encoder/OpusTrackEncoder.h
+++ b/dom/media/encoder/OpusTrackEncoder.h
@@ -32,17 +32,17 @@ public:
   OpusTrackEncoder();
   virtual ~OpusTrackEncoder();
 
   already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
 
   nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE;
 
 protected:
-  int GetPacketDuration();
+  int GetPacketDuration() MOZ_OVERRIDE;
 
   nsresult Init(int aChannels, int aSamplingRate) MOZ_OVERRIDE;
 
   /**
    * Get the samplerate of the data to be fed to the Opus encoder. This might be
    * different from the input samplerate if resampling occurs.
    */
   int GetOutputSampleRate();
--- a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h
+++ b/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h
@@ -61,17 +61,17 @@ public:
     ~BoxSizeChecker();
 
     uint32_t ori_size;
     uint32_t box_size;
     ISOControl* mControl;
   };
 
 protected:
-  Box() MOZ_DELETE;
+  Box() = delete;
   Box(const nsACString& aType, ISOControl* aControl);
 
   ISOControl* mControl;
   nsRefPtr<AudioTrackMetadata> mAudioMeta;
   nsRefPtr<VideoTrackMetadata> mVideoMeta;
 };
 
 /**
@@ -89,17 +89,17 @@ public:
 
   // MuxerOperation methods
   nsresult Write() MOZ_OVERRIDE;
 
 protected:
   // FullBox methods
   FullBox(const nsACString& aType, uint8_t aVersion, uint32_t aFlags,
           ISOControl* aControl);
-  FullBox() MOZ_DELETE;
+  FullBox() = delete;
 };
 
 /**
  * The default implementation of the container box.
  * Basically, the container box inherits this class and overrides the
  * constructor only.
  *
  * According to 14496-12 3.1.1 'container box', a container box is
@@ -113,17 +113,17 @@ public:
   nsresult Generate(uint32_t* aBoxSize) MOZ_OVERRIDE;
   nsresult Write() MOZ_OVERRIDE;
   nsresult Find(const nsACString& aType,
                 nsTArray<nsRefPtr<MuxerOperation>>& aOperations) MOZ_OVERRIDE;
 
 protected:
   // DefaultContainerImpl methods
   DefaultContainerImpl(const nsACString& aType, ISOControl* aControl);
-  DefaultContainerImpl() MOZ_DELETE;
+  DefaultContainerImpl() = delete;
 
   nsTArray<nsRefPtr<MuxerOperation>> boxes;
 };
 
 // 14496-12 4.3 'File Type Box'
 // Box type: 'ftyp'
 class FileTypeBox : public Box {
 public:
@@ -497,17 +497,17 @@ public:
 
   // sampleentrybox methods
   SampleEntryBox(const nsACString& aFormat, ISOControl* aControl);
 
   // MuxerOperation methods
   nsresult Write() MOZ_OVERRIDE;
 
 protected:
-  SampleEntryBox() MOZ_DELETE;
+  SampleEntryBox() = delete;
 };
 
 // 14496-12 8.5.2 'Sample Description Box'
 // Box type: 'stsd'
 class SampleDescriptionBox : public FullBox {
 public:
   // ISO BMFF members
   uint32_t entry_count;
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -11,16 +11,17 @@
 #include "nsCharSeparatedTokenizer.h"
 #ifdef MOZ_EME
 #include "mozilla/CDMProxy.h"
 #endif
 #include "prlog.h"
 
 #ifdef XP_WIN
 #include "mozilla/WindowsVersion.h"
+#include "WMFDecoderModule.h"
 #endif
 #ifdef MOZ_FFMPEG
 #include "FFmpegRuntimeLinker.h"
 #endif
 #ifdef MOZ_APPLEMEDIA
 #include "apple/AppleDecoderModule.h"
 #endif
 #ifdef MOZ_WIDGET_ANDROID
@@ -58,16 +59,22 @@ static bool
 IsSupportedAudioCodec(const nsAString& aCodec,
                       bool& aOutContainsAAC,
                       bool& aOutContainsMP3)
 {
   // AAC-LC or HE-AAC in M4A.
   aOutContainsAAC = aCodec.EqualsASCII("mp4a.40.2") ||
                     aCodec.EqualsASCII("mp4a.40.5");
   if (aOutContainsAAC) {
+#ifdef XP_WIN
+    if (!Preferences::GetBool("media.fragmented-mp4.use-blank-decoder") &&
+        !WMFDecoderModule::HasAAC()) {
+      return false;
+    }
+#endif
     return true;
   }
 #ifndef MOZ_GONK_MEDIACODEC // B2G doesn't support MP3 in MP4 yet.
   aOutContainsMP3 = aCodec.EqualsASCII("mp3");
   if (aOutContainsMP3) {
     return true;
   }
 #else
@@ -80,16 +87,23 @@ static bool
 IsSupportedH264Codec(const nsAString& aCodec)
 {
   int16_t profile = 0, level = 0;
 
   if (!ExtractH264CodecDetails(aCodec, profile, level)) {
     return false;
   }
 
+#ifdef XP_WIN
+  if (!Preferences::GetBool("media.fragmented-mp4.use-blank-decoder") &&
+      !WMFDecoderModule::HasH264()) {
+    return false;
+  }
+#endif
+
   // Just assume what we can play on all platforms the codecs/formats that
   // WMF can play, since we don't have documentation about what other
   // platforms can play... According to the WMF documentation:
   // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815%28v=vs.85%29.aspx
   // "The Media Foundation H.264 video decoder is a Media Foundation Transform
   // that supports decoding of Baseline, Main, and High profiles, up to level
   // 5.1.". We also report that we can play Extended profile, as there are
   // bitstreams that are Extended compliant that are also Baseline compliant.
--- a/dom/media/fmp4/MP4Decoder.h
+++ b/dom/media/fmp4/MP4Decoder.h
@@ -10,24 +10,24 @@
 
 namespace mozilla {
 
 // Decoder that uses a bundled MP4 demuxer and platform decoders to play MP4.
 class MP4Decoder : public MediaDecoder
 {
 public:
 
-  virtual MediaDecoder* Clone() {
+  virtual MediaDecoder* Clone() MOZ_OVERRIDE {
     if (!IsEnabled()) {
       return nullptr;
     }
     return new MP4Decoder();
   }
 
-  virtual MediaDecoderStateMachine* CreateStateMachine();
+  virtual MediaDecoderStateMachine* CreateStateMachine() MOZ_OVERRIDE;
 
 #ifdef MOZ_EME
   virtual nsresult SetCDMProxy(CDMProxy* aProxy) MOZ_OVERRIDE;
 #endif
 
   // Returns true if aMIMEType is a type that we think we can render with the
   // a MP4 platform decoder backend. If aCodecs is non emtpy, it is filled
   // with a comma-delimited list of codecs to check support for. Notes in
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
@@ -76,38 +76,38 @@ private:
   public:
     MessageHandler(GonkVideoDecoderManager *aManager);
     ~MessageHandler();
 
     virtual void onMessageReceived(const android::sp<android::AMessage> &aMessage);
 
   private:
     // Forbidden
-    MessageHandler() MOZ_DELETE;
-    MessageHandler(const MessageHandler &rhs) MOZ_DELETE;
-    const MessageHandler &operator=(const MessageHandler &rhs) MOZ_DELETE;
+    MessageHandler() = delete;
+    MessageHandler(const MessageHandler &rhs) = delete;
+    const MessageHandler &operator=(const MessageHandler &rhs) = delete;
 
     GonkVideoDecoderManager *mManager;
   };
   friend class MessageHandler;
 
   class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
   {
   public:
     VideoResourceListener(GonkVideoDecoderManager *aManager);
     ~VideoResourceListener();
 
     virtual void codecReserved() MOZ_OVERRIDE;
     virtual void codecCanceled() MOZ_OVERRIDE;
 
   private:
     // Forbidden
-    VideoResourceListener() MOZ_DELETE;
-    VideoResourceListener(const VideoResourceListener &rhs) MOZ_DELETE;
-    const VideoResourceListener &operator=(const VideoResourceListener &rhs) MOZ_DELETE;
+    VideoResourceListener() = delete;
+    VideoResourceListener(const VideoResourceListener &rhs) = delete;
+    const VideoResourceListener &operator=(const VideoResourceListener &rhs) = delete;
 
     GonkVideoDecoderManager *mManager;
   };
   friend class VideoResourceListener;
 
   // FrameTimeInfo keeps the presentation time stamp (pts) and its duration.
   // On MediaDecoderStateMachine, it needs pts and duration to display decoded
   // frame correctly. But OMX can carry one field of time info (kKeyTime) so
--- a/dom/media/fmp4/wmf/WMFDecoderModule.cpp
+++ b/dom/media/fmp4/wmf/WMFDecoderModule.cpp
@@ -7,16 +7,18 @@
 #include "WMF.h"
 #include "WMFDecoderModule.h"
 #include "WMFDecoder.h"
 #include "WMFVideoMFTManager.h"
 #include "WMFAudioMFTManager.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/DebugOnly.h"
 #include "WMFMediaDataDecoder.h"
+#include "nsIWindowsRegKey.h"
+#include "nsComponentManagerUtils.h"
 
 namespace mozilla {
 
 bool WMFDecoderModule::sIsWMFEnabled = false;
 bool WMFDecoderModule::sDXVAEnabled = false;
 
 WMFDecoderModule::WMFDecoderModule()
 {
@@ -102,9 +104,48 @@ WMFDecoderModule::SupportsVideoMimeType(
 
 bool
 WMFDecoderModule::SupportsAudioMimeType(const char* aMimeType)
 {
   return !strcmp(aMimeType, "audio/mp4a-latm") ||
          !strcmp(aMimeType, "audio/mpeg");
 }
 
+static bool
+ClassesRootRegKeyExists(const nsAString& aRegKeyPath)
+{
+  nsresult rv;
+
+  nsCOMPtr<nsIWindowsRegKey> regKey =
+    do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
+                    aRegKeyPath,
+                    nsIWindowsRegKey::ACCESS_READ);
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  regKey->Close();
+
+  return true;
+}
+
+/* static */ bool
+WMFDecoderModule::HasH264()
+{
+  // CLSID_CMSH264DecoderMFT
+  return ClassesRootRegKeyExists(
+    NS_LITERAL_STRING("CLSID\\{32D186A7-218F-4C75-8876-DD77273A8999}"));
+}
+
+/* static */ bool
+WMFDecoderModule::HasAAC()
+{
+  // CLSID_CMSAACDecMFT
+  return ClassesRootRegKeyExists(
+    NS_LITERAL_STRING("CLSID\\{62CE7E72-4C71-4D20-B15D-452831A87D9D}"));
+}
+
 } // namespace mozilla
--- a/dom/media/fmp4/wmf/WMFDecoderModule.h
+++ b/dom/media/fmp4/wmf/WMFDecoderModule.h
@@ -32,16 +32,23 @@ public:
   virtual already_AddRefed<MediaDataDecoder>
   CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
                      MediaTaskQueue* aAudioTaskQueue,
                      MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
   bool SupportsVideoMimeType(const char* aMimeType) MOZ_OVERRIDE;
   bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE;
 
+  // Accessors that report whether we have the required MFTs available
+  // on the system to play various codecs. Windows Vista doesn't have the
+  // H.264/AAC decoders if the "Platform Update Supplement for Windows Vista"
+  // is not installed.
+  static bool HasAAC();
+  static bool HasH264();
+
   // Called on main thread.
   static void Init();
 private:
   static bool sIsWMFEnabled;
   static bool sDXVAEnabled;
 };
 
 } // namespace mozilla
--- a/dom/media/gmp-plugin/fake.info
+++ b/dom/media/gmp-plugin/fake.info
@@ -1,5 +1,5 @@
 Name: fake
 Description: Fake GMP Plugin
 Version: 1.0
-APIs: encode-video[h264], decode-video[h264], eme-decrypt[fake]
+APIs: encode-video[h264], decode-video[h264], eme-decrypt-v2[fake]
 Libraries: dxva2.dll
--- a/dom/media/gmp-plugin/gmp-test-decryptor.h
+++ b/dom/media/gmp-plugin/gmp-test-decryptor.h
@@ -15,17 +15,18 @@ class FakeDecryptor : public GMPDecrypto
 public:
 
   explicit FakeDecryptor(GMPDecryptorHost* aHost);
 
   virtual void Init(GMPDecryptorCallback* aCallback) MOZ_OVERRIDE {
     mCallback = aCallback;
   }
 
-  virtual void CreateSession(uint32_t aPromiseId,
+  virtual void CreateSession(uint32_t aCreateSessionToken,
+                             uint32_t aPromiseId,
                              const char* aInitDataType,
                              uint32_t aInitDataTypeSize,
                              const uint8_t* aInitData,
                              uint32_t aInitDataSize,
                              GMPSessionType aSessionType) MOZ_OVERRIDE
   {
   }
 
--- a/dom/media/gmp/GMPDecryptorChild.cpp
+++ b/dom/media/gmp/GMPDecryptorChild.cpp
@@ -44,22 +44,22 @@ GMPDecryptorChild::~GMPDecryptorChild()
 void
 GMPDecryptorChild::Init(GMPDecryptor* aSession)
 {
   MOZ_ASSERT(aSession);
   mSession = aSession;
 }
 
 void
-GMPDecryptorChild::ResolveNewSessionPromise(uint32_t aPromiseId,
-                                            const char* aSessionId,
-                                            uint32_t aSessionIdLength)
+GMPDecryptorChild::SetSessionId(uint32_t aCreateSessionToken,
+                                const char* aSessionId,
+                                uint32_t aSessionIdLength)
 {
-  CALL_ON_GMP_THREAD(SendResolveNewSessionPromise,
-                     aPromiseId, nsAutoCString(aSessionId, aSessionIdLength));
+  CALL_ON_GMP_THREAD(SendSetSessionId,
+                     aCreateSessionToken, nsAutoCString(aSessionId, aSessionIdLength));
 }
 
 void
 GMPDecryptorChild::ResolveLoadSessionPromise(uint32_t aPromiseId,
                                              bool aSuccess)
 {
   CALL_ON_GMP_THREAD(SendResolveLoadSessionPromise, aPromiseId, aSuccess);
 }
@@ -204,26 +204,28 @@ GMPDecryptorChild::RecvInit()
   if (!mSession) {
     return false;
   }
   mSession->Init(this);
   return true;
 }
 
 bool
-GMPDecryptorChild::RecvCreateSession(const uint32_t& aPromiseId,
+GMPDecryptorChild::RecvCreateSession(const uint32_t& aCreateSessionToken,
+                                     const uint32_t& aPromiseId,
                                      const nsCString& aInitDataType,
                                      const nsTArray<uint8_t>& aInitData,
                                      const GMPSessionType& aSessionType)
 {
   if (!mSession) {
     return false;
   }
 
-  mSession->CreateSession(aPromiseId,
+  mSession->CreateSession(aCreateSessionToken,
+                          aPromiseId,
                           aInitDataType.get(),
                           aInitDataType.Length(),
                           aInitData.Elements(),
                           aInitData.Length(),
                           aSessionType);
 
   return true;
 }
--- a/dom/media/gmp/GMPDecryptorChild.h
+++ b/dom/media/gmp/GMPDecryptorChild.h
@@ -26,19 +26,19 @@ public:
 
   explicit GMPDecryptorChild(GMPChild* aPlugin,
                              const nsTArray<uint8_t>& aPluginVoucher,
                              const nsTArray<uint8_t>& aSandboxVoucher);
 
   void Init(GMPDecryptor* aSession);
 
   // GMPDecryptorCallback
-  virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
-                                        const char* aSessionId,
-                                        uint32_t aSessionIdLength) MOZ_OVERRIDE;
+  virtual void SetSessionId(uint32_t aCreateSessionToken,
+                            const char* aSessionId,
+                            uint32_t aSessionIdLength) MOZ_OVERRIDE;
   virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
                                          bool aSuccess) MOZ_OVERRIDE;
   virtual void ResolvePromise(uint32_t aPromiseId) MOZ_OVERRIDE;
 
   virtual void RejectPromise(uint32_t aPromiseId,
                              GMPDOMException aException,
                              const char* aMessage,
                              uint32_t aMessageLength) MOZ_OVERRIDE;
@@ -85,17 +85,18 @@ public:
   virtual void GetPluginVoucher(const uint8_t** aVoucher,
                                 uint32_t* aVoucherLength) MOZ_OVERRIDE;
 private:
   ~GMPDecryptorChild();
 
   // GMPDecryptorChild
   virtual bool RecvInit() MOZ_OVERRIDE;
 
-  virtual bool RecvCreateSession(const uint32_t& aPromiseId,
+  virtual bool RecvCreateSession(const uint32_t& aCreateSessionToken,
+                                 const uint32_t& aPromiseId,
                                  const nsCString& aInitDataType,
                                  const nsTArray<uint8_t>& aInitData,
                                  const GMPSessionType& aSessionType) MOZ_OVERRIDE;
 
   virtual bool RecvLoadSession(const uint32_t& aPromiseId,
                                const nsCString& aSessionId) MOZ_OVERRIDE;
 
   virtual bool RecvUpdateSession(const uint32_t& aPromiseId,
@@ -105,17 +106,17 @@ private:
   virtual bool RecvCloseSession(const uint32_t& aPromiseId,
                                 const nsCString& aSessionId) MOZ_OVERRIDE;
 
   virtual bool RecvRemoveSession(const uint32_t& aPromiseId,
                                  const nsCString& aSessionId) MOZ_OVERRIDE;
 
   virtual bool RecvDecrypt(const uint32_t& aId,
                            const nsTArray<uint8_t>& aBuffer,
-                           const GMPDecryptionData& aMetadata);
+                           const GMPDecryptionData& aMetadata) MOZ_OVERRIDE;
 
   // Resolve/reject promise on completion.
   virtual bool RecvSetServerCertificate(const uint32_t& aPromiseId,
                                         const nsTArray<uint8_t>& aServerCert) MOZ_OVERRIDE;
 
   virtual bool RecvDecryptingComplete() MOZ_OVERRIDE;
 
   // GMP's GMPDecryptor implementation.
--- a/dom/media/gmp/GMPDecryptorParent.cpp
+++ b/dom/media/gmp/GMPDecryptorParent.cpp
@@ -38,28 +38,29 @@ GMPDecryptorParent::Init(GMPDecryptorPro
   if (!SendInit()) {
     return NS_ERROR_FAILURE;
   }
   mIsOpen = true;
   return NS_OK;
 }
 
 void
-GMPDecryptorParent::CreateSession(uint32_t aPromiseId,
+GMPDecryptorParent::CreateSession(uint32_t aCreateSessionToken,
+                                  uint32_t aPromiseId,
                                   const nsCString& aInitDataType,
                                   const nsTArray<uint8_t>& aInitData,
                                   GMPSessionType aSessionType)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use a dead GMP decrypter!");
     return;
   }
   // Caller should ensure parameters passed in from JS are valid.
   MOZ_ASSERT(!aInitDataType.IsEmpty() && !aInitData.IsEmpty());
-  unused << SendCreateSession(aPromiseId, aInitDataType, aInitData, aSessionType);
+  unused << SendCreateSession(aCreateSessionToken, aPromiseId, aInitDataType, aInitData, aSessionType);
 }
 
 void
 GMPDecryptorParent::LoadSession(uint32_t aPromiseId,
                                 const nsCString& aSessionId)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use a dead GMP decrypter!");
@@ -140,24 +141,24 @@ GMPDecryptorParent::Decrypt(uint32_t aId
                          aCrypto.iv,
                          aCrypto.plain_sizes,
                          aCrypto.encrypted_sizes);
 
   unused << SendDecrypt(aId, aBuffer, data);
 }
 
 bool
-GMPDecryptorParent::RecvResolveNewSessionPromise(const uint32_t& aPromiseId,
-                                                 const nsCString& aSessionId)
+GMPDecryptorParent::RecvSetSessionId(const uint32_t& aCreateSessionId,
+                                     const nsCString& aSessionId)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use a dead GMP decrypter!");
     return false;
   }
-  mCallback->ResolveNewSessionPromise(aPromiseId, aSessionId);
+  mCallback->SetSessionId(aCreateSessionId, aSessionId);
   return true;
 }
 
 bool
 GMPDecryptorParent::RecvResolveLoadSessionPromise(const uint32_t& aPromiseId,
                                                   const bool& aSuccess)
 {
   if (!mIsOpen) {
--- a/dom/media/gmp/GMPDecryptorParent.h
+++ b/dom/media/gmp/GMPDecryptorParent.h
@@ -25,17 +25,18 @@ class GMPDecryptorParent MOZ_FINAL : pub
 public:
   NS_INLINE_DECL_REFCOUNTING(GMPDecryptorParent)
 
   explicit GMPDecryptorParent(GMPParent *aPlugin);
 
   // GMPDecryptorProxy
   virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) MOZ_OVERRIDE;
 
-  virtual void CreateSession(uint32_t aPromiseId,
+  virtual void CreateSession(uint32_t aCreateSessionToken,
+                             uint32_t aPromiseId,
                              const nsCString& aInitDataType,
                              const nsTArray<uint8_t>& aInitData,
                              GMPSessionType aSessionType) MOZ_OVERRIDE;
 
   virtual void LoadSession(uint32_t aPromiseId,
                            const nsCString& aSessionId) MOZ_OVERRIDE;
 
   virtual void UpdateSession(uint32_t aPromiseId,
@@ -59,18 +60,18 @@ public:
 
   void Shutdown();
 
 private:
   ~GMPDecryptorParent();
 
   // PGMPDecryptorParent
 
-  virtual bool RecvResolveNewSessionPromise(const uint32_t& aPromiseId,
-                                            const nsCString& aSessionId) MOZ_OVERRIDE;
+  virtual bool RecvSetSessionId(const uint32_t& aCreateSessionToken,
+                                const nsCString& aSessionId) MOZ_OVERRIDE;
 
   virtual bool RecvResolveLoadSessionPromise(const uint32_t& aPromiseId,
                                              const bool& aSuccess) MOZ_OVERRIDE;
 
   virtual bool RecvResolvePromise(const uint32_t& aPromiseId) MOZ_OVERRIDE;
 
   virtual bool RecvRejectPromise(const uint32_t& aPromiseId,
                                  const GMPDOMException& aException,
--- a/dom/media/gmp/GMPDecryptorProxy.h
+++ b/dom/media/gmp/GMPDecryptorProxy.h
@@ -13,18 +13,18 @@
 namespace mp4_demuxer {
 class CryptoSample;
 }
 
 class GMPDecryptorProxyCallback : public GMPCallbackBase {
 public:
   ~GMPDecryptorProxyCallback() {}
 
-  virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
-                                        const nsCString& aSessionId) = 0;
+  virtual void SetSessionId(uint32_t aCreateSessionId,
+                            const nsCString& aSessionId) = 0;
 
   virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
                                          bool aSuccess) = 0;
 
   virtual void ResolvePromise(uint32_t aPromiseId) = 0;
 
   virtual void RejectPromise(uint32_t aPromiseId,
                              nsresult aException,
@@ -58,17 +58,18 @@ public:
 };
 
 class GMPDecryptorProxy {
 public:
   ~GMPDecryptorProxy() {}
 
   virtual nsresult Init(GMPDecryptorProxyCallback* aCallback) = 0;
 
-  virtual void CreateSession(uint32_t aPromiseId,
+  virtual void CreateSession(uint32_t aCreateSessionToken,
+                             uint32_t aPromiseId,
                              const nsCString& aInitDataType,
                              const nsTArray<uint8_t>& aInitData,
                              GMPSessionType aSessionType) = 0;
 
   virtual void LoadSession(uint32_t aPromiseId,
                            const nsCString& aSessionId) = 0;
 
   virtual void UpdateSession(uint32_t aPromiseId,
--- a/dom/media/gmp/PGMPDecryptor.ipdl
+++ b/dom/media/gmp/PGMPDecryptor.ipdl
@@ -15,17 +15,18 @@ namespace gmp {
 
 async protocol PGMPDecryptor
 {
   manager PGMP;
 child:
 
   Init();
 
-  CreateSession(uint32_t aPromiseId,
+  CreateSession(uint32_t aCreateSessionToken,
+                uint32_t aPromiseId,
                 nsCString aInitDataType,
                 uint8_t[] aInitData,
                 GMPSessionType aSessionType);
 
   LoadSession(uint32_t aPromiseId,
               nsCString aSessionId);
 
   UpdateSession(uint32_t aPromiseId,
@@ -45,18 +46,18 @@ child:
           uint8_t[] aBuffer,
           GMPDecryptionData aMetadata);
 
   DecryptingComplete();
 
 parent:
   __delete__();
 
-  ResolveNewSessionPromise(uint32_t aPromiseId,
-                           nsCString aSessionId);
+  SetSessionId(uint32_t aCreateSessionToken,
+               nsCString aSessionId);
 
   ResolveLoadSessionPromise(uint32_t aPromiseId,
                             bool aSuccess);
 
   ResolvePromise(uint32_t aPromiseId);
 
   RejectPromise(uint32_t aPromiseId,
                 GMPDOMException aDOMExceptionCode,
--- a/dom/media/gmp/gmp-api/gmp-decryption.h
+++ b/dom/media/gmp/gmp-api/gmp-decryption.h
@@ -91,23 +91,35 @@ typedef int64_t GMPTimestamp;
 // Capability; CDM can decrypt and then decode encrypted buffers,
 // and return decompressed samples to Gecko for playback.
 #define GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO (uint64_t(1) << 2)
 #define GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO (uint64_t(1) << 3)
 
 // Callbacks to be called from the CDM. Threadsafe.
 class GMPDecryptorCallback {
 public:
-  // Resolves a promise for a session created.
-  // Passes the session id to be exposed to JavaScript.
-  // Must be called before SessionMessage().
+
+  // The GMPDecryptor should call this in response to a call to
+  // GMPDecryptor::CreateSession(). The GMP host calls CreateSession() when
+  // MediaKeySession.generateRequest() is called by JavaScript.
+  // After CreateSession() is called, the GMPDecryptor should call
+  // GMPDecryptorCallback::SetSessionId() to set the sessionId exposed to
+  // JavaScript on the MediaKeySession on which the generateRequest() was
+  // called. SetSessionId() must be called before
+  // GMPDecryptorCallback::SessionMessage() will work.
   // aSessionId must be null terminated.
-  virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
-                                        const char* aSessionId,
-                                        uint32_t aSessionIdLength) = 0;
+  // Note: pass the aCreateSessionToken from the CreateSession() call,
+  // and then once the session has sent any messages required for the
+  // license request to be sent, then resolve the aPromiseId that was passed
+  // to GMPDecryptor::CreateSession().
+  // Note: GMPDecryptor::LoadSession() does *not* need to call SetSessionId()
+  // for GMPDecryptorCallback::SessionMessage() to work.
+  virtual void SetSessionId(uint32_t aCreateSessionToken,
+                            const char* aSessionId,
+                            uint32_t aSessionIdLength) = 0;
 
   // Resolves a promise for a session loaded.
   // Resolves to false if we don't have any session data stored for the given
   // session ID.
   // Must be called before SessionMessage().
   virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
                                          bool aSuccess) = 0;
 
@@ -117,17 +129,17 @@ public:
   // Called to reject a promise with a DOMException.
   // aMessage is logged to the WebConsole.
   // aMessage is optional, but if present must be null terminated.
   virtual void RejectPromise(uint32_t aPromiseId,
                              GMPDOMException aException,
                              const char* aMessage,
                              uint32_t aMessageLength) = 0;
 
-  // Called by the CDM when it has a message for session |session_id|.
+  // Called by the CDM when it has a message for a session.
   // Length parameters should not include null termination.
   // aSessionId must be null terminated.
   virtual void SessionMessage(const char* aSessionId,
                               uint32_t aSessionIdLength,
                               const uint8_t* aMessage,
                               uint32_t aMessageLength,
                               const char* aDestinationURL,
                               uint32_t aDestinationURLLength) = 0;
@@ -196,69 +208,111 @@ public:
 };
 
 enum GMPSessionType {
   kGMPTemporySession = 0,
   kGMPPersistentSession = 1,
   kGMPSessionInvalid = 2 // Must always be last.
 };
 
-#define GMP_API_DECRYPTOR "eme-decrypt"
+#define GMP_API_DECRYPTOR "eme-decrypt-v2"
 
 // API exposed by plugin library to manage decryption sessions.
 // When the Host requests this by calling GMPGetAPIFunc().
 //
 // API name macro: GMP_API_DECRYPTOR
 // Host API: GMPDecryptorHost
 class GMPDecryptor {
 public:
 
   // Sets the callback to use with the decryptor to return results
   // to Gecko.
-  virtual void Init(GMPDecryptorCallback* aCallback) = 0;
-
-  // Requests the creation of a session given |aType| and |aInitData|.
-  // Decryptor should callback GMPDecryptorCallback::SessionCreated()
-  // with the web session ID on success, or SessionError() on failure,
-  // and then call KeyIdUsable() as keys for that session become
-  // usable.
   //
   // The CDM must also call GMPDecryptorCallback::SetCapabilities()
   // exactly once during start up, to inform Gecko whether to use the CDM
   // in decrypt or decrypt-and-decode mode.
-  virtual void CreateSession(uint32_t aPromiseId,
+  //
+  // Note: GMPDecryptorCallback::SetCapabilities() must be called before
+  // Gecko will send any samples for decryption to the GMP.
+  virtual void Init(GMPDecryptorCallback* aCallback) = 0;
+
+  // Initiates the creation of a session given |aType| and |aInitData|, and
+  // the generation of a license request message.
+  //
+  // This corresponds to a MediaKeySession.generateRequest() call in JS.
+  //
+  // The GMPDecryptor must do the following, in order, upon this method
+  // being called:
+  //
+  // 1. Generate a sessionId to expose to JS, and call
+  //    GMPDecryptorCallback::SetSessionId(aCreateSessionToken, sessionId...)
+  //    with the sessionId to be exposed to JS/EME on the MediaKeySession
+  //    object on which generateRequest() was called, and then
+  // 2. send any messages to JS/EME required to generate a license request
+  //    given the supplied initData, and then
+  // 3. generate a license request message, and send it to JS/EME, and then
+  // 4. call GMPDecryptorCallback::ResolvePromise().
+  //
+  // Note: GMPDecryptorCallback::SetSessionId(aCreateSessionToken, sessionId, ...)
+  // *must* be called before GMPDecryptorCallback::SendMessage(sessionId, ...)
+  // will work.
+  //
+  // If generating the request fails, reject aPromiseId by calling
+  // GMPDecryptorCallback::RejectPromise().
+  virtual void CreateSession(uint32_t aCreateSessionToken,
+                             uint32_t aPromiseId,
                              const char* aInitDataType,
                              uint32_t aInitDataTypeSize,
                              const uint8_t* aInitData,
                              uint32_t aInitDataSize,
                              GMPSessionType aSessionType) = 0;
 
   // Loads a previously loaded persistent session.
+  //
+  // This corresponds to a MediaKeySession.load() call in JS.
+  //
+  // The GMPDecryptor must do the following, in order, upon this method
+  // being called:
+  //
+  // 1. Send any messages to JS/EME, or read from storage, whatever is
+  //    required to load the session, and then
+  // 2. if there is no session with the given sessionId loadable, call
+  //    ResolveLoadSessionPromise(aPromiseId, false), otherwise
+  // 2. mark the session's keys as usable, and then
+  // 3. update the session's expiration, and then
+  // 4. call GMPDecryptorCallback::ResolveLoadSessionPromise(aPromiseId, true).
+  //
+  // If loading the session fails due to error, reject aPromiseId by calling
+  // GMPDecryptorCallback::RejectPromise().
   virtual void LoadSession(uint32_t aPromiseId,
                            const char* aSessionId,
                            uint32_t aSessionIdLength) = 0;
 
   // Updates the session with |aResponse|.
+  // This corresponds to a MediaKeySession.update() call in JS.
   virtual void UpdateSession(uint32_t aPromiseId,
                              const char* aSessionId,
                              uint32_t aSessionIdLength,
                              const uint8_t* aResponse,
                              uint32_t aResponseSize) = 0;
 
   // Releases the resources (keys) for the specified session.
+  // This corresponds to a MediaKeySession.close() call in JS.
   virtual void CloseSession(uint32_t aPromiseId,
                             const char* aSessionId,
                             uint32_t aSessionIdLength) = 0;
 
   // Removes the resources (keys) for the specified session.
+  // This corresponds to a MediaKeySession.remove() call in JS.
   virtual void RemoveSession(uint32_t aPromiseId,
                              const char* aSessionId,
                              uint32_t aSessionIdLength) = 0;
 
   // Resolve/reject promise on completion.
+  // This corresponds to a MediaKeySession.setServerCertificate() call in JS.
   virtual void SetServerCertificate(uint32_t aPromiseId,
                                     const uint8_t* aServerCert,
                                     uint32_t aServerCertSize) = 0;
 
   // Asynchronously decrypts aBuffer in place. When the decryption is
   // complete, GMPDecryptor should write the decrypted data back into the
   // same GMPBuffer object and return it to Gecko by calling Decrypted(),
   // with the GMPNoErr successcode. If decryption fails, call Decrypted()
--- a/dom/media/gtest/TestGMPCrossOrigin.cpp
+++ b/dom/media/gtest/TestGMPCrossOrigin.cpp
@@ -905,18 +905,18 @@ class GMPStorageTest : public GMPDecrypt
       nsRefPtr<nsIRunnable> continuation = mExpected[0].mContinuation;
       mExpected.RemoveElementAt(0);
       if (continuation) {
         NS_DispatchToCurrentThread(continuation);
       }
     }
   }
 
-  virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
-                                        const nsCString& aSessionId) MOZ_OVERRIDE { }
+  virtual void SetSessionId(uint32_t aCreateSessionToken,
+                            const nsCString& aSessionId) MOZ_OVERRIDE { }
   virtual void ResolveLoadSessionPromise(uint32_t aPromiseId,
                                          bool aSuccess) MOZ_OVERRIDE {}
   virtual void ResolvePromise(uint32_t aPromiseId) MOZ_OVERRIDE {}
   virtual void RejectPromise(uint32_t aPromiseId,
                              nsresult aException,
                              const nsCString& aSessionId) MOZ_OVERRIDE { }
   virtual void ExpirationChange(const nsCString& aSessionId,
                                 GMPTimestamp aExpiryTime) MOZ_OVERRIDE {}
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -173,26 +173,34 @@ MediaSource::Duration()
   MOZ_ASSERT(mDecoder);
   return mDecoder->GetMediaSourceDuration();
 }
 
 void
 MediaSource::SetDuration(double aDuration, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MSE_API("MediaSource(%p)::SetDuration(aDuration=%f)", this, aDuration);
+  MSE_API("MediaSource(%p)::SetDuration(aDuration=%f, ErrorResult)", this, aDuration);
   if (aDuration < 0 || IsNaN(aDuration)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
   if (mReadyState != MediaSourceReadyState::Open ||
       mSourceBuffers->AnyUpdating()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
+  SetDuration(aDuration);
+}
+
+void
+MediaSource::SetDuration(double aDuration)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MSE_API("MediaSource(%p)::SetDuration(aDuration=%f)", this, aDuration);
   mDecoder->SetMediaSourceDuration(aDuration);
 }
 
 already_AddRefed<SourceBuffer>
 MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   nsresult rv = mozilla::IsTypeSupported(aType);
@@ -325,37 +333,41 @@ MediaSource::Enabled(JSContext* cx, JSOb
   }
 
   // Check whether it's enabled everywhere or just YouTube.
   bool restrict = Preferences::GetBool("media.mediasource.youtubeonly", false);
   if (!restrict) {
     return true;
   }
 
-  // We want to restrict to YouTube only.  We define that as the
-  // origin being https://*.youtube.com.
+  // We want to restrict to YouTube only.
+  // We define that as the origin being https://*.youtube.com.
+  // We also support https://*.youtube-nocookie.com.
   nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(global);
   nsCOMPtr<nsIURI> uri;
   if (NS_FAILED(principal->GetURI(getter_AddRefs(uri))) || !uri) {
     return false;
   }
 
   bool isHttps = false;
   if (NS_FAILED(uri->SchemeIs("https", &isHttps)) || !isHttps) {
     return false;
   }
 
   nsCOMPtr<nsIEffectiveTLDService> tldServ =
     do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
   NS_ENSURE_TRUE(tldServ, false);
 
   nsAutoCString eTLDplusOne;
-  return
-    NS_SUCCEEDED(tldServ->GetBaseDomain(uri, 0, eTLDplusOne)) &&
-    eTLDplusOne.EqualsLiteral("youtube.com");
+   if (NS_FAILED(tldServ->GetBaseDomain(uri, 0, eTLDplusOne))) {
+     return false;
+   }
+
+   return eTLDplusOne.EqualsLiteral("youtube.com") ||
+          eTLDplusOne.EqualsLiteral("youtube-nocookie.com");
 }
 
 bool
 MediaSource::Attach(MediaSourceDecoder* aDecoder)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("MediaSource(%p)::Attach(aDecoder=%p) owner=%p", this, aDecoder, aDecoder->GetOwner());
   MOZ_ASSERT(aDecoder);
--- a/dom/media/mediasource/MediaSource.h
+++ b/dom/media/mediasource/MediaSource.h
@@ -108,29 +108,34 @@ public:
   // aPath must exist.  Debug only, invoke from your favourite debugger.
   void Dump(const char* aPath);
 #endif
 
 private:
   // MediaSourceDecoder uses DurationChange to set the duration
   // without hitting the checks in SetDuration.
   friend class mozilla::MediaSourceDecoder;
+  // SourceBuffer uses SetDuration
+  friend class mozilla::dom::SourceBuffer;
 
   ~MediaSource();
 
   explicit MediaSource(nsPIDOMWindow* aWindow);
 
   friend class AsyncEventRunner<MediaSource>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   void DurationChange(double aOldDuration, double aNewDuration);
 
   void InitializationEvent();
 
+  // SetDuration with no checks.
+  void SetDuration(double aDuration);
+
   nsRefPtr<SourceBufferList> mSourceBuffers;
   nsRefPtr<SourceBufferList> mActiveSourceBuffers;
 
   nsRefPtr<MediaSourceDecoder> mDecoder;
   // Ensures the media element remains alive to dispatch progress and
   // durationchanged events.
   nsRefPtr<HTMLMediaElement> mMediaElement;
 
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -83,17 +83,17 @@ public:
   virtual int64_t ComputeStartTime(const VideoData* aVideo, const AudioData* aAudio) MOZ_OVERRIDE { return 0; }
 
   // Buffering heuristics don't make sense for MSE, because the arrival of data
   // is at least partly controlled by javascript, and javascript does not expect
   // us to sit on unplayed data just because it may not be enough to play
   // through.
   bool UseBufferingHeuristics() MOZ_OVERRIDE { return false; }
 
-  bool IsMediaSeekable() { return true; }
+  bool IsMediaSeekable() MOZ_OVERRIDE { return true; }
 
   nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE;
   void ReadUpdatedMetadata(MediaInfo* aInfo) MOZ_OVERRIDE;
   nsRefPtr<SeekPromise>
   Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
        int64_t aCurrentTime) MOZ_OVERRIDE;
 
   // Acquires the decoder monitor, and is thus callable on any thread.
@@ -103,17 +103,17 @@ public:
                                                          int64_t aTimestampOffset /* microseconds */);
 
   void AddTrackBuffer(TrackBuffer* aTrackBuffer);
   void RemoveTrackBuffer(TrackBuffer* aTrackBuffer);
   void OnTrackBufferConfigured(TrackBuffer* aTrackBuffer, const MediaInfo& aInfo);
 
   nsRefPtr<ShutdownPromise> Shutdown() MOZ_OVERRIDE;
 
-  virtual void BreakCycles();
+  virtual void BreakCycles() MOZ_OVERRIDE;
 
   bool IsShutdown()
   {
     ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
     return mDecoder->IsShutdown();
   }
 
   // Return true if all of the active tracks contain data for the specified time.
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -322,16 +322,26 @@ SourceBuffer::AbortUpdating()
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mUpdating);
   mUpdating = false;
   QueueAsyncSimpleEvent("abort");
   QueueAsyncSimpleEvent("updateend");
 }
 
 void
+SourceBuffer::CheckEndTime()
+{
+  // Check if we need to update mMediaSource duration
+  double endTime = GetBufferedEnd();
+  if (endTime > mMediaSource->Duration()) {
+    mMediaSource->SetDuration(endTime);
+  }
+}
+
+void
 SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
 {
   MSE_DEBUG("SourceBuffer(%p)::AppendData(aLength=%u)", this, aLength);
   if (!PrepareAppend(aRv)) {
     return;
   }
   StartUpdating();
 
@@ -344,16 +354,18 @@ SourceBuffer::AppendData(const uint8_t* 
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   if (mTrackBuffer->HasInitSegment()) {
     mMediaSource->QueueInitializationEvent();
   }
 
+  CheckEndTime();
+
   // Run the final step of the buffer append algorithm asynchronously to
   // ensure the SourceBuffer's updating flag transition behaves as required
   // by the spec.
   nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
   NS_DispatchToMainThread(event);
 }
 
 bool
--- a/dom/media/mediasource/SourceBuffer.h
+++ b/dom/media/mediasource/SourceBuffer.h
@@ -122,16 +122,21 @@ private:
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   // Update mUpdating and fire the appropriate events.
   void StartUpdating();
   void StopUpdating();
   void AbortUpdating();
 
+  // If the media segment contains data beyond the current duration,
+  // then run the duration change algorithm with new duration set to the
+  // maximum of the current duration and the group end timestamp.
+  void CheckEndTime();
+
   // Shared implementation of AppendBuffer overloads.
   void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
 
   // Implements the "Prepare Append Algorithm".  Returns true if the append
   // may continue, or false (with aRv set) on error.
   bool PrepareAppend(ErrorResult& aRv);
 
   nsRefPtr<MediaSource> mMediaSource;
--- a/dom/media/mediasource/SourceBufferDecoder.h
+++ b/dom/media/mediasource/SourceBufferDecoder.h
@@ -96,17 +96,17 @@ public:
     }
     mTaskQueue = nullptr;
 #ifdef MOZ_EME
     mCDMProxy = nullptr;
 #endif
   }
 
 #ifdef MOZ_EME
-  virtual nsresult SetCDMProxy(CDMProxy* aProxy)
+  virtual nsresult SetCDMProxy(CDMProxy* aProxy) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     mCDMProxy = aProxy;
     return NS_OK;
   }
 
   virtual CDMProxy* GetCDMProxy() MOZ_OVERRIDE
--- a/dom/media/mediasource/test/mochitest.ini
+++ b/dom/media/mediasource/test/mochitest.ini
@@ -1,25 +1,26 @@
 [DEFAULT]
 skip-if = e10s || buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)
 support-files =
   mediasource.js
   seek.webm seek.webm^headers^
   seek_lowres.webm seek_lowres.webm^headers^
 
-[test_MediaSource.html]
-[test_MediaSource_disabled.html]
 [test_BufferedSeek.html]
 [test_BufferingWait.html]
 skip-if = true # bug 1093133
 [test_EndOfStream.html]
 skip-if = (toolkit == 'android' || buildapp == 'mulet') #timeout android/mulet only bug 1101187
+[test_DurationUpdated.html]
 [test_FrameSelection.html]
 [test_HaveMetadataUnbufferedSeek.html]
 [test_LoadedMetadataFired.html]
+[test_MediaSource.html]
+[test_MediaSource_disabled.html]
 [test_SeekableAfterEndOfStream.html]
 [test_SeekableAfterEndOfStreamSplit.html]
 [test_SeekableBeforeEndOfStream.html]
 [test_SeekableBeforeEndOfStreamSplit.html]
 [test_SetModeThrows.html]
 [test_SplitAppendDelay.html]
 [test_SplitAppend.html]
 [test_WaitingOnMissingData.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/mediasource/test/test_DurationUpdated.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>MSE: append data and check that mediasource duration got updated</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="mediasource.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var updateCount = 0;
+var durationChangeCount = 0;
+
+runWithMSE(function (ms, v) {
+  ms.addEventListener("sourceopen", function () {
+    var sb = ms.addSourceBuffer("video/webm");
+
+    fetchWithXHR("seek.webm", function (arrayBuffer) {
+      sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
+      sb.addEventListener("updateend", function () {
+        updateCount++;
+        if (updateCount == 1) {
+          v.addEventListener("loadedmetadata", function () {
+            v.addEventListener("durationchange", function () {
+              durationChangeCount++;
+              if (durationChangeCount == 1) {
+                sb.addEventListener('updateend', function(e) {
+                  sb.removeEventListener('updateend', arguments.callee);
+                  sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
+                });
+              }
+            });
+            // Set mediasource duration to 0, so future appendBuffer
+            // will update the mediasource duration
+            // setting ms.duration will fire updatestart/update/updateend
+            //  event as per w3c spec
+            ms.duration = 0;
+          });
+        }
+      });
+    });
+  });
+
+  v.addEventListener("loadeddata", function () {
+    // XXX: Duration should be exactly 4.0, see bug 1065207.
+    is(durationChangeCount, 2, "durationchange not fired as many times as expected");
+    ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration");
+    SimpleTest.finish();
+  });
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/ogg/OggReader.h
+++ b/dom/media/ogg/OggReader.h
@@ -49,40 +49,40 @@ class OggReader MOZ_FINAL : public Media
 {
 public:
   explicit OggReader(AbstractMediaDecoder* aDecoder);
 
 protected:
   ~OggReader();
 
 public:
-  virtual nsresult Init(MediaDecoderReader* aCloneDonor);
-  virtual nsresult ResetDecode();
-  virtual bool DecodeAudioData();
+  virtual nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE;
+  virtual nsresult ResetDecode() MOZ_OVERRIDE;
+  virtual bool DecodeAudioData() MOZ_OVERRIDE;
 
   // If the Theora granulepos has not been captured, it may read several packets
   // until one with a granulepos has been captured, to ensure that all packets
   // read have valid time info.
   virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
-                                  int64_t aTimeThreshold);
+                                  int64_t aTimeThreshold) MOZ_OVERRIDE;
 
-  virtual bool HasAudio() {
+  virtual bool HasAudio() MOZ_OVERRIDE {
     return (mVorbisState != 0 && mVorbisState->mActive) ||
            (mOpusState != 0 && mOpusState->mActive);
   }
 
-  virtual bool HasVideo() {
+  virtual bool HasVideo() MOZ_OVERRIDE {
     return mTheoraState != 0 && mTheoraState->mActive;
   }
 
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
-                                MetadataTags** aTags);
+                                MetadataTags** aTags) MOZ_OVERRIDE;
   virtual nsRefPtr<SeekPromise>
   Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime) MOZ_OVERRIDE;
-  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
+  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) MOZ_OVERRIDE;
 
   virtual bool IsMediaSeekable() MOZ_OVERRIDE;
 
 private:
   // TODO: DEPRECATED. This uses synchronous decoding.
   // Stores the presentation time of the first frame we'd be able to play if
   // we started playback at the current position. Returns the first video
   // frame, if we have video.
--- a/dom/media/omx/I420ColorConverterHelper.h
+++ b/dom/media/omx/I420ColorConverterHelper.h
@@ -50,15 +50,15 @@ private:
   II420ColorConverter mConverter;
 
   bool loadLocked();
   bool loadedLocked() const;
   void unloadLocked();
 
   bool ensureLoaded();
 
-  I420ColorConverterHelper(const I420ColorConverterHelper &) MOZ_DELETE;
-  const I420ColorConverterHelper &operator=(const I420ColorConverterHelper &) MOZ_DELETE;
+  I420ColorConverterHelper(const I420ColorConverterHelper &) = delete;
+  const I420ColorConverterHelper &operator=(const I420ColorConverterHelper &) = delete;
 };
 
 } // namespace android
 
 #endif // I420_COLOR_CONVERTER_HELPER_H
--- a/dom/media/omx/MediaCodecProxy.h
+++ b/dom/media/omx/MediaCodecProxy.h
@@ -143,19 +143,19 @@ protected:
 
   // MediaResourceHandler::EventListener::resourceReserved()
   virtual void resourceReserved();
   // MediaResourceHandler::EventListener::resourceCanceled()
   virtual void resourceCanceled();
 
 private:
   // Forbidden
-  MediaCodecProxy() MOZ_DELETE;
-  MediaCodecProxy(const MediaCodecProxy &) MOZ_DELETE;
-  const MediaCodecProxy &operator=(const MediaCodecProxy &) MOZ_DELETE;
+  MediaCodecProxy() = delete;
+  MediaCodecProxy(const MediaCodecProxy &) = delete;
+  const MediaCodecProxy &operator=(const MediaCodecProxy &) = delete;
 
   // Constructor for MediaCodecProxy::CreateByType
   MediaCodecProxy(sp<ALooper> aLooper,
                   const char *aMime,
                   bool aEncoder,
                   bool aAsync,
                   wp<CodecResourceListener> aListener);
 
--- a/dom/media/omx/MediaCodecReader.h
+++ b/dom/media/omx/MediaCodecReader.h
@@ -160,18 +160,18 @@ protected:
     bool mOutputEndOfStream;
     int64_t mSeekTimeUs;
     bool mFlushed; // meaningless when mSeekTimeUs is invalid.
     bool mDiscontinuity;
     nsRefPtr<MediaTaskQueue> mTaskQueue;
 
   private:
     // Forbidden
-    Track(const Track &rhs) MOZ_DELETE;
-    const Track &operator=(const Track&) MOZ_DELETE;
+    Track(const Track &rhs) = delete;
+    const Track &operator=(const Track&) = delete;
   };
 
   // Receive a message from MessageHandler.
   // Called on MediaCodecReader::mLooper thread.
   void onMessageReceived(const android::sp<android::AMessage>& aMessage);
 
   // Receive a notify from ResourceListener.
   // Called on Binder thread.
@@ -197,19 +197,19 @@ private:
   public:
     MessageHandler(MediaCodecReader* aReader);
     ~MessageHandler();
 
     virtual void onMessageReceived(const android::sp<android::AMessage>& aMessage);
 
   private:
     // Forbidden
-    MessageHandler() MOZ_DELETE;
-    MessageHandler(const MessageHandler& rhs) MOZ_DELETE;
-    const MessageHandler& operator=(const MessageHandler& rhs) MOZ_DELETE;
+    MessageHandler() = delete;
+    MessageHandler(const MessageHandler& rhs) = delete;
+    const MessageHandler& operator=(const MessageHandler& rhs) = delete;
 
     MediaCodecReader *mReader;
   };
   friend class MessageHandler;
 
   // An intermediary class that can be managed by android::sp<T>.
   // Redirect codecReserved() and codecCanceled() to MediaCodecReader.
   class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
@@ -218,19 +218,19 @@ private:
     VideoResourceListener(MediaCodecReader* aReader);
     ~VideoResourceListener();
 
     virtual void codecReserved();
     virtual void codecCanceled();
 
   private:
     // Forbidden
-    VideoResourceListener() MOZ_DELETE;
-    VideoResourceListener(const VideoResourceListener& rhs) MOZ_DELETE;
-    const VideoResourceListener& operator=(const VideoResourceListener& rhs) MOZ_DELETE;
+    VideoResourceListener() = delete;
+    VideoResourceListener(const VideoResourceListener& rhs) = delete;
+    const VideoResourceListener& operator=(const VideoResourceListener& rhs) = delete;
 
     MediaCodecReader* mReader;
   };
   friend class VideoResourceListener;
 
   class VorbisInputCopier : public TrackInputCopier
   {
     virtual bool Copy(android::MediaBuffer* aSourceBuffer,
@@ -238,18 +238,18 @@ private:
   };
 
   struct AudioTrack : public Track
   {
     AudioTrack();
 
   private:
     // Forbidden
-    AudioTrack(const AudioTrack &rhs) MOZ_DELETE;
-    const AudioTrack &operator=(const AudioTrack &rhs) MOZ_DELETE;
+    AudioTrack(const AudioTrack &rhs) = delete;
+    const AudioTrack &operator=(const AudioTrack &rhs) = delete;
   };
 
   struct VideoTrack : public Track
   {
     VideoTrack();
 
     int32_t mWidth;
     int32_t mHeight;
@@ -258,18 +258,18 @@ private:
     int32_t mColorFormat;
     int32_t mRotation;
     nsIntSize mFrameSize;
     nsIntRect mPictureRect;
     gfx::IntRect mRelativePictureRect;
 
   private:
     // Forbidden
-    VideoTrack(const VideoTrack &rhs) MOZ_DELETE;
-    const VideoTrack &operator=(const VideoTrack &rhs) MOZ_DELETE;
+    VideoTrack(const VideoTrack &rhs) = delete;
+    const VideoTrack &operator=(const VideoTrack &rhs) = delete;
   };
 
   struct CodecBufferInfo
   {
     CodecBufferInfo();
 
     android::sp<android::ABuffer> mBuffer;
     size_t mIndex;
@@ -286,19 +286,19 @@ private:
 
     SignalObject(const char* aName);
     ~SignalObject();
     void Wait();
     void Signal();
 
   private:
     // Forbidden
-    SignalObject() MOZ_DELETE;
-    SignalObject(const SignalObject &rhs) MOZ_DELETE;
-    const SignalObject &operator=(const SignalObject &rhs) MOZ_DELETE;
+    SignalObject() = delete;
+    SignalObject(const SignalObject &rhs) = delete;
+    const SignalObject &operator=(const SignalObject &rhs) = delete;
 
     Monitor mMonitor;
     bool mSignaled;
   };
 
   class ParseCachedDataRunnable : public nsRunnable
   {
   public:
@@ -307,19 +307,19 @@ private:
                             uint32_t aLength,
                             int64_t aOffset,
                             nsRefPtr<SignalObject> aSignal);
 
     NS_IMETHOD Run() MOZ_OVERRIDE;
 
   private:
     // Forbidden
-    ParseCachedDataRunnable() MOZ_DELETE;
-    ParseCachedDataRunnable(const ParseCachedDataRunnable &rhs) MOZ_DELETE;
-    const ParseCachedDataRunnable &operator=(const ParseCachedDataRunnable &rhs) MOZ_DELETE;
+    ParseCachedDataRunnable() = delete;
+    ParseCachedDataRunnable(const ParseCachedDataRunnable &rhs) = delete;
+    const ParseCachedDataRunnable &operator=(const ParseCachedDataRunnable &rhs) = delete;
 
     nsRefPtr<MediaCodecReader> mReader;
     nsAutoArrayPtr<const char> mBuffer;
     uint32_t mLength;
     int64_t mOffset;
     nsRefPtr<SignalObject> mSignal;
   };
   friend class ParseCachedDataRunnable;
@@ -329,28 +329,28 @@ private:
   public:
     ProcessCachedDataTask(nsRefPtr<MediaCodecReader> aReader,
                           int64_t aOffset);
 
     void Run() MOZ_OVERRIDE;
 
   private:
     // Forbidden
-    ProcessCachedDataTask() MOZ_DELETE;
-    ProcessCachedDataTask(const ProcessCachedDataTask &rhs) MOZ_DELETE;
-    const ProcessCachedDataTask &operator=(const ProcessCachedDataTask &rhs) MOZ_DELETE;
+    ProcessCachedDataTask() = delete;
+    ProcessCachedDataTask(const ProcessCachedDataTask &rhs) = delete;
+    const ProcessCachedDataTask &operator=(const ProcessCachedDataTask &rhs) = delete;
 
     nsRefPtr<MediaCodecReader> mReader;
     int64_t mOffset;
   };
   friend class ProcessCachedDataTask;
 
   // Forbidden
-  MediaCodecReader() MOZ_DELETE;
-  const MediaCodecReader& operator=(const MediaCodecReader& rhs) MOZ_DELETE;
+  MediaCodecReader() = delete;
+  const MediaCodecReader& operator=(const MediaCodecReader& rhs) = delete;
 
   bool ReallocateResources();
   void ReleaseCriticalResources();
   void ReleaseResources();
 
   bool CreateLooper();
   void DestroyLooper();
 
--- a/dom/media/omx/OMXCodecWrapper.h
+++ b/dom/media/omx/OMXCodecWrapper.h
@@ -167,19 +167,19 @@ protected:
   virtual void AppendFrame(nsTArray<uint8_t>* aOutputBuf,
                            const uint8_t* aData, size_t aSize)
   {
     aOutputBuf->AppendElements(aData, aSize);
   }
 
 private:
   // Hide these. User should always use creator functions to get a media codec.
-  OMXCodecWrapper() MOZ_DELETE;
-  OMXCodecWrapper(const OMXCodecWrapper&) MOZ_DELETE;
-  OMXCodecWrapper& operator=(const OMXCodecWrapper&) MOZ_DELETE;
+  OMXCodecWrapper() = delete;
+  OMXCodecWrapper(const OMXCodecWrapper&) = delete;
+  OMXCodecWrapper& operator=(const OMXCodecWrapper&) = delete;
 
   /**
    * Create a media codec of given type. It will be a AVC/H.264 video encoder if
    * aCodecType is CODEC_AVC_ENC, or AAC audio encoder if aCodecType is
    * CODEC_AAC_ENC.
    */
   OMXCodecWrapper(CodecType aCodecType);
 
@@ -233,19 +233,19 @@ public:
   nsresult Encode(mozilla::AudioSegment& aSegment, int aInputFlags = 0);
 
   ~OMXAudioEncoder();
 protected:
   virtual status_t AppendDecoderConfig(nsTArray<uint8_t>* aOutputBuf,
                                        ABuffer* aData) MOZ_OVERRIDE;
 private:
   // Hide these. User should always use creator functions to get a media codec.
-  OMXAudioEncoder() MOZ_DELETE;
-  OMXAudioEncoder(const OMXAudioEncoder&) MOZ_DELETE;
-  OMXAudioEncoder& operator=(const OMXAudioEncoder&) MOZ_DELETE;
+  OMXAudioEncoder() = delete;
+  OMXAudioEncoder(const OMXAudioEncoder&) = delete;
+  OMXAudioEncoder& operator=(const OMXAudioEncoder&) = delete;
 
   /**
    * Create a audio codec. It will be a AAC encoder if aCodecType is
    * CODEC_AAC_ENC.
    */
   OMXAudioEncoder(CodecType aCodecType)
     : OMXCodecWrapper(aCodecType)
     , mResampler(nullptr)
@@ -326,19 +326,19 @@ protected:
   // If configured to output MP4 format blob, AVC/H.264 encoder has to replace
   // NAL unit start code with the unit length as specified in
   // ISO/IEC 14496-15 5.2.3.
   virtual void AppendFrame(nsTArray<uint8_t>* aOutputBuf,
                            const uint8_t* aData, size_t aSize) MOZ_OVERRIDE;
 
 private:
   // Hide these. User should always use creator functions to get a media codec.
-  OMXVideoEncoder() MOZ_DELETE;
-  OMXVideoEncoder(const OMXVideoEncoder&) MOZ_DELETE;
-  OMXVideoEncoder& operator=(const OMXVideoEncoder&) MOZ_DELETE;
+  OMXVideoEncoder() = delete;
+  OMXVideoEncoder(const OMXVideoEncoder&) = delete;
+  OMXVideoEncoder& operator=(const OMXVideoEncoder&) = delete;
 
   /**
    * Create a video codec. It will be a AVC/H.264 encoder if aCodecType is
    * CODEC_AVC_ENC.
    */
   OMXVideoEncoder(CodecType aCodecType)
     : OMXCodecWrapper(aCodecType)
     , mWidth(0)
--- a/dom/media/omx/mediaresourcemanager/MediaResourceHandler.h
+++ b/dom/media/omx/mediaresourcemanager/MediaResourceHandler.h
@@ -45,19 +45,19 @@ public:
   bool IsWaitingResource();
 
 protected:
   // MediaResourceManagerClient::EventListener::statusChanged()
   virtual void statusChanged(int event);
 
 private:
   // Forbidden
-  MediaResourceHandler() MOZ_DELETE;
-  MediaResourceHandler(const MediaResourceHandler &) MOZ_DELETE;
-  const MediaResourceHandler &operator=(const MediaResourceHandler &) MOZ_DELETE;
+  MediaResourceHandler() = delete;
+  MediaResourceHandler(const MediaResourceHandler &) = delete;
+  const MediaResourceHandler &operator=(const MediaResourceHandler &) = delete;
 
   // Resource Notification Listener
   wp<ResourceListener> mListener;
 
   // Resource Management
   Mutex mLock;
   sp<IMediaResourceManagerClient> mClient;
   sp<IMediaResourceManagerService> mService;
--- a/dom/media/raw/RawReader.h
+++ b/dom/media/raw/RawReader.h
@@ -15,39 +15,39 @@ class RawReader : public MediaDecoderRea
 {
 public:
   explicit RawReader(AbstractMediaDecoder* aDecoder);
 
 protected:
   ~RawReader();
 
 public:
-  virtual nsresult Init(MediaDecoderReader* aCloneDonor);
-  virtual nsresult ResetDecode();
-  virtual bool DecodeAudioData();
+  virtual nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE;
+  virtual nsresult ResetDecode() MOZ_OVERRIDE;
+  virtual bool DecodeAudioData() MOZ_OVERRIDE;
 
   virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
-                                  int64_t aTimeThreshold);
+                                  int64_t aTimeThreshold) MOZ_OVERRIDE;
 
-  virtual bool HasAudio()
+  virtual bool HasAudio() MOZ_OVERRIDE
   {
     return false;
   }
 
-  virtual bool HasVideo()
+  virtual bool HasVideo() MOZ_OVERRIDE
   {
     return true;
   }
 
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
-                                MetadataTags** aTags);
+                                MetadataTags** aTags) MOZ_OVERRIDE;
   virtual nsRefPtr<SeekPromise>
   Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime) MOZ_OVERRIDE;
 
-  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
+  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) MOZ_OVERRIDE;
 
   virtual bool IsMediaSeekable() MOZ_OVERRIDE;
 
 private:
   bool ReadFromResource(MediaResource *aResource, uint8_t *aBuf, uint32_t aLength);
 
   nsresult SeekInternal(int64_t aTime);
 
--- a/dom/media/wave/WaveReader.h
+++ b/dom/media/wave/WaveReader.h
@@ -21,42 +21,37 @@ class WaveReader : public MediaDecoderRe
 {
 public:
   explicit WaveReader(AbstractMediaDecoder* aDecoder);
 
 protected:
   ~WaveReader();
 
 public:
-  virtual nsresult Init(MediaDecoderReader* aCloneDonor);
-  virtual bool DecodeAudioData();
+  virtual nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE;
+  virtual bool DecodeAudioData() MOZ_OVERRIDE;
   virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
-                                  int64_t aTimeThreshold);
+                                  int64_t aTimeThreshold) MOZ_OVERRIDE;
 
-  virtual bool HasAudio()
+  virtual bool HasAudio() MOZ_OVERRIDE
   {
     return true;
   }
 
-  virtual bool HasVideo()
+  virtual bool HasVideo() MOZ_OVERRIDE
   {
     return false;
   }
 
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
-                                MetadataTags** aTags);
+                                MetadataTags** aTags) MOZ_OVERRIDE;
   virtual nsRefPtr<SeekPromise>
   Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime) MOZ_OVERRIDE;
 
-  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
-
-  // To seek in a buffered range, we just have to seek the stream.
-  virtual bool IsSeekableInBufferedRanges() {
-    return true;
-  }
+  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) MOZ_OVERRIDE;
 
   virtual bool IsMediaSeekable() MOZ_OVERRIDE;
 
 private:
   bool ReadAll(char* aBuf, int64_t aSize, int64_t* aBytesRead = nullptr);
   bool LoadRIFFChunk();
   bool GetNextChunk(uint32_t* aChunk, uint32_t* aChunkSize);
   bool LoadFormatChunk(uint32_t aChunkSize);
--- a/dom/media/webaudio/FFTBlock.h
+++ b/dom/media/webaudio/FFTBlock.h
@@ -138,18 +138,18 @@ public:
   }
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
   {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
 private:
-  FFTBlock(const FFTBlock& other) MOZ_DELETE;
-  void operator=(const FFTBlock& other) MOZ_DELETE;
+  FFTBlock(const FFTBlock& other) = delete;
+  void operator=(const FFTBlock& other) = delete;
 
   void EnsureFFT()
   {
     if (!mFFT) {
       mFFT = kiss_fftr_alloc(mFFTSize, 0, nullptr, nullptr);
     }
   }
   void EnsureIFFT()
--- a/dom/media/webaudio/blink/HRTFDatabase.h
+++ b/dom/media/webaudio/blink/HRTFDatabase.h
@@ -54,18 +54,18 @@ public:
     float sampleRate() const { return m_sampleRate; }
 
     // Number of elevations loaded from resource.
     static const unsigned NumberOfRawElevations;
 
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
-    HRTFDatabase(const HRTFDatabase& other) MOZ_DELETE;
-    void operator=(const HRTFDatabase& other) MOZ_DELETE;
+    HRTFDatabase(const HRTFDatabase& other) = delete;
+    void operator=(const HRTFDatabase& other) = delete;
 
     explicit HRTFDatabase(float sampleRate);
 
     // Minimum and maximum elevation angles (inclusive) for a HRTFDatabase.
     static const int MinElevation;
     static const int MaxElevation;
     static const unsigned RawElevationAngleSpacing;
 
--- a/dom/media/webaudio/blink/HRTFElevation.h
+++ b/dom/media/webaudio/blink/HRTFElevation.h
@@ -62,18 +62,18 @@ public:
     // Total number of azimuths after interpolation.
     static const unsigned NumberOfTotalAzimuths;
 
     static size_t fftSizeForSampleRate(float sampleRate);
 
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
-    HRTFElevation(const HRTFElevation& other) MOZ_DELETE;
-    void operator=(const HRTFElevation& other) MOZ_DELETE;
+    HRTFElevation(const HRTFElevation& other) = delete;
+    void operator=(const HRTFElevation& other) = delete;
 
     HRTFElevation(HRTFKernelList *kernelListL, int elevation, float sampleRate)
         : m_elevationAngle(elevation)
         , m_sampleRate(sampleRate)
     {
         m_kernelListL.SwapElements(*kernelListL);
     }
 
--- a/dom/media/webaudio/blink/HRTFKernel.h
+++ b/dom/media/webaudio/blink/HRTFKernel.h
@@ -68,18 +68,18 @@ public:
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
     {
         size_t amount = aMallocSizeOf(this);
         amount += m_fftFrame->SizeOfIncludingThis(aMallocSizeOf);
         return amount;
     }
 
 private:
-    HRTFKernel(const HRTFKernel& other) MOZ_DELETE;
-    void operator=(const HRTFKernel& other) MOZ_DELETE;
+    HRTFKernel(const HRTFKernel& other) = delete;
+    void operator=(const HRTFKernel& other) = delete;
 
     // Note: this is destructive on the passed in |impulseResponse|.
     HRTFKernel(float* impulseResponse, size_t fftSize, float sampleRate);
     
     HRTFKernel(nsAutoPtr<FFTBlock> fftFrame, float frameDelay, float sampleRate)
         : m_fftFrame(fftFrame)
         , m_frameDelay(frameDelay)
         , m_sampleRate(sampleRate)
--- a/dom/media/webm/WebMReader.h
+++ b/dom/media/webm/WebMReader.h
@@ -129,44 +129,44 @@ class WebMReader : public MediaDecoderRe
 public:
   explicit WebMReader(AbstractMediaDecoder* aDecoder);
 
 protected:
   ~WebMReader();
 
 public:
   virtual nsRefPtr<ShutdownPromise> Shutdown() MOZ_OVERRIDE;
-  virtual nsresult Init(MediaDecoderReader* aCloneDonor);
-  virtual nsresult ResetDecode();
-  virtual bool DecodeAudioData();
+  virtual nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE;
+  virtual nsresult ResetDecode() MOZ_OVERRIDE;
+  virtual bool DecodeAudioData() MOZ_OVERRIDE;
 
   virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
-                                int64_t aTimeThreshold);
+                                int64_t aTimeThreshold) MOZ_OVERRIDE;
 
-  virtual bool HasAudio()
+  virtual bool HasAudio() MOZ_OVERRIDE
   {
     NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
     return mHasAudio;
   }
 
-  virtual bool HasVideo()
+  virtual bool HasVideo() MOZ_OVERRIDE
   {
     NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
     return mHasVideo;
   }
 
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
-                                MetadataTags** aTags);
+                                MetadataTags** aTags) MOZ_OVERRIDE;
   virtual nsRefPtr<SeekPromise>
   Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime) MOZ_OVERRIDE;
 
-  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
+  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) MOZ_OVERRIDE;
   virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength,
-                                 int64_t aOffset);
-  virtual int64_t GetEvictionOffset(double aTime);
+                                 int64_t aOffset) MOZ_OVERRIDE;
+  virtual int64_t GetEvictionOffset(double aTime) MOZ_OVERRIDE;
 
   virtual bool IsMediaSeekable() MOZ_OVERRIDE;
 
   // Value passed to NextPacket to determine if we are reading a video or an
   // audio packet.
   enum TrackType {
     VIDEO = 0,
     AUDIO = 1
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.h
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.h
@@ -44,17 +44,17 @@ public:
     return NS_OK;
   };
 
   virtual bool IsFake() MOZ_OVERRIDE
   {
     return false;
   }
 
-  virtual const MediaSourceType GetMediaSource() {
+  virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
       return MediaSourceType::Camera;
   }
 
   virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
--- a/dom/media/webrtc/MediaEngineDefault.h
+++ b/dom/media/webrtc/MediaEngineDefault.h
@@ -32,48 +32,48 @@ class MediaEngineDefault;
  * The default implementation of the MediaEngine interface.
  */
 class MediaEngineDefaultVideoSource : public nsITimerCallback,
                                       public MediaEngineVideoSource
 {
 public:
   MediaEngineDefaultVideoSource();
 
-  virtual void GetName(nsAString&);
-  virtual void GetUUID(nsAString&);
+  virtual void GetName(nsAString&) MOZ_OVERRIDE;
+  virtual void GetUUID(nsAString&) MOZ_OVERRIDE;
 
   virtual nsresult Allocate(const VideoTrackConstraintsN &aConstraints,
-                            const MediaEnginePrefs &aPrefs);
-  virtual nsresult Deallocate();
-  virtual nsresult Start(SourceMediaStream*, TrackID);
-  virtual nsresult Stop(SourceMediaStream*, TrackID);
-  virtual void SetDirectListeners(bool aHasDirectListeners) {};
+                            const MediaEnginePrefs &aPrefs) MOZ_OVERRIDE;
+  virtual nsresult Deallocate() MOZ_OVERRIDE;
+  virtual nsresult Start(SourceMediaStream*, TrackID) MOZ_OVERRIDE;
+  virtual nsresult Stop(SourceMediaStream*, TrackID) MOZ_OVERRIDE;
+  virtual void SetDirectListeners(bool aHasDirectListeners) MOZ_OVERRIDE {};
   virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
                           bool aAgcOn, uint32_t aAGC,
                           bool aNoiseOn, uint32_t aNoise,
-                          int32_t aPlayoutDelay) { return NS_OK; };
+                          int32_t aPlayoutDelay) MOZ_OVERRIDE { return NS_OK; };
   virtual void NotifyPull(MediaStreamGraph* aGraph,
                           SourceMediaStream *aSource,
                           TrackID aId,
                           StreamTime aDesiredTime) MOZ_OVERRIDE;
   virtual bool SatisfiesConstraintSets(
-      const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets)
+      const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets) MOZ_OVERRIDE
   {
     return true;
   }
 
-  virtual bool IsFake() {
+  virtual bool IsFake() MOZ_OVERRIDE {
     return true;
   }
 
-  virtual const MediaSourceType GetMediaSource() {
+  virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
     return MediaSourceType::Camera;
   }
 
-  virtual nsresult TakePhoto(PhotoCallback* aCallback)
+  virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
 protected:
@@ -100,43 +100,43 @@ protected:
 class SineWaveGenerator;
 
 class MediaEngineDefaultAudioSource : public nsITimerCallback,
                                       public MediaEngineAudioSource
 {
 public:
   MediaEngineDefaultAudioSource();
 
-  virtual void GetName(nsAString&);
-  virtual void GetUUID(nsAString&);
+  virtual void GetName(nsAString&) MOZ_OVERRIDE;
+  virtual void GetUUID(nsAString&) MOZ_OVERRIDE;
 
   virtual nsresult Allocate(const AudioTrackConstraintsN &aConstraints,
-                            const MediaEnginePrefs &aPrefs);
-  virtual nsresult Deallocate();
-  virtual nsresult Start(SourceMediaStream*, TrackID);
-  virtual nsresult Stop(SourceMediaStream*, TrackID);
-  virtual void SetDirectListeners(bool aHasDirectListeners) {};
+                            const MediaEnginePrefs &aPrefs) MOZ_OVERRIDE;
+  virtual nsresult Deallocate() MOZ_OVERRIDE;
+  virtual nsresult Start(SourceMediaStream*, TrackID) MOZ_OVERRIDE;
+  virtual nsresult Stop(SourceMediaStream*, TrackID) MOZ_OVERRIDE;
+  virtual void SetDirectListeners(bool aHasDirectListeners) MOZ_OVERRIDE {};
   virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
                           bool aAgcOn, uint32_t aAGC,
                           bool aNoiseOn, uint32_t aNoise,
-                          int32_t aPlayoutDelay) { return NS_OK; };
+                          int32_t aPlayoutDelay) MOZ_OVERRIDE { return NS_OK; };
   virtual void NotifyPull(MediaStreamGraph* aGraph,
                           SourceMediaStream *aSource,
                           TrackID aId,
                           StreamTime aDesiredTime) MOZ_OVERRIDE {}
 
-  virtual bool IsFake() {
+  virtual bool IsFake() MOZ_OVERRIDE {
     return true;
   }
 
-  virtual const MediaSourceType GetMediaSource() {
+  virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
     return MediaSourceType::Microphone;
   }
 
-  virtual nsresult TakePhoto(PhotoCallback* aCallback)
+  virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
 protected:
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -60,62 +60,62 @@ namespace mozilla {
  */
 class MediaEngineWebRTCVideoSource : public MediaEngineCameraVideoSource
                                    , public webrtc::ExternalRenderer
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // ViEExternalRenderer.
-  virtual int FrameSizeChange(unsigned int w, unsigned int h, unsigned int streams);
+  virtual int FrameSizeChange(unsigned int w, unsigned int h, unsigned int streams) MOZ_OVERRIDE;
   virtual int DeliverFrame(unsigned char* buffer,
                            int size,
                            uint32_t time_stamp,
                            int64_t render_time,
-                           void *handle);
+                           void *handle) MOZ_OVERRIDE;
   /**
    * Does DeliverFrame() support a null buffer and non-null handle
    * (video texture)?
    * XXX Investigate!  Especially for Android/B2G
    */
-  virtual bool IsTextureSupported() { return false; }
+  virtual bool IsTextureSupported() MOZ_OVERRIDE { return false; }
 
   MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr, int aIndex,
                                MediaSourceType aMediaSource = MediaSourceType::Camera)
     : MediaEngineCameraVideoSource(aIndex, "WebRTCCamera.Monitor")
     , mVideoEngine(aVideoEnginePtr)
     , mMinFps(-1)
     , mMediaSource(aMediaSource)
   {
     MOZ_ASSERT(aVideoEnginePtr);
     Init();
   }
 
   virtual nsresult Allocate(const VideoTrackConstraintsN& aConstraints,
-                            const MediaEnginePrefs& aPrefs);
-  virtual nsresult Deallocate();
-  virtual nsresult Start(SourceMediaStream*, TrackID);
-  virtual nsresult Stop(SourceMediaStream*, TrackID);
+                            const MediaEnginePrefs& aPrefs) MOZ_OVERRIDE;
+  virtual nsresult Deallocate() MOZ_OVERRIDE;
+  virtual nsresult Start(SourceMediaStream*, TrackID) MOZ_OVERRIDE;
+  virtual nsresult Stop(SourceMediaStream*, TrackID) MOZ_OVERRIDE;
   virtual void NotifyPull(MediaStreamGraph* aGraph,
                           SourceMediaStream* aSource,
                           TrackID aId,
                           StreamTime aDesiredTime) MOZ_OVERRIDE;
 
-  virtual const MediaSourceType GetMediaSource() {
+  virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
     return mMediaSource;
   }
-  virtual nsresult TakePhoto(PhotoCallback* aCallback)
+  virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   void Refresh(int aIndex);
 
   bool SatisfiesConstraintSets(
-      const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
+      const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets) MOZ_OVERRIDE;
 
 protected:
   ~MediaEngineWebRTCVideoSource() { Shutdown(); }
 
 private:
   // Initialize the needed Video engine interfaces.
   void Init();
   void Shutdown();
@@ -157,52 +157,52 @@ public:
     , mPlayoutDelay(0)
     , mNullTransport(nullptr) {
     MOZ_ASSERT(aVoiceEnginePtr);
     mDeviceName.Assign(NS_ConvertUTF8toUTF16(name));
     mDeviceUUID.Assign(NS_ConvertUTF8toUTF16(uuid));
     Init();
   }
 
-  virtual void GetName(nsAString& aName);
-  virtual void GetUUID(nsAString& aUUID);
+  virtual void GetName(nsAString& aName) MOZ_OVERRIDE;
+  virtual void GetUUID(nsAString& aUUID) MOZ_OVERRIDE;
 
   virtual nsresult Allocate(const AudioTrackConstraintsN& aConstraints,
-                            const MediaEnginePrefs& aPrefs);
-  virtual nsresult Deallocate();
-  virtual nsresult Start(SourceMediaStream* aStream, TrackID aID);
-  virtual nsresult Stop(SourceMediaStream* aSource, TrackID aID);
-  virtual void SetDirectListeners(bool aHasDirectListeners) {};
+                            const MediaEnginePrefs& aPrefs) MOZ_OVERRIDE;
+  virtual nsresult Deallocate() MOZ_OVERRIDE;
+  virtual nsresult Start(SourceMediaStream* aStream, TrackID aID) MOZ_OVERRIDE;
+  virtual nsresult Stop(SourceMediaStream* aSource, TrackID aID) MOZ_OVERRIDE;
+  virtual void SetDirectListeners(bool aHasDirectListeners) MOZ_OVERRIDE {};
   virtual nsresult Config(bool aEchoOn, uint32_t aEcho,
                           bool aAgcOn, uint32_t aAGC,
                           bool aNoiseOn, uint32_t aNoise,
-                          int32_t aPlayoutDelay);
+                          int32_t aPlayoutDelay) MOZ_OVERRIDE;
 
   virtual void NotifyPull(MediaStreamGraph* aGraph,
                           SourceMediaStream* aSource,
                           TrackID aId,
                           StreamTime aDesiredTime) MOZ_OVERRIDE;
 
-  virtual bool IsFake() {
+  virtual bool IsFake() MOZ_OVERRIDE {
     return false;
   }
 
-  virtual const MediaSourceType GetMediaSource() {
+  virtual const MediaSourceType GetMediaSource() MOZ_OVERRIDE {
     return MediaSourceType::Microphone;
   }
 
-  virtual nsresult TakePhoto(PhotoCallback* aCallback)
+  virtual nsresult TakePhoto(PhotoCallback* aCallback) MOZ_OVERRIDE
   {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // VoEMediaProcess.
   void Process(int channel, webrtc::ProcessingTypes type,
                int16_t audio10ms[], int length,
-               int samplingFreq, bool isStereo);
+               int samplingFreq, bool isStereo) MOZ_OVERRIDE;
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
 protected:
   ~MediaEngineWebRTCAudioSource() { Shutdown(); }
 
   // mSamples is an int to avoid conversions when comparing/etc to
   // samplingFreq & length. Making mSamples protected instead of private is a
--- a/dom/mobileconnection/ipc/MobileConnectionChild.h
+++ b/dom/mobileconnection/ipc/MobileConnectionChild.h
@@ -36,17 +36,17 @@ public:
 
   void
   Init();
 
   void
   Shutdown();
 
 private:
-  MobileConnectionChild() MOZ_DELETE;
+  MobileConnectionChild() = delete;
 
   // MOZ_FINAL suppresses -Werror,-Wdelete-non-virtual-dtor
   ~MobileConnectionChild()
   {
     MOZ_COUNT_DTOR(MobileConnectionChild);
   }
 
 protected:
--- a/dom/mobilemessage/MobileMessageThread.h
+++ b/dom/mobilemessage/MobileMessageThread.h
@@ -44,17 +44,17 @@ public:
                          nsIDOMMozMobileMessageThread** aThread);
 
   const ThreadData& GetData() const { return mData; }
 
 private:
   ~MobileMessageThread() {}
 
   // Don't try to use the default constructor.
-  MobileMessageThread() MOZ_DELETE;
+  MobileMessageThread() = delete;
 
   ThreadData mData;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_mobilemessage_MobileMessageThread_h
--- a/dom/nfc/MozNDEFRecord.h
+++ b/dom/nfc/MozNDEFRecord.h
@@ -84,17 +84,17 @@ public:
   }
 
   uint32_t Size() const
   {
     return mSize;
   }
 
 private:
-  MozNDEFRecord() MOZ_DELETE;
+  MozNDEFRecord() = delete;
   nsRefPtr<nsPIDOMWindow> mWindow;
   void HoldData();
   void DropData();
 
   static bool
   ValidateTNF(const MozNDEFRecordOptions& aOptions, ErrorResult& aRv);
 
   TNF mTnf;
--- a/dom/plugins/ipc/PluginProcessParent.cpp
+++ b/dom/plugins/ipc/PluginProcessParent.cpp
@@ -106,46 +106,63 @@ PluginProcessParent::Delete()
 }
 
 void
 PluginProcessParent::SetCallRunnableImmediately(bool aCallImmediately)
 {
     mRunCompleteTaskImmediately = aCallImmediately;
 }
 
+/**
+ * This function exists so that we may provide an additional level of
+ * indirection between the task being posted to main event loop (a
+ * RunnableMethod) and the launch complete task itself. This is needed
+ * for cases when both WaitUntilConnected or OnChannel* race to invoke the
+ * task.
+ */
+void
+PluginProcessParent::RunLaunchCompleteTask()
+{
+    if (mLaunchCompleteTask) {
+        mLaunchCompleteTask->Run();
+        mLaunchCompleteTask = nullptr;
+    }
+}
+
 bool
 PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs)
 {
     bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs);
     if (mRunCompleteTaskImmediately && mLaunchCompleteTask) {
         if (result) {
             mLaunchCompleteTask->SetLaunchSucceeded();
         }
-        mLaunchCompleteTask->Run();
-        mLaunchCompleteTask = nullptr;
+        RunLaunchCompleteTask();
     }
     return result;
 }
 
 void
 PluginProcessParent::OnChannelConnected(int32_t peer_pid)
 {
     GeckoChildProcessHost::OnChannelConnected(peer_pid);
     if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
         mLaunchCompleteTask->SetLaunchSucceeded();
-        mMainMsgLoop->PostTask(FROM_HERE, mLaunchCompleteTask.release());
+        mMainMsgLoop->PostTask(FROM_HERE, NewRunnableMethod(this,
+                                   &PluginProcessParent::RunLaunchCompleteTask));
     }
 }
 
 void
 PluginProcessParent::OnChannelError()
 {
     GeckoChildProcessHost::OnChannelError();
     if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
-        mMainMsgLoop->PostTask(FROM_HERE, mLaunchCompleteTask.release());
+        mMainMsgLoop->PostTask(FROM_HERE, NewRunnableMethod(this,
+                                   &PluginProcessParent::RunLaunchCompleteTask));
     }
 }
 
 bool
 PluginProcessParent::IsConnected()
 {
     mozilla::MonitorAutoLock lock(mMonitor);
     return mProcessState == PROCESS_CONNECTED;
--- a/dom/plugins/ipc/PluginProcessParent.h
+++ b/dom/plugins/ipc/PluginProcessParent.h
@@ -69,16 +69,18 @@ public:
     virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0) MOZ_OVERRIDE;
 
     virtual void OnChannelConnected(int32_t peer_pid) MOZ_OVERRIDE;
     virtual void OnChannelError() MOZ_OVERRIDE;
 
     bool IsConnected();
 
 private:
+    void RunLaunchCompleteTask();
+
     std::string mPluginFilePath;
     UniquePtr<LaunchCompleteTask> mLaunchCompleteTask;
     MessageLoop* mMainMsgLoop;
     bool mRunCompleteTaskImmediately;
 
     DISALLOW_EVIL_CONSTRUCTORS(PluginProcessParent);
 };
 
--- a/dom/quota/OriginOrPatternString.h
+++ b/dom/quota/OriginOrPatternString.h
@@ -56,17 +56,17 @@ private:
     mIsOrigin(aIsOrigin), mIsPattern(!aIsOrigin), mIsNull(false)
   { }
 
   OriginOrPatternString()
   : mIsOrigin(false), mIsPattern(false), mIsNull(true)
   { }
 
   bool
-  operator==(const OriginOrPatternString& aOther) MOZ_DELETE;
+  operator==(const OriginOrPatternString& aOther) = delete;
 
   bool mIsOrigin;
   bool mIsPattern;
   bool mIsNull;
 };
 
 END_QUOTA_NAMESPACE
 
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -873,16 +873,20 @@ GetLastModifiedTime(nsIFile* aFile, int6
         }
 
         int64_t timestamp;
         rv = aFile->GetLastModifiedTime(&timestamp);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
 
+        // Need to convert from milliseconds to microseconds.
+        MOZ_ASSERT((INT64_MAX / PR_USEC_PER_MSEC) > timestamp);
+        timestamp *= int64_t(PR_USEC_PER_MSEC);
+
         if (timestamp > *aTimestamp) {
           *aTimestamp = timestamp;
         }
         return NS_OK;
       }
 
       nsCOMPtr<nsISimpleEnumerator> entries;
       rv = aFile->GetDirectoryEntries(getter_AddRefs(entries));
--- a/dom/svg/SVGFragmentIdentifier.h
+++ b/dom/svg/SVGFragmentIdentifier.h
@@ -19,17 +19,17 @@ class SVGSVGElement;
 
 /**
  * Implements support for parsing SVG fragment identifiers
  * http://www.w3.org/TR/SVG/linking.html#SVGFragmentIdentifiers
  */
 class SVGFragmentIdentifier
 {
   // To prevent the class being instantiated
-  SVGFragmentIdentifier() MOZ_DELETE;
+  SVGFragmentIdentifier() = delete;
 
 public:
   /**
    * Process the SVG fragment identifier, if there is one.
    * @return true if we found something we recognised
    */
   static bool ProcessFragmentIdentifier(nsIDocument *aDocument,
                                         const nsAString &aAnchorName);
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1310,19 +1310,19 @@ public:
   static already_AddRefed<ChromeWorkerPrivate>
   Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
               ErrorResult& rv);
 
   static bool
   WorkerAvailable(JSContext* aCx, JSObject* /* unused */);
 
 private:
-  ChromeWorkerPrivate() MOZ_DELETE;
-  ChromeWorkerPrivate(const ChromeWorkerPrivate& aRHS) MOZ_DELETE;
-  ChromeWorkerPrivate& operator =(const ChromeWorkerPrivate& aRHS) MOZ_DELETE;
+  ChromeWorkerPrivate() = delete;
+  ChromeWorkerPrivate(const ChromeWorkerPrivate& aRHS) = delete;
+  ChromeWorkerPrivate& operator =(const ChromeWorkerPrivate& aRHS) = delete;
 };
 
 WorkerPrivate*
 GetWorkerPrivateFromContext(JSContext* aCx);
 
 WorkerPrivate*
 GetCurrentThreadWorkerPrivate();
 
--- a/dom/xul/templates/nsTemplateMatch.h
+++ b/dom/xul/templates/nsTemplateMatch.h
@@ -126,14 +126,14 @@ public:
      * match that has a rule set (mRule) is the active match and generates
      * content. The next match is owned by the builder, which will delete
      * template matches when needed.
      */
     nsTemplateMatch *mNext;
 
 private:
 
-    nsTemplateMatch(const nsTemplateMatch& aMatch) MOZ_DELETE;
-    void operator=(const nsTemplateMatch& aMatch) MOZ_DELETE;
+    nsTemplateMatch(const nsTemplateMatch& aMatch) = delete;
+    void operator=(const nsTemplateMatch& aMatch) = delete;
 };
 
 #endif // nsTemplateMatch_h__
 
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -98,17 +98,17 @@ public:
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey)
 
     nsCString mHost;
     uint32_t  mAppId;
     bool      mIsInBrowserElement;
 
   private:
     // Default ctor shouldn't be used.
-    PermissionKey() MOZ_DELETE;
+    PermissionKey() = delete;
 
     // Dtor shouldn't be used outside of the class.
     ~PermissionKey() {};
   };
 
   class PermissionHashKey : public nsRefPtrHashKey<PermissionKey>
   {
   public:
@@ -278,17 +278,17 @@ private:
    * If |browserOnly| is true, only permissions related to a browserElement will
    * be in |permissions|.
    */
   struct GetPermissionsForAppStruct {
     uint32_t                  appId;
     bool                      browserOnly;
     nsCOMArray<nsIPermission> permissions;
 
-    GetPermissionsForAppStruct() MOZ_DELETE;
+    GetPermissionsForAppStruct() = delete;
     GetPermissionsForAppStruct(uint32_t aAppId, bool aBrowserOnly)
       : appId(aAppId)
       , browserOnly(aBrowserOnly)
     {}
   };
 
   /**
    * This method will return the list of all permissions that are related to a
--- a/gfx/gl/HeapCopyOfStackArray.h
+++ b/gfx/gl/HeapCopyOfStackArray.h
@@ -30,18 +30,18 @@ public:
     memcpy(mArrayData, &array[0], N * sizeof(ElemType));
   }
 
   ElemType* Data() const { return mArrayData; }
   size_t ArrayLength() const { return mArrayLength; }
   size_t ByteLength() const { return mArrayLength * sizeof(ElemType); }
 
 private:
-  HeapCopyOfStackArray() MOZ_DELETE;
-  HeapCopyOfStackArray(const HeapCopyOfStackArray&) MOZ_DELETE;
+  HeapCopyOfStackArray() = delete;
+  HeapCopyOfStackArray(const HeapCopyOfStackArray&) = delete;
 
   const size_t mArrayLength;
   ScopedDeletePtr<ElemType> const mArrayData;
 };
 
 }
 
 #endif // HEAPCOPYOFSTACKARRAY_H_
\ No newline at end of file
--- a/gfx/layers/basic/AutoMaskData.h
+++ b/gfx/layers/basic/AutoMaskData.h
@@ -45,16 +45,16 @@ private:
   bool IsConstructed()
   {
     return !!mSurface;
   }
 
   gfx::Matrix mTransform;
   RefPtr<gfx::SourceSurface> mSurface;
 
-  AutoMoz2DMaskData(const AutoMoz2DMaskData&) MOZ_DELETE;
-  AutoMoz2DMaskData& operator=(const AutoMoz2DMaskData&) MOZ_DELETE;
+  AutoMoz2DMaskData(const AutoMoz2DMaskData&) = delete;
+  AutoMoz2DMaskData& operator=(const AutoMoz2DMaskData&) = delete;
 };
 
 }
 }
 
 #endif // GFX_AUTOMASKDATA_H_
--- a/gfx/layers/basic/BasicLayersImpl.h
+++ b/gfx/layers/basic/BasicLayersImpl.h
@@ -5,17 +5,17 @@
 
 #ifndef GFX_BASICLAYERSIMPL_H
 #define GFX_BASICLAYERSIMPL_H
 
 #include "BasicImplData.h"              // for BasicImplData
 #include "BasicLayers.h"                // for BasicLayerManager
 #include "ReadbackLayer.h"              // for ReadbackLayer
 #include "gfxContext.h"                 // for gfxContext, etc
-#include "mozilla/Attributes.h"         // for MOZ_DELETE, MOZ_STACK_CLASS
+#include "mozilla/Attributes.h"         // for MOZ_STACK_CLASS
 #include "mozilla/Maybe.h"              // for Maybe
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for gfxContext::Release, etc
 #include "nsRegion.h"                   // for nsIntRegion
 
 namespace mozilla {
 namespace gfx {
--- a/gfx/layers/composite/AsyncCompositionManager.h
+++ b/gfx/layers/composite/AsyncCompositionManager.h
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_ASYNCCOMPOSITIONMANAGER_H
 #define GFX_ASYNCCOMPOSITIONMANAGER_H
 
 #include "Units.h"                      // for ScreenPoint, etc
 #include "mozilla/layers/LayerManagerComposite.h"  // for LayerManagerComposite
-#include "mozilla/Attributes.h"         // for MOZ_DELETE, MOZ_FINAL, etc
+#include "mozilla/Attributes.h"         // for MOZ_FINAL, etc
 #include "mozilla/RefPtr.h"             // for RefCounted
 #include "mozilla/TimeStamp.h"          // for TimeStamp
 #include "mozilla/dom/ScreenOrientation.h"  // for ScreenOrientation
 #include "mozilla/gfx/BasePoint.h"      // for BasePoint
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
 #include "mozilla/layers/LayersMessages.h"  // for TargetConfig
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsISupportsImpl.h"            // for LayerManager::AddRef, etc
@@ -222,16 +222,16 @@ public:
     if (mManager) {
       mManager->DetachRefLayers();
     }
   }
 
 private:
   AsyncCompositionManager* mManager;
 
-  AutoResolveRefLayers(const AutoResolveRefLayers&) MOZ_DELETE;
-  AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) MOZ_DELETE;
+  AutoResolveRefLayers(const AutoResolveRefLayers&) = delete;
+  AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) = delete;
 };
 
 } // layers
 } // mozilla
 
 #endif
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/SoftwareVsyncSource.cpp
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "SoftwareVsyncSource.h"
+#include "base/task.h"
+#include "nsThreadUtils.h"
+
+SoftwareVsyncSource::SoftwareVsyncSource()
+{
+  mGlobalDisplay = new SoftwareDisplay();
+}
+
+SoftwareVsyncSource::~SoftwareVsyncSource()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  // Ensure we disable vsync on the main thread here
+  mGlobalDisplay->DisableVsync();
+  mGlobalDisplay = nullptr;
+}
+
+SoftwareDisplay::SoftwareDisplay()
+  : mCurrentTaskMonitor("SoftwareVsyncCurrentTaskMonitor")
+{
+  // Mimic 60 fps
+  MOZ_ASSERT(NS_IsMainThread());
+  const double rate = 1000 / 60.0;
+  mVsyncRate = mozilla::TimeDuration::FromMilliseconds(rate);
+  mVsyncThread = new base::Thread("SoftwareVsyncThread");
+  EnableVsync();
+}
+
+void
+SoftwareDisplay::EnableVsync()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
+  mVsyncEnabled = true;
+  MOZ_ASSERT(!mVsyncThread->IsRunning());
+  MOZ_RELEASE_ASSERT(mVsyncThread->Start(), "Could not start software vsync thread");
+  mCurrentVsyncTask = NewRunnableMethod(this,
+      &SoftwareDisplay::NotifyVsync,
+      mozilla::TimeStamp::Now());
+  mVsyncThread->message_loop()->PostTask(FROM_HERE, mCurrentVsyncTask);
+}
+
+void
+SoftwareDisplay::DisableVsync()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mVsyncThread->IsRunning());
+  { // Scope lock
+    mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
+    mVsyncEnabled = false;
+    if (mCurrentVsyncTask) {
+      mCurrentVsyncTask->Cancel();
+      mCurrentVsyncTask = nullptr;
+    }
+  }
+  mVsyncThread->Stop();
+}
+
+bool
+SoftwareDisplay::IsVsyncEnabled()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
+  return mVsyncEnabled;
+}
+
+bool
+SoftwareDisplay::IsInSoftwareVsyncThread()
+{
+  return mVsyncThread->thread_id() == PlatformThread::CurrentId();
+}
+
+void
+SoftwareDisplay::NotifyVsync(mozilla::TimeStamp aVsyncTimestamp)
+{
+  MOZ_ASSERT(IsInSoftwareVsyncThread());
+  Display::NotifyVsync(aVsyncTimestamp);
+  ScheduleNextVsync(aVsyncTimestamp);
+}
+
+void
+SoftwareDisplay::ScheduleNextVsync(mozilla::TimeStamp aVsyncTimestamp)
+{
+  MOZ_ASSERT(IsInSoftwareVsyncThread());
+  mozilla::TimeStamp nextVsync = aVsyncTimestamp + mVsyncRate;
+  mozilla::TimeDuration delay = nextVsync - mozilla::TimeStamp::Now();
+  if (delay.ToMilliseconds() < 0) {
+    delay = mozilla::TimeDuration::FromMilliseconds(0);
+  }
+
+  mozilla::MonitorAutoLock lock(mCurrentTaskMonitor);
+  // We could've disabled vsync between this posted task and when it actually
+  // executes
+  if (!mVsyncEnabled) {
+    return;
+  }
+  mCurrentVsyncTask = NewRunnableMethod(this,
+      &SoftwareDisplay::NotifyVsync,
+      nextVsync);
+
+  mVsyncThread->message_loop()->PostDelayedTask(FROM_HERE,
+      mCurrentVsyncTask,
+      delay.ToMilliseconds());
+}
+
+SoftwareDisplay::~SoftwareDisplay()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  delete mVsyncThread;
+}
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/SoftwareVsyncSource.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef GFX_SOFTWARE_VSYNC_SOURCE_H
+#define GFX_SOFTWARE_VSYNC_SOURCE_H
+
+#include "mozilla/Monitor.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/TimeStamp.h"
+#include "base/thread.h"
+#include "nsISupportsImpl.h"
+#include "VsyncSource.h"
+
+class CancelableTask;
+
+class SoftwareDisplay MOZ_FINAL : public mozilla::gfx::VsyncSource::Display
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SoftwareDisplay)
+
+public:
+  SoftwareDisplay();
+  virtual void EnableVsync() MOZ_OVERRIDE;
+  virtual void DisableVsync() MOZ_OVERRIDE;
+  virtual bool IsVsyncEnabled() MOZ_OVERRIDE;
+  bool IsInSoftwareVsyncThread();
+  virtual void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp) MOZ_OVERRIDE;
+  void ScheduleNextVsync(mozilla::TimeStamp aVsyncTimestamp);
+
+protected:
+  ~SoftwareDisplay();
+
+private:
+  mozilla::TimeDuration mVsyncRate;
+  // Use a chromium thread because nsITimers* fire on the main thread
+  base::Thread* mVsyncThread;
+  bool mVsyncEnabled;
+  CancelableTask* mCurrentVsyncTask;
+  // Locks against both mCurrentVsyncTask and mVsyncEnabled
+  mozilla::Monitor mCurrentTaskMonitor;
+}; // SoftwareDisplay
+
+// Fallback option to use a software timer to mimic vsync. Useful for gtests
+// To mimic a hardware vsync thread, we create a dedicated software timer
+// vsync thread.
+class SoftwareVsyncSource : public mozilla::gfx::VsyncSource
+{
+public:
+  SoftwareVsyncSource();
+  ~SoftwareVsyncSource();
+
+  virtual Display& GetGlobalDisplay() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(mGlobalDisplay != nullptr);
+    return *mGlobalDisplay;
+  }
+
+private:
+  nsRefPtr<SoftwareDisplay> mGlobalDisplay;
+};
+
+#endif /* GFX_SOFTWARE_VSYNC_SOURCE_H */
--- a/gfx/thebes/VsyncSource.cpp
+++ b/gfx/thebes/VsyncSource.cpp
@@ -30,17 +30,17 @@ VsyncSource::Display&
 VsyncSource::FindDisplay(CompositorVsyncDispatcher* aCompositorVsyncDispatcher)
 {
   return GetGlobalDisplay();
 }
 
 void
 VsyncSource::Display::NotifyVsync(TimeStamp aVsyncTimestamp)
 {
-  // Called on the hardware vsync thread
+  // Called on the vsync thread
   for (size_t i = 0; i < mCompositorVsyncDispatchers.Length(); i++) {
     mCompositorVsyncDispatchers[i]->NotifyVsync(aVsyncTimestamp);
   }
 }
 
 VsyncSource::Display::Display()
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/gfx/thebes/VsyncSource.h
+++ b/gfx/thebes/VsyncSource.h
@@ -1,13 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifndef GFX_VSYNCSOURCE_H
+#define GFX_VSYNCSOURCE_H
+
 #include "mozilla/RefPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "nsISupportsImpl.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 class CompositorVsyncDispatcher;
 
@@ -21,18 +24,18 @@ class VsyncSource
 public:
   // Controls vsync unique to each display and unique on each platform
   class Display {
     public:
       Display();
       virtual ~Display();
       void AddCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
       void RemoveCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
-      // Notified when this display's vsync occurs, on the hardware vsync thread
-      void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
+      // Notified when this display's vsync occurs, on the vsync thread
+      virtual void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
 
       // These should all only be called on the main thread
       virtual void EnableVsync() = 0;
       virtual void DisableVsync() = 0;
       virtual bool IsVsyncEnabled() = 0;
 
     private:
       nsTArray<nsRefPtr<mozilla::CompositorVsyncDispatcher>> mCompositorVsyncDispatchers;
@@ -43,8 +46,10 @@ public:
 
 protected:
   virtual Display& GetGlobalDisplay() = 0; // Works across all displays
   virtual Display& FindDisplay(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
   virtual ~VsyncSource() {}
 }; // VsyncSource
 } // gfx
 } // mozilla
+
+#endif /* GFX_VSYNCSOURCE_H */
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -1795,19 +1795,19 @@ public:
     BundledFontFileEnumerator(IDWriteFactory *aFactory,
                               nsIFile        *aFontDir);
 
     IFACEMETHODIMP MoveNext(BOOL * hasCurrentFile);
 
     IFACEMETHODIMP GetCurrentFontFile(IDWriteFontFile ** fontFile);
 
 private:
-    BundledFontFileEnumerator() MOZ_DELETE;
-    BundledFontFileEnumerator(const BundledFontFileEnumerator&) MOZ_DELETE;
-    BundledFontFileEnumerator& operator=(const BundledFontFileEnumerator&) MOZ_DELETE;
+    BundledFontFileEnumerator() = delete;
+    BundledFontFileEnumerator(const BundledFontFileEnumerator&) = delete;
+    BundledFontFileEnumerator& operator=(const BundledFontFileEnumerator&) = delete;
 
     nsRefPtr<IDWriteFactory>      mFactory;
 
     nsCOMPtr<nsIFile>             mFontDir;
     nsCOMPtr<nsISimpleEnumerator> mEntries;
     nsCOMPtr<nsISupports>         mCurrent;
 };
 
@@ -1863,18 +1863,18 @@ public:
 
     IFACEMETHODIMP CreateEnumeratorFromKey(
         IDWriteFactory *aFactory,
         const void *aCollectionKey,
         UINT32 aCollectionKeySize,
         IDWriteFontFileEnumerator **aFontFileEnumerator);
 
 private:
-    BundledFontLoader(const BundledFontLoader&) MOZ_DELETE;
-    BundledFontLoader& operator=(const BundledFontLoader&) MOZ_DELETE;
+    BundledFontLoader(const BundledFontLoader&) = delete;
+    BundledFontLoader& operator=(const BundledFontLoader&) = delete;
 };
 
 IFACEMETHODIMP
 BundledFontLoader::CreateEnumeratorFromKey(
     IDWriteFactory *aFactory,
     const void *aCollectionKey,
     UINT32  aCollectionKeySize,
     IDWriteFontFileEnumerator **aFontFileEnumerator)
--- a/gfx/thebes/gfxFontEntry.h
+++ b/gfx/thebes/gfxFontEntry.h
@@ -302,18 +302,18 @@ public:
             if (mBlob) {
                 hb_blob_destroy(mBlob);
             }
         }
         operator hb_blob_t*() const { return mBlob; }
     private:
         hb_blob_t* mBlob;
         // not implemented:
-        AutoTable(const AutoTable&) MOZ_DELETE;
-        AutoTable& operator=(const AutoTable&) MOZ_DELETE;
+        AutoTable(const AutoTable&) = delete;
+        AutoTable& operator=(const AutoTable&) = delete;
     };
 
     already_AddRefed<gfxFont>
     FindOrMakeFont(const gfxFontStyle *aStyle,
                    bool aNeedsBold,
                    gfxCharacterMap* aUnicodeRangeMap = nullptr);
 
     // Get an existing font table cache entry in aBlob if it has been
--- a/gfx/thebes/gfxFontMissingGlyphs.h
+++ b/gfx/thebes/gfxFontMissingGlyphs.h
@@ -22,17 +22,17 @@ class Pattern;
  */
 class gfxFontMissingGlyphs MOZ_FINAL
 {
     typedef mozilla::gfx::DrawTarget DrawTarget;
     typedef mozilla::gfx::Float Float;
     typedef mozilla::gfx::Pattern Pattern;
     typedef mozilla::gfx::Rect Rect;
 
-    gfxFontMissingGlyphs() MOZ_DELETE; // prevent instantiation
+    gfxFontMissingGlyphs() = delete; // prevent instantiation
 
 public:
     /**
      * Draw hexboxes for a missing glyph.
      * @param aChar the UTF16 codepoint for the character
      * @param aRect the glyph-box for the glyph that is missing
      * @param aDrawTarget the DrawTarget to draw to
      * @param aPattern the pattern currently being used to paint
--- a/gfx/thebes/gfxGlyphExtents.h
+++ b/gfx/thebes/gfxGlyphExtents.h
@@ -132,13 +132,13 @@ private:
     };
 
     GlyphWidths             mContainedGlyphWidths;
     nsTHashtable<HashEntry> mTightGlyphExtents;
     int32_t                 mAppUnitsPerDevUnit;
 
 private:
     // not implemented:
-    gfxGlyphExtents(const gfxGlyphExtents& aOther) MOZ_DELETE;
-    gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) MOZ_DELETE;
+    gfxGlyphExtents(const gfxGlyphExtents& aOther) = delete;
+    gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) = delete;
 };
 
 #endif
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -100,16 +100,17 @@ class mozilla::gl::SkiaGLGlue : public G
 #include "mozilla/Preferences.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Mutex.h"
 
 #include "nsIGfxInfo.h"
 #include "nsIXULRuntime.h"
 #include "VsyncSource.h"
+#include "SoftwareVsyncSource.h"
 
 namespace mozilla {
 namespace layers {
 #ifdef MOZ_WIDGET_GONK
 void InitGralloc();
 #endif
 void ShutdownTileCache();
 }
@@ -2278,8 +2279,16 @@ gfxPlatform::UsesOffMainThreadCompositin
     result &= PR_GetEnv("MOZ_USE_OMTC") || PR_GetEnv("MOZ_OMTC_ENABLED");
 #endif
 #endif
     firstTime = false;
   }
 
   return result;
 }
+
+already_AddRefed<mozilla::gfx::VsyncSource>
+gfxPlatform::CreateHardwareVsyncSource()
+{
+  NS_WARNING("Hardware Vsync support not yet implemented. Falling back to software timers\n");
+  nsRefPtr<mozilla::gfx::VsyncSource> softwareVsync = new SoftwareVsyncSource();
+  return softwareVsync.forget();
+}
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -599,20 +599,17 @@ protected:
     virtual ~gfxPlatform();
 
     void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen,
                             eFontPrefLang aCharLang, eFontPrefLang aPageLang);
 
     /**
      * Initialized hardware vsync based on each platform.
      */
-    virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() {
-      NS_WARNING("Hardware vsync not supported on platform yet");
-      return nullptr;
-    }
+    virtual already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource();
 
     /**
      * Helper method, creates a draw target for a specific Azure backend.
      * Used by CreateOffscreenDrawTarget.
      */
     mozilla::TemporaryRef<DrawTarget>
       CreateDrawTargetForBackend(mozilla::gfx::BackendType aBackend,
                                  const mozilla::gfx::IntSize& aSize,
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -369,15 +369,15 @@ private:
   static void PrefSet(const char* aPref, int32_t aValue);
   static void PrefSet(const char* aPref, uint32_t aValue);
   static void PrefSet(const char* aPref, float aValue);
 
   static void AssertMainThread();
 
   gfxPrefs();
   ~gfxPrefs();
-  gfxPrefs(const gfxPrefs&) MOZ_DELETE;
-  gfxPrefs& operator=(const gfxPrefs&) MOZ_DELETE;
+  gfxPrefs(const gfxPrefs&) = delete;
+  gfxPrefs& operator=(const gfxPrefs&) = delete;
 };
 
 #undef DECL_GFX_PREF /* Don't need it outside of this file */
 
 #endif /* GFX_PREFS_H */
--- a/gfx/thebes/gfxQuartzNativeDrawing.h
+++ b/gfx/thebes/gfxQuartzNativeDrawing.h
@@ -50,18 +50,18 @@ public:
      * for drawing after that time, the result is undefined. */
     CGContextRef BeginNativeDrawing();
 
     /* Marks the end of native drawing */
     void EndNativeDrawing();
 
 private:
     // don't allow copying via construction or assignment
-    gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&) MOZ_DELETE;
-    const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&) MOZ_DELETE;
+    gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&) = delete;
+    const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&) = delete;
 
     // Final destination context
     mozilla::RefPtr<DrawTarget> mDrawTarget;
     mozilla::RefPtr<DrawTarget> mTempDrawTarget;
     mozilla::gfx::BorrowedCGContext mBorrowedContext;
     mozilla::gfx::Rect mNativeRect;
 
     // saved state
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -47,16 +47,17 @@ EXPORTS += [
     'gfxTeeSurface.h',
     'gfxTextRun.h',
     'gfxTypes.h',
     'gfxUserFontSet.h',
     'gfxUtils.h',
     'gfxVR.h',
     'GraphicsFilter.h',
     'RoundedRect.h',
+    'SoftwareVsyncSource.h',
     'VsyncSource.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     EXPORTS += [
         'gfxAndroidPlatform.h',
         'gfxFT2FontBase.h',
         'gfxFT2Fonts.h',
@@ -240,16 +241,17 @@ UNIFIED_SOURCES += [
     'gfxSkipChars.cpp',
     'gfxSVGGlyphs.cpp',
     'gfxTeeSurface.cpp',
     'gfxTextRun.cpp',
     'gfxUserFontSet.cpp',
     'gfxUtils.cpp',
     'gfxVR.cpp',
     'nsUnicodeRange.cpp',
+    'SoftwareVsyncSource.cpp',
     'VsyncSource.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     UNIFIED_SOURCES += [
         'gfxMacPlatformFontList.mm',
     ]
 
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -19,16 +19,17 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <linux/android_alarm.h>
 #include <math.h>
 #include <regex.h>
 #include <sched.h>
 #include <stdio.h>
 #include <sys/klog.h>
+#include <sys/stat.h>
 #include <sys/syscall.h>
 #include <sys/resource.h>
 #include <time.h>
 #include <unistd.h>
 
 #include "mozilla/DebugOnly.h"
 
 #include "android/log.h"
@@ -42,16 +43,17 @@
 #include "utils/threads.h"
 
 #include "base/message_loop.h"
 
 #include "Hal.h"
 #include "HalImpl.h"
 #include "HalLog.h"
 #include "mozilla/ArrayUtils.h"
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/battery/Constants.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Preferences.h"
@@ -595,38 +597,16 @@ GetCurrentBatteryInformation(hal::Batter
   }
 }
 
 namespace {
 
 /**
  * RAII class to help us remember to close file descriptors.
  */
-const char *wakeLockFilename = "/sys/power/wake_lock";
-const char *wakeUnlockFilename = "/sys/power/wake_unlock";
-
-template<ssize_t n>
-bool ReadFromFile(const char *filename, char (&buf)[n])
-{
-  int fd = open(filename, O_RDONLY);
-  ScopedClose autoClose(fd);
-  if (fd < 0) {
-    HAL_LOG("Unable to open file %s.", filename);
-    return false;
-  }
-
-  ssize_t numRead = read(fd, buf, n);
-  if (numRead < 0) {
-    HAL_LOG("Error reading from file %s.", filename);
-    return false;
-  }
-
-  buf[std::min(numRead, n - 1)] = '\0';
-  return true;
-}
 
 bool WriteToFile(const char *filename, const char *toWrite)
 {
   int fd = open(filename, O_WRONLY);
   ScopedClose autoClose(fd);
   if (fd < 0) {
     HAL_LOG("Unable to open file %s.", filename);
     return false;
@@ -742,16 +722,19 @@ SetScreenBrightness(double brightness)
   }
 }
 
 static Monitor* sInternalLockCpuMonitor = nullptr;
 
 static void
 UpdateCpuSleepState()
 {
+  const char *wakeLockFilename = "/sys/power/wake_lock";
+  const char *wakeUnlockFilename = "/sys/power/wake_unlock";
+
   sInternalLockCpuMonitor->AssertCurrentThreadOwns();
   bool allowed = sCpuSleepAllowed && !sInternalLockCpuCount;
   WriteToFile(allowed ? wakeUnlockFilename : wakeLockFilename, "gecko");
 }
 
 static void
 InternalLockCpu() {
   MonitorAutoLock monitor(*sInternalLockCpuMonitor);
@@ -1253,17 +1236,16 @@ OomVictimLogger::Observe(
          after_float == ']') {
       if (lineTimestamp <= mLastLineChecked) {
         continue;
       }
 
       lineTimestampFound = true;
       mLastLineChecked = lineTimestamp;
     }
-      
 
     // Log interesting lines
     for (size_t i = 0; i < regex_count; i++) {
       int matching = !regexec(&(mRegexes[i]), line_begin, 0, NULL, 0);
       if (matching) {
         // Log content of kernel message. We try to skip the ], but if for
         // some reason (most likely due to buffer overflow/wraparound), we
         // can't find the ] then we just log the entire line.
@@ -1279,16 +1261,271 @@ OomVictimLogger::Observe(
         break;
       }
     }
   }
 
   return NS_OK;
 }
 
+/**
+ * Wraps a particular ProcessPriority, giving us easy access to the prefs that
+ * are relevant to it.
+ *
+ * Creating a PriorityClass also ensures that the control group is created.
+ */
+class PriorityClass
+{
+public:
+  /**
+   * Create a PriorityClass for the given ProcessPriority.  This implicitly
+   * reads the relevant prefs and opens the cgroup.procs file of the relevant
+   * control group caching its file descriptor for later use.
+   */
+  PriorityClass(ProcessPriority aPriority);
+
+  /**
+   * Closes the file descriptor for the cgroup.procs file of the associated
+   * control group.
+   */
+  ~PriorityClass();
+
+  PriorityClass(const PriorityClass& aOther);
+  PriorityClass& operator=(const PriorityClass& aOther);
+
+  ProcessPriority Priority()
+  {
+    return mPriority;
+  }
+
+  int32_t OomScoreAdj()
+  {
+    return clamped<int32_t>(mOomScoreAdj, OOM_SCORE_ADJ_MIN, OOM_SCORE_ADJ_MAX);
+  }
+
+  int32_t KillUnderKB()
+  {
+    return mKillUnderKB;
+  }
+
+  nsCString CGroup()
+  {
+    return mGroup;
+  }
+
+  /**
+   * Adds a process to this priority class, this moves the process' PID into
+   * the associated control group.
+   *
+   * @param aPid The PID of the process to be added.
+   */
+  void AddProcess(int aPid);
+
+private:
+  ProcessPriority mPriority;
+  int32_t mOomScoreAdj;
+  int32_t mKillUnderKB;
+  int mCGroupProcsFd;
+  nsCString mGroup;
+
+  /**
+   * Return a string that identifies where we can find the value of aPref
+   * that's specific to mPriority.  For example, we might return
+   * "hal.processPriorityManager.gonk.FOREGROUND_HIGH.oomScoreAdjust".
+   */
+  nsCString PriorityPrefName(const char* aPref)
+  {
+    return nsPrintfCString("hal.processPriorityManager.gonk.%s.%s",
+                           ProcessPriorityToString(mPriority), aPref);
+  }
+
+  /**
+   * Get the full path of the cgroup.procs file associated with the group.
+   */
+  nsCString CGroupProcsFilename()
+  {
+    nsCString cgroupName = mGroup;
+
+    /* If mGroup is empty, our cgroup.procs file is the root procs file,
+     * located at /dev/cpuctl/cgroup.procs.  Otherwise our procs file is
+     * /dev/cpuctl/NAME/cgroup.procs. */
+
+    if (!mGroup.IsEmpty()) {
+      cgroupName.AppendLiteral("/");
+    }
+
+    return NS_LITERAL_CSTRING("/dev/cpuctl/") + cgroupName +
+           NS_LITERAL_CSTRING("cgroup.procs");
+  }
+
+  int OpenCGroupProcs()
+  {
+    return open(CGroupProcsFilename().get(), O_WRONLY);
+  }
+};
+
+/**
+ * Try to create the cgroup for the given PriorityClass, if it doesn't already
+ * exist.  This essentially implements mkdir -p; that is, we create parent
+ * cgroups as necessary.  The group parameters are also set according to
+ * the corresponding preferences.
+ *
+ * @param aGroup The name of the group.
+ * @return true if we successfully created the cgroup, or if it already
+ * exists.  Otherwise, return false.
+ */
+static bool
+EnsureCGroupExists(const nsACString &aGroup)
+{
+  NS_NAMED_LITERAL_CSTRING(kDevCpuCtl, "/dev/cpuctl/");
+  NS_NAMED_LITERAL_CSTRING(kSlash, "/");
+
+  nsAutoCString prefPrefix("hal.processPriorityManager.gonk.cgroups.");
+
+  /* If cgroup is not empty, append the cgroup name and a dot to obtain the
+   * group specific preferences. */
+  if (!aGroup.IsEmpty()) {
+    prefPrefix += aGroup + NS_LITERAL_CSTRING(".");
+  }
+
+  nsAutoCString cpuSharesPref(prefPrefix + NS_LITERAL_CSTRING("cpu_shares"));
+  int cpuShares = Preferences::GetInt(cpuSharesPref.get());
+
+  nsAutoCString cpuNotifyOnMigratePref(prefPrefix
+    + NS_LITERAL_CSTRING("cpu_notify_on_migrate"));
+  int cpuNotifyOnMigrate = Preferences::GetInt(cpuNotifyOnMigratePref.get());
+
+  // Create mCGroup and its parent directories, as necessary.
+  nsCString cgroupIter = aGroup + kSlash;
+
+  int32_t offset = 0;
+  while ((offset = cgroupIter.FindChar('/', offset)) != -1) {
+    nsAutoCString path = kDevCpuCtl + Substring(cgroupIter, 0, offset);
+    int rv = mkdir(path.get(), 0744);
+
+    if (rv == -1 && errno != EEXIST) {
+      HAL_LOG("Could not create the %s control group.", path.get());
+      return false;
+    }
+
+    offset++;
+  }
+
+  nsAutoCString pathPrefix(kDevCpuCtl + aGroup + kSlash);
+  nsAutoCString cpuSharesPath(pathPrefix + NS_LITERAL_CSTRING("cpu.shares"));
+  if (cpuShares && !WriteToFile(cpuSharesPath.get(),
+                                nsPrintfCString("%d", cpuShares).get())) {
+    HAL_LOG("Could not set the cpu share for group %s", cpuSharesPath.get());
+    return false;
+  }
+
+  nsAutoCString notifyOnMigratePath(pathPrefix
+    + NS_LITERAL_CSTRING("cpu.notify_on_migrate"));
+  if (!WriteToFile(notifyOnMigratePath.get(),
+                   nsPrintfCString("%d", cpuNotifyOnMigrate).get())) {
+    HAL_LOG("Could not set the cpu migration notification flag for group %s",
+            notifyOnMigratePath.get());
+    return false;
+  }
+
+  return true;
+}
+
+PriorityClass::PriorityClass(ProcessPriority aPriority)
+  : mPriority(aPriority)
+  , mOomScoreAdj(0)
+  , mKillUnderKB(0)
+  , mCGroupProcsFd(-1)
+{
+  DebugOnly<nsresult> rv;
+
+  rv = Preferences::GetInt(PriorityPrefName("OomScoreAdjust").get(),
+                           &mOomScoreAdj);
+  MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing oom_score_adj preference");
+
+  rv = Preferences::GetInt(PriorityPrefName("KillUnderKB").get(),
+                           &mKillUnderKB);
+
+  rv = Preferences::GetCString(PriorityPrefName("cgroup").get(), &mGroup);
+  MOZ_ASSERT(NS_SUCCEEDED(rv), "Missing control group preference");
+
+  if (EnsureCGroupExists(mGroup)) {
+    mCGroupProcsFd = OpenCGroupProcs();
+  }
+}
+
+PriorityClass::~PriorityClass()
+{
+  close(mCGroupProcsFd);
+}
+
+PriorityClass::PriorityClass(const PriorityClass& aOther)
+  : mPriority(aOther.mPriority)
+  , mOomScoreAdj(aOther.mOomScoreAdj)
+  , mKillUnderKB(aOther.mKillUnderKB)
+  , mGroup(aOther.mGroup)
+{
+  mCGroupProcsFd = OpenCGroupProcs();
+}
+
+PriorityClass& PriorityClass::operator=(const PriorityClass& aOther)
+{
+  mPriority = aOther.mPriority;
+  mOomScoreAdj = aOther.mOomScoreAdj;
+  mKillUnderKB = aOther.mKillUnderKB;
+  mGroup = aOther.mGroup;
+  mCGroupProcsFd = OpenCGroupProcs();
+  return *this;
+}
+
+void PriorityClass::AddProcess(int aPid)
+{
+  if (mCGroupProcsFd < 0) {
+    return;
+  }
+
+  nsPrintfCString str("%d", aPid);
+
+  if (write(mCGroupProcsFd, str.get(), strlen(str.get())) < 0) {
+    HAL_ERR("Couldn't add PID %d to the %s control group", aPid, mGroup.get());
+  }
+}
+
+/**
+ * Get the PriorityClass associated with the given ProcessPriority.
+ *
+ * If you pass an invalid ProcessPriority value, we return null.
+ *
+ * The pointers returned here are owned by GetPriorityClass (don't free them
+ * yourself).  They are guaranteed to stick around until shutdown.
+ */
+PriorityClass*
+GetPriorityClass(ProcessPriority aPriority)
+{
+  static StaticAutoPtr<nsTArray<PriorityClass>> priorityClasses;
+
+  // Initialize priorityClasses if this is the first time we're running this
+  // method.
+  if (!priorityClasses) {
+    priorityClasses = new nsTArray<PriorityClass>();
+    ClearOnShutdown(&priorityClasses);
+
+    for (int32_t i = 0; i < NUM_PROCESS_PRIORITY; i++) {
+      priorityClasses->AppendElement(PriorityClass(ProcessPriority(i)));
+    }
+  }
+
+  if (aPriority < 0 ||
+      static_cast<uint32_t>(aPriority) >= priorityClasses->Length()) {
+    return nullptr;
+  }
+
+  return &(*priorityClasses)[aPriority];
+}
+
 static void
 EnsureKernelLowMemKillerParamsSet()
 {
   static bool kernelLowMemKillerParamsSet;
   if (kernelLowMemKillerParamsSet) {
     return;
   }
   kernelLowMemKillerParamsSet = true;
@@ -1319,31 +1556,22 @@ EnsureKernelLowMemKillerParamsSet()
   int32_t countOfLowmemorykillerParametersSets = 0;
 
   long page_size = sysconf(_SC_PAGESIZE);
 
   for (int i = NUM_PROCESS_PRIORITY - 1; i >= 0; i--) {
     // The system doesn't function correctly if we're missing these prefs, so
     // crash loudly.
 
-    ProcessPriority priority = static_cast<ProcessPriority>(i);
+    PriorityClass* pc = GetPriorityClass(static_cast<ProcessPriority>(i));
 
-    int32_t oomScoreAdj;
-    if (!NS_SUCCEEDED(Preferences::GetInt(
-          nsPrintfCString("hal.processPriorityManager.gonk.%s.OomScoreAdjust",
-                          ProcessPriorityToString(priority)).get(),
-          &oomScoreAdj))) {
-      MOZ_CRASH();
-    }
+    int32_t oomScoreAdj = pc->OomScoreAdj();
+    int32_t killUnderKB = pc->KillUnderKB();
 
-    int32_t killUnderKB;
-    if (!NS_SUCCEEDED(Preferences::GetInt(
-          nsPrintfCString("hal.processPriorityManager.gonk.%s.KillUnderKB",
-                          ProcessPriorityToString(priority)).get(),
-          &killUnderKB))) {
+    if (killUnderKB == 0) {
       // ProcessPriority values like PROCESS_PRIORITY_FOREGROUND_KEYBOARD,
       // which has only OomScoreAdjust but lacks KillUnderMB value, will not
       // create new LMK parameters.
       continue;
     }
 
     // The LMK in kernel silently malfunctions if we assign the parameters
     // in non-increasing order, so we add this assertion here. See bug 887192.
@@ -1364,17 +1592,18 @@ EnsureKernelLowMemKillerParamsSet()
     countOfLowmemorykillerParametersSets++;
   }
 
   // Strip off trailing commas.
   adjParams.Cut(adjParams.Length() - 1, 1);
   minfreeParams.Cut(minfreeParams.Length() - 1, 1);
   if (!adjParams.IsEmpty() && !minfreeParams.IsEmpty()) {
     WriteToFile("/sys/module/lowmemorykiller/parameters/adj", adjParams.get());
-    WriteToFile("/sys/module/lowmemorykiller/parameters/minfree", minfreeParams.get());
+    WriteToFile("/sys/module/lowmemorykiller/parameters/minfree",
+                minfreeParams.get());
   }
 
   // Set the low-memory-notification threshold.
   int32_t lowMemNotifyThresholdKB;
   if (NS_SUCCEEDED(Preferences::GetInt(
         "hal.processPriorityManager.gonk.notifyLowMemUnderKB",
         &lowMemNotifyThresholdKB))) {
 
@@ -1386,158 +1615,16 @@ EnsureKernelLowMemKillerParamsSet()
   // Ensure OOM events appear in logcat
   nsRefPtr<OomVictimLogger> oomLogger = new OomVictimLogger();
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
     os->AddObserver(oomLogger, "ipc:content-shutdown", false);
   }
 }
 
-static void
-SetNiceForPid(int aPid, int aNice)
-{
-  errno = 0;
-  int origProcPriority = getpriority(PRIO_PROCESS, aPid);
-  if (errno) {
-    HAL_LOG("Unable to get nice for pid=%d; error %d.  SetNiceForPid bailing.",
-            aPid, errno);
-    return;
-  }
-
-  int rv = setpriority(PRIO_PROCESS, aPid, aNice);
-  if (rv) {
-    HAL_LOG("Unable to set nice for pid=%d; error %d.  SetNiceForPid bailing.",
-            aPid, errno);
-    return;
-  }
-
-  // On Linux, setpriority(aPid) modifies the priority only of the main
-  // thread of that process.  We have to modify the priorities of all of the
-  // process's threads as well, so iterate over all the threads and increase
-  // each of their priorites by aNice - origProcPriority (and also ensure that
-  // none of the tasks has a lower priority than the main thread).
-  //
-  // This is horribly racy.
-
-  DIR* tasksDir = opendir(nsPrintfCString("/proc/%d/task/", aPid).get());
-  if (!tasksDir) {
-    HAL_LOG("Unable to open /proc/%d/task.  SetNiceForPid bailing.", aPid);
-    return;
-  }
-
-  // Be careful not to leak tasksDir; after this point, we must call closedir().
-
-  while (struct dirent* de = readdir(tasksDir)) {
-    char* endptr = nullptr;
-    long tidlong = strtol(de->d_name, &endptr, /* base */ 10);
-    if (*endptr || tidlong < 0 || tidlong > INT32_MAX || tidlong == aPid) {
-      // if dp->d_name was not an integer, was negative (?!) or too large, or
-      // was the same as aPid, we're not interested.
-      //
-      // (The |tidlong == aPid| check is very important; without it, we'll
-      // renice aPid twice, and the second renice will be relative to the
-      // priority set by the first renice.)
-      continue;
-    }
-
-    int tid = static_cast<int>(tidlong);
-
-    // Do not set the priority of threads running with a real-time policy
-    // as part of the bulk process adjustment.  These threads need to run
-    // at their specified priority in order to meet timing guarantees.
-    int schedPolicy = sched_getscheduler(tid);
-    if (schedPolicy == SCHED_FIFO || schedPolicy == SCHED_RR) {
-      continue;
-    }
-
-    errno = 0;
-    // Get and set the task's new priority.
-    int origtaskpriority = getpriority(PRIO_PROCESS, tid);
-    if (errno) {
-      HAL_LOG("Unable to get nice for tid=%d (pid=%d); error %d.  This isn't "
-              "necessarily a problem; it could be a benign race condition.",
-              tid, aPid, errno);
-      continue;
-    }
-
-    int newtaskpriority =
-      std::max(origtaskpriority - origProcPriority + aNice, aNice);
-
-    // Do not reduce priority of threads already running at priorities greater
-    // than normal.  These threads are likely special service threads that need
-    // elevated priorities to process audio, display composition, etc.
-    if (newtaskpriority > origtaskpriority &&
-        origtaskpriority < ANDROID_PRIORITY_NORMAL) {
-      continue;
-    }
-
-    rv = setpriority(PRIO_PROCESS, tid, newtaskpriority);
-
-    if (rv) {
-      HAL_LOG("Unable to set nice for tid=%d (pid=%d); error %d.  This isn't "
-              "necessarily a problem; it could be a benign race condition.",
-              tid, aPid, errno);
-      continue;
-    }
-  }
-
-  HAL_LOG("Changed nice for pid %d from %d to %d.",
-          aPid, origProcPriority, aNice);
-
-  closedir(tasksDir);
-}
-
-/*
- * Used to store the nice value adjustments and oom_adj values for the various
- * process priority levels.
- */
-struct ProcessPriorityPrefs {
-  bool initialized;
-  int lowPriorityNice;
-  struct {
-    int nice;
-    int oomScoreAdj;
-  } priorities[NUM_PROCESS_PRIORITY];
-};
-
-/*
- * Reads the preferences for the various process priority levels and sets up
- * watchers so that if they're dynamically changed the change is reflected on
- * the appropriate variables.
- */
-void
-EnsureProcessPriorityPrefs(ProcessPriorityPrefs* prefs)
-{
-  if (prefs->initialized) {
-    return;
-  }
-
-  // Read the preferences for process priority levels
-  for (int i = PROCESS_PRIORITY_BACKGROUND; i < NUM_PROCESS_PRIORITY; i++) {
-    ProcessPriority priority = static_cast<ProcessPriority>(i);
-
-    // Read the nice values
-    const char* processPriorityStr = ProcessPriorityToString(priority);
-    nsPrintfCString niceStr("hal.processPriorityManager.gonk.%s.Nice",
-                            processPriorityStr);
-    Preferences::AddIntVarCache(&prefs->priorities[i].nice, niceStr.get());
-
-    // Read the oom_adj scores
-    nsPrintfCString oomStr("hal.processPriorityManager.gonk.%s.OomScoreAdjust",
-                           processPriorityStr);
-    Preferences::AddIntVarCache(&prefs->priorities[i].oomScoreAdj,
-                                oomStr.get());
-  }
-
-  Preferences::AddIntVarCache(&prefs->lowPriorityNice,
-                              "hal.processPriorityManager.gonk.LowCPUNice");
-
-  prefs->initialized = true;
-}
-
 void
 SetProcessPriority(int aPid,
                    ProcessPriority aPriority,
                    ProcessCPUPriority aCPUPriority,
                    uint32_t aBackgroundLRU)
 {
   HAL_LOG("SetProcessPriority(pid=%d, priority=%d, cpuPriority=%d, LRU=%u)",
           aPid, aPriority, aCPUPriority, aBackgroundLRU);
@@ -1546,59 +1633,33 @@ SetProcessPriority(int aPid,
   // OOM parameters according to our prefs.
   //
   // We could/should do this on startup instead of waiting for the first
   // SetProcessPriorityCall.  But in practice, the master process needs to set
   // its priority early in the game, so we can reasonably rely on
   // SetProcessPriority being called early in startup.
   EnsureKernelLowMemKillerParamsSet();
 
-  static ProcessPriorityPrefs prefs = { 0 };
-  EnsureProcessPriorityPrefs(&prefs);
+  PriorityClass* pc = GetPriorityClass(aPriority);
 
-  int oomScoreAdj = prefs.priorities[aPriority].oomScoreAdj;
+  int oomScoreAdj = pc->OomScoreAdj();
 
   RoundOomScoreAdjUpWithBackroundLRU(oomScoreAdj, aBackgroundLRU);
 
-  int clampedOomScoreAdj = clamped<int>(oomScoreAdj, OOM_SCORE_ADJ_MIN,
-                                                     OOM_SCORE_ADJ_MAX);
-  if (clampedOomScoreAdj != oomScoreAdj) {
-    HAL_LOG("Clamping OOM adjustment for pid %d to %d", aPid,
-            clampedOomScoreAdj);
-  } else {
-    HAL_LOG("Setting OOM adjustment for pid %d to %d", aPid,
-            clampedOomScoreAdj);
-  }
-
   // We try the newer interface first, and fall back to the older interface
   // on failure.
-
   if (!WriteToFile(nsPrintfCString("/proc/%d/oom_score_adj", aPid).get(),
-                   nsPrintfCString("%d", clampedOomScoreAdj).get()))
+                   nsPrintfCString("%d", oomScoreAdj).get()))
   {
-    int oomAdj = OomAdjOfOomScoreAdj(clampedOomScoreAdj);
-
     WriteToFile(nsPrintfCString("/proc/%d/oom_adj", aPid).get(),
-                nsPrintfCString("%d", oomAdj).get());
+                nsPrintfCString("%d", OomAdjOfOomScoreAdj(oomScoreAdj)).get());
   }
 
-  int nice = 0;
-
-  if (aCPUPriority == PROCESS_CPU_PRIORITY_NORMAL) {
-    nice = prefs.priorities[aPriority].nice;
-  } else if (aCPUPriority == PROCESS_CPU_PRIORITY_LOW) {
-    nice = prefs.lowPriorityNice;
-  } else {
-    HAL_ERR("Unknown aCPUPriority value %d", aCPUPriority);
-    MOZ_ASSERT(false);
-    return;
-  }
-