Merge m-i to m-c, a=merge
authorPhil Ringnalda <philringnalda@gmail.com>
Sun, 29 Mar 2015 17:20:48 -0700
changeset 266748 dfe60814eda70948c866d548498cc6dbe5f1de5c
parent 266710 9c786bf6a7ff4b00d84bd5a1c2218a30ba976c2d (current diff)
parent 266747 beb016173f6f1ac953c3c4998f232e2f7d5adccc (diff)
child 266749 0cabefa3e330953d2a738e5285ea2861fab7dda8
child 266760 267f7f1c2dcd8f24d24d723a3d1d18bb7bd587eb
child 267862 5a67281405a2cf66f1aadd5fde1a42b74763f911
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-i to m-c, a=merge
dom/indexedDB/TransactionThreadPool.cpp
dom/indexedDB/TransactionThreadPool.h
toolkit/components/telemetry/Histograms.json
toolkit/mozapps/update/UpdaterHealthProvider.jsm
toolkit/mozapps/update/tests/unit_aus_update/updateHealthReport.js
--- a/accessible/ipc/PDocAccessible.ipdl
+++ b/accessible/ipc/PDocAccessible.ipdl
@@ -4,18 +4,18 @@
  * 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 protocol PContent;
 
 include "mozilla/GfxMessageUtils.h";
 
 using struct nsIntPoint from "nsRect.h";
-using struct nsIntSize from "nsRect.h";
 using struct nsIntRect from "nsRect.h";
+using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
 
 namespace mozilla {
 namespace a11y {
 
 struct AccessibleData
 {
   uint64_t ID;
   uint32_t Role;
@@ -126,17 +126,17 @@ child:
   prio(high) sync ReplaceText(uint64_t aID, nsString aText);
   prio(high) sync InsertText(uint64_t aID, nsString aText, int32_t aPosition);
   prio(high) sync CopyText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
   prio(high) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
   prio(high) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
   prio(high) sync PasteText(uint64_t aID, int32_t aPosition);
 
   prio(high) sync ImagePosition(uint64_t aID, uint32_t aCoordType) returns(nsIntPoint aRetVal);
-  prio(high) sync ImageSize(uint64_t aID) returns(nsIntSize aRetVal);
+  prio(high) sync ImageSize(uint64_t aID) returns(IntSize aRetVal);
 
   prio(high) sync StartOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
   prio(high) sync EndOffset(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
   prio(high) sync IsLinkValid(uint64_t aID) returns(bool aRetVal);
   prio(high) sync AnchorCount(uint64_t aID) returns(uint32_t aRetVal, bool aOk);
   prio(high) sync AnchorURIAt(uint64_t aID, uint32_t aIndex) returns(nsCString aURI, bool aOk);
   prio(high) sync AnchorAt(uint64_t aID, uint32_t aIndex) returns(uint64_t aIDOfAnchor, bool aOk);
 
--- a/addon-sdk/source/lib/sdk/system/events.js
+++ b/addon-sdk/source/lib/sdk/system/events.js
@@ -24,17 +24,17 @@ const Subject = Class({
     // subjects that are one of our wrappers (which we should unwrap
     // when notifying our observers) and those that are real JS XPCOM
     // components (which we should pass through unaltered).
     this.wrappedJSObject = {
       observersModuleSubjectWrapper: true,
       object: object
     };
   },
-  getHelperForLanguage: function() {},
+  getScriptableHelper: function() {},
   getInterfaces: function() {}
 });
 
 function emit(type, event) {
   // From bug 910599
   // We must test to see if 'subject' or 'data' is a defined property
   // of the event object, but also allow primitives to be passed in,
   // which the `in` operator breaks, yet `null` is an object, hence
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -224,20 +224,34 @@ Animation::ActiveDuration(const Animatio
     return aTiming.mIterationDuration == zeroDuration
            ? zeroDuration
            : StickyTimeDuration::Forever();
   }
   return StickyTimeDuration(
     aTiming.mIterationDuration.MultDouble(aTiming.mIterationCount));
 }
 
+// http://w3c.github.io/web-animations/#in-play
 bool
-Animation::IsCurrent() const
+Animation::IsInPlay(const AnimationPlayer& aPlayer) const
 {
-  if (IsFinishedTransition()) {
+  if (IsFinishedTransition() ||
+      aPlayer.PlayState() == AnimationPlayState::Finished) {
+    return false;
+  }
+
+  return GetComputedTiming().mPhase == ComputedTiming::AnimationPhase_Active;
+}
+
+// http://w3c.github.io/web-animations/#current
+bool
+Animation::IsCurrent(const AnimationPlayer& aPlayer) const
+{
+  if (IsFinishedTransition() ||
+      aPlayer.PlayState() == AnimationPlayState::Finished) {
     return false;
   }
 
   ComputedTiming computedTiming = GetComputedTiming();
   return computedTiming.mPhase == ComputedTiming::AnimationPhase_Before ||
          computedTiming.mPhase == ComputedTiming::AnimationPhase_Active;
 }
 
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -297,17 +297,18 @@ public:
   }
 
   void SetIsFinishedTransition() {
     MOZ_ASSERT(AsTransition(),
                "Calling SetIsFinishedTransition but it's not a transition");
     mIsFinishedTransition = true;
   }
 
-  bool IsCurrent() const;
+  bool IsInPlay(const AnimationPlayer& aPlayer) const;
+  bool IsCurrent(const AnimationPlayer& aPlayer) const;
   bool IsInEffect() const;
 
   const AnimationProperty*
   GetAnimationOfProperty(nsCSSProperty aProperty) const;
   bool HasAnimationOfProperty(nsCSSProperty aProperty) const {
     return GetAnimationOfProperty(aProperty) != nullptr;
   }
   const InfallibleTArray<AnimationProperty>& Properties() const {
--- a/dom/animation/AnimationPlayer.cpp
+++ b/dom/animation/AnimationPlayer.cpp
@@ -346,29 +346,16 @@ AnimationPlayer::Cancel()
   }
 
   mHoldTime.SetNull();
   mStartTime.SetNull();
 
   UpdateSourceContent();
 }
 
-bool
-AnimationPlayer::IsRunning() const
-{
-  if (IsPausedOrPausing() ||
-      !GetSource() ||
-      GetSource()->IsFinishedTransition()) {
-    return false;
-  }
-
-  ComputedTiming computedTiming = GetSource()->GetComputedTiming();
-  return computedTiming.mPhase == ComputedTiming::AnimationPhase_Active;
-}
-
 void
 AnimationPlayer::UpdateRelevance()
 {
   bool wasRelevant = mIsRelevant;
   mIsRelevant = HasCurrentSource() || HasInEffectSource();
 
   // Notify animation observers.
   if (wasRelevant && !mIsRelevant) {
--- a/dom/animation/AnimationPlayer.h
+++ b/dom/animation/AnimationPlayer.h
@@ -196,27 +196,44 @@ public:
     return mSource ? mSource->Name() : EmptyString();
   }
 
   bool IsPausedOrPausing() const
   {
     return PlayState() == AnimationPlayState::Paused ||
            mPendingState == PendingState::PausePending;
   }
-  bool IsRunning() const;
 
+  bool HasInPlaySource() const
+  {
+    return GetSource() && GetSource()->IsInPlay(*this);
+  }
   bool HasCurrentSource() const
   {
-    return GetSource() && GetSource()->IsCurrent();
+    return GetSource() && GetSource()->IsCurrent(*this);
   }
   bool HasInEffectSource() const
   {
     return GetSource() && GetSource()->IsInEffect();
   }
 
+  /**
+   * "Playing" is different to "running". An animation in its delay phase is
+   * still running but we only consider it playing when it is in its active
+   * interval. This definition is used for fetching the animations that are
+   * are candidates for running on the compositor (since we don't ship
+   * animations to the compositor when they are in their delay phase or
+   * paused).
+   */
+  bool IsPlaying() const
+  {
+    return HasInPlaySource() && // Check we are in the active interval
+           PlayState() == AnimationPlayState::Running; // And not paused
+  }
+
   bool IsRelevant() const { return mIsRelevant; }
   void UpdateRelevance();
 
   void SetIsRunningOnCompositor() { mIsRunningOnCompositor = true; }
   void ClearIsRunningOnCompositor() { mIsRunningOnCompositor = false; }
 
   // Returns true if this animation does not currently need to update
   // style on the main thread (e.g. because it is empty, or is
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -824,26 +824,20 @@ nsDOMClassInfo::GetInterfaces(uint32_t *
 
     *((*aArray) + i) = iid;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMClassInfo::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
+nsDOMClassInfo::GetScriptableHelper(nsIXPCScriptable **_retval)
 {
-  if (language == nsIProgrammingLanguage::JAVASCRIPT) {
-    *_retval = static_cast<nsIXPCScriptable *>(this);
-
-    NS_ADDREF(*_retval);
-  } else {
-    *_retval = nullptr;
-  }
-
+  nsCOMPtr<nsIXPCScriptable> rval = this;
+  rval.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMClassInfo::GetContractID(char **aContractID)
 {
   *aContractID = nullptr;
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -46,16 +46,17 @@
 #include "mozilla/TimeStamp.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIIdleObserver.h"
 #include "nsIDocument.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "Units.h"
 #include "nsComponentManagerUtils.h"
+#include "nsSize.h"
 
 #define DEFAULT_HOME_PAGE "www.mozilla.org"
 #define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
 
 // Amount of time allowed between alert/prompt/confirm before enabling
 // the stop dialog checkbox.
 #define DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
 
@@ -85,17 +86,16 @@ class nsIWebBrowserChrome;
 class nsDOMWindowList;
 class nsLocation;
 class nsScreen;
 class nsHistory;
 class nsGlobalWindowObserver;
 class nsGlobalWindow;
 class nsDOMWindowUtils;
 class nsIIdleService;
-struct nsIntSize;
 struct nsRect;
 
 class nsWindowSizes;
 
 namespace mozilla {
 class DOMEventTargetHelper;
 namespace dom {
 class BarProp;
--- a/dom/base/nsHostObjectURI.cpp
+++ b/dom/base/nsHostObjectURI.cpp
@@ -197,17 +197,17 @@ NS_IMETHODIMP
 nsHostObjectURI::GetInterfaces(uint32_t *count, nsIID * **array)
 {
   *count = 0;
   *array = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsHostObjectURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
+nsHostObjectURI::GetScriptableHelper(nsIXPCScriptable **_retval)
 {
   *_retval = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsHostObjectURI::GetContractID(char * *aContractID)
 {
--- a/dom/bindings/Exceptions.cpp
+++ b/dom/bindings/Exceptions.cpp
@@ -211,35 +211,23 @@ namespace exceptions {
 
 class StackFrame : public nsIStackFrame
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(StackFrame)
   NS_DECL_NSISTACKFRAME
 
-  StackFrame(uint32_t aLanguage,
-             const char* aFilename,
-             const char* aFunctionName,
-             int32_t aLineNumber,
-             nsIStackFrame* aCaller);
-
   StackFrame()
     : mLineno(0)
     , mColNo(0)
     , mLanguage(nsIProgrammingLanguage::UNKNOWN)
   {
   }
 
-  static already_AddRefed<nsIStackFrame>
-  CreateStackFrameLocation(uint32_t aLanguage,
-                           const char* aFilename,
-                           const char* aFunctionName,
-                           int32_t aLineNumber,
-                           nsIStackFrame* aCaller);
 protected:
   virtual ~StackFrame();
 
   virtual bool IsJSFrame() const
   {
     return false;
   }
 
@@ -258,29 +246,16 @@ protected:
   nsString mFilename;
   nsString mFunname;
   nsString mAsyncCause;
   int32_t mLineno;
   int32_t mColNo;
   uint32_t mLanguage;
 };
 
-StackFrame::StackFrame(uint32_t aLanguage,
-                       const char* aFilename,
-                       const char* aFunctionName,
-                       int32_t aLineNumber,
-                       nsIStackFrame* aCaller)
-  : mCaller(aCaller)
-  , mLineno(aLineNumber)
-  , mLanguage(aLanguage)
-{
-  CopyUTF8toUTF16(aFilename, mFilename);
-  CopyUTF8toUTF16(aFunctionName, mFunname);
-}
-
 StackFrame::~StackFrame()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION(StackFrame, mCaller, mAsyncCaller)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(StackFrame)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(StackFrame)
 
@@ -850,41 +825,17 @@ JSStackFrame::CreateStack(JSContext* aCx
   if (!stack) {
     first = new StackFrame();
   } else {
     first = new JSStackFrame(stack);
   }
   return first.forget();
 }
 
-/* static */ already_AddRefed<nsIStackFrame>
-StackFrame::CreateStackFrameLocation(uint32_t aLanguage,
-                                     const char* aFilename,
-                                     const char* aFunctionName,
-                                     int32_t aLineNumber,
-                                     nsIStackFrame* aCaller)
-{
-  nsRefPtr<StackFrame> self =
-    new StackFrame(aLanguage, aFilename, aFunctionName, aLineNumber, aCaller);
-  return self.forget();
-}
-
 already_AddRefed<nsIStackFrame>
 CreateStack(JSContext* aCx, int32_t aMaxDepth)
 {
   return JSStackFrame::CreateStack(aCx, aMaxDepth);
 }
 
-already_AddRefed<nsIStackFrame>
-CreateStackFrameLocation(uint32_t aLanguage,
-                         const char* aFilename,
-                         const char* aFunctionName,
-                         int32_t aLineNumber,
-                         nsIStackFrame* aCaller)
-{
-  return StackFrame::CreateStackFrameLocation(aLanguage, aFilename,
-                                              aFunctionName, aLineNumber,
-                                              aCaller);
-}
-
 } // namespace exceptions
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/Exceptions.h
+++ b/dom/bindings/Exceptions.h
@@ -60,20 +60,13 @@ public:
 // Internal stuff not intended to be widely used.
 namespace exceptions {
 
 // aMaxDepth can be used to define a maximal depth for the stack trace. If the
 // value is -1, a default maximal depth will be selected.
 already_AddRefed<nsIStackFrame>
 CreateStack(JSContext* aCx, int32_t aMaxDepth = -1);
 
-already_AddRefed<nsIStackFrame>
-CreateStackFrameLocation(uint32_t aLanguage,
-                         const char* aFilename,
-                         const char* aFunctionName,
-                         int32_t aLineNumber,
-                         nsIStackFrame* aCaller);
-
 } // namespace exceptions
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -2051,29 +2051,23 @@ CreateStyleRule(nsINode* aNode,
 
   error = parser.ParseStyleAttribute(EmptyString(), docURL, baseURL,
                                      principal, getter_AddRefs(rule));
   if (error.Failed()) {
     return nullptr;
   }
 
   if (aProp1 != eCSSProperty_UNKNOWN) {
-    error = parser.ParseProperty(aProp1, aValue1, docURL, baseURL, principal,
-                                 rule->GetDeclaration(), aChanged1, false);
-    if (error.Failed()) {
-      return nullptr;
-    }
+    parser.ParseProperty(aProp1, aValue1, docURL, baseURL, principal,
+                         rule->GetDeclaration(), aChanged1, false);
   }
 
   if (aProp2 != eCSSProperty_UNKNOWN) {
-    error = parser.ParseProperty(aProp2, aValue2, docURL, baseURL, principal,
-                                 rule->GetDeclaration(), aChanged2, false);
-    if (error.Failed()) {
-      return nullptr;
-    }
+    parser.ParseProperty(aProp2, aValue2, docURL, baseURL, principal,
+                         rule->GetDeclaration(), aChanged2, false);
   }
 
   rule->RuleMatched();
 
   return rule.forget();
 }
 
 static already_AddRefed<StyleRule>
@@ -4134,17 +4128,17 @@ CanvasRenderingContext2D::CachedSurfaceF
     return res;
   }
 
   int32_t corsmode = imgIRequest::CORS_NONE;
   if (NS_SUCCEEDED(imgRequest->GetCORSMode(&corsmode))) {
     res.mCORSUsed = corsmode != imgIRequest::CORS_NONE;
   }
 
-  res.mSize = ThebesIntSize(res.mSourceSurface->GetSize());
+  res.mSize = res.mSourceSurface->GetSize();
   res.mPrincipal = principal.forget();
   res.mIsWriteOnly = false;
   res.mImageRequest = imgRequest.forget();
 
   return res;
 }
 
 //
@@ -4338,17 +4332,17 @@ CanvasRenderingContext2D::DrawImage(cons
       CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
                                             res.mPrincipal, res.mIsWriteOnly,
                                             res.mCORSUsed);
     }
 
     if (res.mSourceSurface) {
       if (res.mImageRequest) {
         CanvasImageCache::NotifyDrawImage(element, mCanvasElement, res.mImageRequest,
-                                          res.mSourceSurface, ThebesIntSize(imgSize));
+                                          res.mSourceSurface, imgSize);
       }
 
       srcSurf = res.mSourceSurface;
     } else {
       drawInfo = res.mDrawInfo;
     }
   }
 
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -35,17 +35,17 @@ using FrameMetrics::ViewID from "FrameMe
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
 using nscolor from "nsColor.h";
 using class mozilla::WidgetCompositionEvent from "ipc/nsGUIEventIPC.h";
 using struct mozilla::widget::IMENotification from "nsIWidget.h";
 using struct nsIMEUpdatePreference from "nsIWidget.h";
 using struct nsIntPoint from "nsPoint.h";
 using struct nsIntRect from "nsRect.h";
-using struct nsIntSize from "nsSize.h";
+using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
 using class mozilla::WidgetKeyboardEvent from "ipc/nsGUIEventIPC.h";
 using class mozilla::WidgetMouseEvent from "ipc/nsGUIEventIPC.h";
 using class mozilla::WidgetWheelEvent from "ipc/nsGUIEventIPC.h";
 using struct nsRect from "nsRect.h";
 using class mozilla::WidgetSelectionEvent from "ipc/nsGUIEventIPC.h";
 using class mozilla::WidgetTouchEvent from "ipc/nsGUIEventIPC.h";
 using struct mozilla::dom::RemoteDOMEvent from "mozilla/dom/TabMessageUtils.h";
 using mozilla::dom::ScreenOrientation from "mozilla/dom/ScreenOrientation.h";
@@ -600,17 +600,17 @@ child:
      * default background color |bgcolor|.  |renderFlags| are the
      * nsIPresShell::RenderDocument() flags to use on the remote side,
      * and if true, |flushLayout| will do just that before rendering
      * the document.  The rendered image will be of size |renderSize|.
      */
     PDocumentRenderer(nsRect documentRect, Matrix transform,
                       nsString bgcolor,
                       uint32_t renderFlags, bool flushLayout,
-                      nsIntSize renderSize);
+                      IntSize renderSize);
 
     /**
      * Sent by the chrome process when it no longer wants this remote
      * <browser>.  The child side cleans up in response, then
      * finalizing its death by sending back __delete__() to the
      * parent.
      */
     Destroy();
--- a/dom/ipc/PDocumentRenderer.ipdl
+++ b/dom/ipc/PDocumentRenderer.ipdl
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PBrowser;
 
 include "mozilla/GfxMessageUtils.h";
 
-using struct nsIntSize from "nsSize.h";
+using nsIntSize from "nsSize.h";
 
 namespace mozilla {
 namespace ipc {
 
 protocol PDocumentRenderer
 {
   manager PBrowser;
 
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -252,17 +252,17 @@ VideoData::Create(VideoInfo& aInfo,
   if (!aImage && !aContainer) {
     // Create a dummy VideoData with no image. This gives us something to
     // send to media streams if necessary.
     nsRefPtr<VideoData> v(new VideoData(aOffset,
                                         aTime,
                                         aDuration,
                                         aKeyframe,
                                         aTimecode,
-                                        aInfo.mDisplay.ToIntSize()));
+                                        aInfo.mDisplay));
     return v.forget();
   }
 
   // The following situation should never happen unless there is a bug
   // in the decoder
   if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth ||
       aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) {
     NS_ERROR("C planes with different sizes");
@@ -294,17 +294,17 @@ VideoData::Create(VideoInfo& aInfo,
     return nullptr;
   }
 
   nsRefPtr<VideoData> v(new VideoData(aOffset,
                                       aTime,
                                       aDuration,
                                       aKeyframe,
                                       aTimecode,
-                                      aInfo.mDisplay.ToIntSize()));
+                                      aInfo.mDisplay));
 #ifdef MOZ_WIDGET_GONK
   const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
   const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
   const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
 #endif
 
   if (!aImage) {
     // Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR
@@ -396,17 +396,17 @@ VideoData::CreateFromImage(VideoInfo& aI
                            int64_t aTimecode,
                            const IntRect& aPicture)
 {
   nsRefPtr<VideoData> v(new VideoData(aOffset,
                                       aTime,
                                       aDuration,
                                       aKeyframe,
                                       aTimecode,
-                                      aInfo.mDisplay.ToIntSize()));
+                                      aInfo.mDisplay));
   v->mImage = aImage;
   return v.forget();
 }
 
 #ifdef MOZ_OMX_DECODER
 /* static */
 already_AddRefed<VideoData>
 VideoData::Create(VideoInfo& aInfo,
@@ -422,17 +422,17 @@ VideoData::Create(VideoInfo& aInfo,
   if (!aContainer) {
     // Create a dummy VideoData with no image. This gives us something to
     // send to media streams if necessary.
     nsRefPtr<VideoData> v(new VideoData(aOffset,
                                         aTime,
                                         aDuration,
                                         aKeyframe,
                                         aTimecode,
-                                        aInfo.mDisplay.ToIntSize()));
+                                        aInfo.mDisplay));
     return v.forget();
   }
 
   // The following situations could be triggered by invalid input
   if (aPicture.width <= 0 || aPicture.height <= 0) {
     NS_WARNING("Empty picture rect");
     return nullptr;
   }
@@ -449,17 +449,17 @@ VideoData::Create(VideoInfo& aInfo,
     return nullptr;
   }
 
   nsRefPtr<VideoData> v(new VideoData(aOffset,
                                       aTime,
                                       aDuration,
                                       aKeyframe,
                                       aTimecode,
-                                      aInfo.mDisplay.ToIntSize()));
+                                      aInfo.mDisplay));
 
   v->mImage = aContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
   if (!v->mImage) {
     return nullptr;
   }
   NS_ASSERTION(v->mImage->GetFormat() == ImageFormat::GRALLOC_PLANAR_YCBCR,
                "Wrong format?");
   typedef mozilla::layers::GrallocImage GrallocImage;
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2792,18 +2792,17 @@ void MediaDecoderStateMachine::RenderVid
           frameStats.GetPresentedFrames() > 30 &&
           mCorruptFrames.mean() >= 1 /* 10% */) {
         DecodeTaskQueue()->Dispatch(NS_NewRunnableMethod(mReader, &MediaDecoderReader::DisableHardwareAcceleration));
         mDisabledHardwareAcceleration = true;
       }
     } else {
       mCorruptFrames.insert(0);
     }
-    container->SetCurrentFrame(ThebesIntSize(aData->mDisplay), aData->mImage,
-                               aTarget);
+    container->SetCurrentFrame(aData->mDisplay, aData->mImage, aTarget);
     MOZ_ASSERT(container->GetFrameDelay() >= 0 || IsRealTime());
   }
 }
 
 void MediaDecoderStateMachine::ResyncAudioClock()
 {
   AssertCurrentThreadInMonitor();
   if (IsPlaying()) {
--- a/dom/media/VideoSegment.cpp
+++ b/dom/media/VideoSegment.cpp
@@ -92,17 +92,17 @@ VideoChunk::~VideoChunk()
 
 void
 VideoSegment::AppendFrame(already_AddRefed<Image>&& aImage,
                           StreamTime aDuration,
                           const IntSize& aIntrinsicSize,
                           bool aForceBlack)
 {
   VideoChunk* chunk = AppendChunk(aDuration);
-  VideoFrame frame(aImage, ThebesIntSize(aIntrinsicSize));
+  VideoFrame frame(aImage, aIntrinsicSize);
   frame.SetForceBlack(aForceBlack);
   chunk->mFrame.TakeFrom(&frame);
 }
 
 VideoSegment::VideoSegment()
   : MediaSegmentBase<VideoSegment, VideoChunk>(VIDEO)
 {}
 
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -6,33 +6,33 @@
 
 #ifndef VideoUtils_h
 #define VideoUtils_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/CheckedInt.h"
 #include "nsIThread.h"
+#include "nsSize.h"
 
 #if !(defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) || \
     defined(MOZ_ASAN)
 // For MEDIA_THREAD_STACK_SIZE
 #include "nsIThreadManager.h"
 #endif
 #include "nsThreadUtils.h"
 #include "prtime.h"
 #include "AudioSampleFormat.h"
 #include "mozilla/RefPtr.h"
 
 using mozilla::CheckedInt64;
 using mozilla::CheckedUint64;
 using mozilla::CheckedInt32;
 using mozilla::CheckedUint32;
 
-struct nsIntSize;
 struct nsIntRect;
 
 // This file contains stuff we'd rather put elsewhere, but which is
 // dependent on other changes which we don't want to wait for. We plan to
 // remove this file in the near future.
 
 
 // This belongs in xpcom/monitor/Monitor.h, once we've made
--- a/dom/media/encoder/TrackEncoder.cpp
+++ b/dom/media/encoder/TrackEncoder.cpp
@@ -235,17 +235,17 @@ VideoTrackEncoder::AppendVideoSegment(co
   // Append all video segments from MediaStreamGraph, including null an
   // non-null frames.
   VideoSegment::ChunkIterator iter(const_cast<VideoSegment&>(aSegment));
   while (!iter.IsEnded()) {
     VideoChunk chunk = *iter;
     nsRefPtr<layers::Image> image = chunk.mFrame.GetImage();
     mRawSegment.AppendFrame(image.forget(),
                             chunk.GetDuration(),
-                            chunk.mFrame.GetIntrinsicSize().ToIntSize(),
+                            chunk.mFrame.GetIntrinsicSize(),
                             chunk.mFrame.GetForceBlack());
     iter.Next();
   }
 
   if (mRawSegment.GetDuration() > 0) {
     mReentrantMonitor.NotifyAll();
   }
 
--- a/dom/media/gstreamer/GStreamerReader.cpp
+++ b/dom/media/gstreamer/GStreamerReader.cpp
@@ -1116,17 +1116,17 @@ void GStreamerReader::VideoPreroll()
   nsIntSize frameSize = nsIntSize(mPicture.width, mPicture.height);
   nsIntSize displaySize = nsIntSize(mPicture.width, mPicture.height);
   ScaleDisplayByAspectRatio(displaySize, float(PARNumerator) / float(PARDenominator));
 
   // If video frame size is overflow, stop playing.
   if (IsValidVideoRegion(frameSize, pictureRect, displaySize)) {
     GstStructure* structure = gst_caps_get_structure(caps, 0);
     gst_structure_get_fraction(structure, "framerate", &fpsNum, &fpsDen);
-    mInfo.mVideo.mDisplay = ThebesIntSize(displaySize.ToIntSize());
+    mInfo.mVideo.mDisplay = displaySize;
     mInfo.mVideo.mHasVideo = true;
   } else {
     LOG(PR_LOG_DEBUG, "invalid video region");
     Eos();
   }
   gst_caps_unref(caps);
   gst_object_unref(sinkpad);
 }
--- a/dom/media/webspeech/synth/test/common.js
+++ b/dom/media/webspeech/synth/test/common.js
@@ -11,17 +11,17 @@ function SpeechTaskCallback(onpause, onr
 
 SpeechTaskCallback.prototype = {
   QueryInterface: function(iid) {
     return this;
   },
 
   getInterfaces: function(c) {},
 
-  getHelperForLanguage: function() {},
+  getScriptableHelper: function() {},
 
   onPause: function onPause() {
     if (this.onpause)
       this.onpause();
   },
 
   onResume: function onResume() {
     if (this.onresume)
@@ -53,17 +53,17 @@ var TestSpeechServiceWithAudio = Special
   },
 
   QueryInterface: function(iid) {
     return this;
   },
 
   getInterfaces: function(c) {},
 
-  getHelperForLanguage: function() {}
+  getScriptableHelper: function() {}
 });
 
 var TestSpeechServiceNoAudio = SpecialPowers.wrapCallbackObject({
   serviceType: SpecialPowers.Ci.nsISpeechService.SERVICETYPE_INDIRECT_AUDIO,
 
   speak: function speak(aText, aUri, aRate, aPitch, aTask) {
     var pair = this.expectedSpeaks.shift();
     if (pair) {
@@ -93,17 +93,17 @@ var TestSpeechServiceNoAudio = SpecialPo
   },
 
   QueryInterface: function(iid) {
     return this;
   },
 
   getInterfaces: function(c) {},
 
-  getHelperForLanguage: function() {},
+  getScriptableHelper: function() {},
 
   expectedSpeaks: []
 });
 
 function synthAddVoice(aServiceName, aName, aLang, aIsLocal) {
   if (SpecialPowers.isMainProcess()) {
     var voicesBefore = speechSynthesis.getVoices().length;
     var uri = "urn:moz-tts:mylittleservice:" + encodeURI(aName + '?' + aLang);
--- a/dom/media/wmf/DXVA2Manager.h
+++ b/dom/media/wmf/DXVA2Manager.h
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(DXVA2Manager_h_)
 #define DXVA2Manager_h_
 
 #include "WMF.h"
 #include "nsAutoPtr.h"
 #include "mozilla/Mutex.h"
 
-struct nsIntSize;
 struct nsIntRect;
 
 namespace mozilla {
 
 namespace layers {
 class Image;
 class ImageContainer;
 }
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsNPAPIPluginInstance_h_
 #define nsNPAPIPluginInstance_h_
 
+#include "nsSize.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsPIDOMWindow.h"
 #include "nsITimer.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsIURI.h"
 #include "nsIChannel.h"
 #include "nsHashKeys.h"
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -636,17 +636,17 @@ PluginInstanceParent::RecvShow(const NPR
                    updatedRect.bottom - updatedRect.top);
         surface->MarkDirty(ur);
 
         ImageContainer *container = GetImageContainer();
         nsRefPtr<Image> image = container->CreateImage(ImageFormat::CAIRO_SURFACE);
         NS_ASSERTION(image->GetFormat() == ImageFormat::CAIRO_SURFACE, "Wrong format?");
         CairoImage* cairoImage = static_cast<CairoImage*>(image.get());
         CairoImage::Data cairoData;
-        cairoData.mSize = surface->GetSize().ToIntSize();
+        cairoData.mSize = surface->GetSize();
         cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface);
         cairoImage->SetData(cairoData);
 
         container->SetCurrentImage(cairoImage);
     }
     else if (mImageContainer) {
         mImageContainer->SetCurrentImage(nullptr);
     }
--- a/dom/plugins/ipc/PluginLibrary.h
+++ b/dom/plugins/ipc/PluginLibrary.h
@@ -9,21 +9,21 @@
 
 #include "prlink.h"
 #include "npapi.h"
 #include "npfunctions.h"
 #include "nscore.h"
 #include "nsTArray.h"
 #include "nsError.h"
 #include "mozilla/EventForwards.h"
+#include "nsSize.h"
 
 class gfxContext;
 class nsCString;
 struct nsIntRect;
-struct nsIntSize;
 class nsNPAPIPlugin;
 
 namespace mozilla {
 namespace layers {
 class Image;
 class ImageContainer;
 }
 }
--- a/gfx/gl/GLTextureImage.cpp
+++ b/gfx/gl/GLTextureImage.cpp
@@ -115,23 +115,23 @@ gfx::DrawTarget*
 BasicTextureImage::BeginUpdate(nsIntRegion& aRegion)
 {
     NS_ASSERTION(!mUpdateDrawTarget, "BeginUpdate() without EndUpdate()?");
 
     // determine the region the client will need to repaint
     if (CanUploadSubTextures(mGLContext)) {
         GetUpdateRegion(aRegion);
     } else {
-        aRegion = nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize));
+        aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
     }
 
     mUpdateRegion = aRegion;
 
     nsIntRect rgnSize = mUpdateRegion.GetBounds();
-    if (!nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize)).Contains(rgnSize)) {
+    if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(rgnSize)) {
         NS_ERROR("update outside of image");
         return nullptr;
     }
 
     gfx::SurfaceFormat format =
         (GetContentType() == gfxContentType::COLOR) ?
         gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::B8G8R8A8;
     mUpdateDrawTarget =
@@ -141,18 +141,19 @@ BasicTextureImage::BeginUpdate(nsIntRegi
 }
 
 void
 BasicTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
 {
   // if the texture hasn't been initialized yet, or something important
   // changed, we need to recreate our backing surface and force the
   // client to paint everything
-  if (mTextureState != Valid)
-      aForRegion = nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize));
+  if (mTextureState != Valid) {
+      aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+  }
 }
 
 void
 BasicTextureImage::EndUpdate()
 {
     NS_ASSERTION(!!mUpdateDrawTarget, "EndUpdate() without BeginUpdate()?");
 
     // FIXME: this is the slow boat.  Make me fast (with GLXPixmap?).
@@ -260,47 +261,32 @@ BasicTextureImage::Resize(const gfx::Int
 }
 
 gfx::IntSize TextureImage::GetSize() const {
   return mSize;
 }
 
 TextureImage::TextureImage(const gfx::IntSize& aSize,
              GLenum aWrapMode, ContentType aContentType,
-             Flags aFlags)
+             Flags aFlags, ImageFormat aImageFormat)
     : mSize(aSize)
     , mWrapMode(aWrapMode)
     , mContentType(aContentType)
     , mFilter(GraphicsFilter::FILTER_GOOD)
     , mFlags(aFlags)
 {}
 
 BasicTextureImage::BasicTextureImage(GLuint aTexture,
-                                     const nsIntSize& aSize,
-                                     GLenum aWrapMode,
-                                     ContentType aContentType,
-                                     GLContext* aContext,
-                                     TextureImage::Flags aFlags /* = TextureImage::NoFlags */,
-                                     TextureImage::ImageFormat aImageFormat /* = gfxImageFormat::Unknown */)
-    : TextureImage(aSize, aWrapMode, aContentType, aFlags, aImageFormat)
-    , mTexture(aTexture)
-    , mTextureState(Created)
-    , mGLContext(aContext)
-    , mUpdateOffset(0, 0)
-{
-}
-
-BasicTextureImage::BasicTextureImage(GLuint aTexture,
                   const gfx::IntSize& aSize,
                   GLenum aWrapMode,
                   ContentType aContentType,
                   GLContext* aContext,
                   TextureImage::Flags aFlags,
                   TextureImage::ImageFormat aImageFormat)
-  : TextureImage(ThebesIntSize(aSize), aWrapMode, aContentType, aFlags, aImageFormat)
+  : TextureImage(aSize, aWrapMode, aContentType, aFlags, aImageFormat)
   , mTexture(aTexture)
   , mTextureState(Created)
   , mGLContext(aContext)
   , mUpdateOffset(0, 0)
 {}
 
 static bool
 WantsSmallTiles(GLContext* gl)
@@ -409,29 +395,29 @@ TiledTextureImage::DirectUpdate(gfx::Dat
 
 void
 TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
 {
     if (mTextureState != Valid) {
         // if the texture hasn't been initialized yet, or something important
         // changed, we need to recreate our backing surface and force the
         // client to paint everything
-        aForRegion = nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize));
+        aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
         return;
     }
 
     nsIntRegion newRegion;
 
     // We need to query each texture with the region it will be drawing and
     // set aForRegion to be the combination of all of these regions
     for (unsigned i = 0; i < mImages.Length(); i++) {
         int xPos = (i % mColumns) * mTileSize;
         int yPos = (i / mColumns) * mTileSize;
         nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos),
-                                        ThebesIntSize(mImages[i]->GetSize()));
+                                        mImages[i]->GetSize());
 
         if (aForRegion.Intersects(imageRect)) {
             // Make a copy of the region
             nsIntRegion subRegion;
             subRegion.And(aForRegion, imageRect);
             // Translate it into tile-space
             subRegion.MoveBy(-xPos, -yPos);
             // Query region
@@ -455,27 +441,27 @@ TiledTextureImage::BeginUpdate(nsIntRegi
     // Note, we don't call GetUpdateRegion here as if the updated region is
     // fully contained in a single tile, we get to avoid iterating through
     // the tiles again (and a little copying).
     if (mTextureState != Valid)
     {
         // if the texture hasn't been initialized yet, or something important
         // changed, we need to recreate our backing surface and force the
         // client to paint everything
-        aRegion = nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize));
+        aRegion = nsIntRect(nsIntPoint(0, 0), mSize);
     }
 
     nsIntRect bounds = aRegion.GetBounds();
 
     for (unsigned i = 0; i < mImages.Length(); i++) {
         int xPos = (i % mColumns) * mTileSize;
         int yPos = (i / mColumns) * mTileSize;
         nsIntRegion imageRegion =
           nsIntRegion(nsIntRect(nsIntPoint(xPos,yPos),
-                                ThebesIntSize(mImages[i]->GetSize())));
+                                mImages[i]->GetSize()));
 
         // a single Image can handle this update request
         if (imageRegion.Contains(aRegion)) {
             // adjust for tile offset
             aRegion.MoveBy(-xPos, -yPos);
             // forward the actual call
             RefPtr<gfx::DrawTarget> drawTarget = mImages[i]->BeginUpdate(aRegion);
             // caller expects container space
@@ -494,17 +480,17 @@ TiledTextureImage::BeginUpdate(nsIntRegi
     mUpdateRegion = aRegion;
     bounds = aRegion.GetBounds();
 
     // update covers multiple Images - create a temp surface to paint in
     gfx::SurfaceFormat format =
         (GetContentType() == gfxContentType::COLOR) ?
         gfx::SurfaceFormat::B8G8R8X8: gfx::SurfaceFormat::B8G8R8A8;
     mUpdateDrawTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO,
-                                                       bounds.Size().ToIntSize(),
+                                                       bounds.Size(),
                                                        format);
 
     return mUpdateDrawTarget;;
 }
 
 void
 TiledTextureImage::EndUpdate()
 {
@@ -520,17 +506,17 @@ TiledTextureImage::EndUpdate()
     RefPtr<gfx::SourceSurface> updateSnapshot = mUpdateDrawTarget->Snapshot();
     RefPtr<gfx::DataSourceSurface> updateData = updateSnapshot->GetDataSurface();
 
     // upload tiles from temp surface
     for (unsigned i = 0; i < mImages.Length(); i++) {
         int xPos = (i % mColumns) * mTileSize;
         int yPos = (i / mColumns) * mTileSize;
         nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos),
-                                        ThebesIntSize(mImages[i]->GetSize()));
+                                        mImages[i]->GetSize());
 
         nsIntRegion subregion;
         subregion.And(mUpdateRegion, imageRect);
         if (subregion.IsEmpty())
             continue;
         subregion.MoveBy(-xPos, -yPos); // Tile-local space
         // copy tile from temp target
         gfx::DrawTarget* drawTarget = mImages[i]->BeginUpdate(subregion);
--- a/gfx/gl/GLTextureImage.h
+++ b/gfx/gl/GLTextureImage.h
@@ -206,32 +206,20 @@ protected:
     friend class GLContext;
 
     /**
      * After the ctor, the TextureImage is invalid.  Implementations
      * must allocate resources successfully before returning the new
      * TextureImage from GLContext::CreateTextureImage().  That is,
      * clients must not be given partially-constructed TextureImages.
      */
-    TextureImage(const nsIntSize& aSize,
+    TextureImage(const gfx::IntSize& aSize,
                  GLenum aWrapMode, ContentType aContentType,
                  Flags aFlags = NoFlags,
-                 ImageFormat aImageFormat = gfxImageFormat::Unknown)
-        : mSize(aSize.ToIntSize())
-        , mWrapMode(aWrapMode)
-        , mContentType(aContentType)
-        , mImageFormat(aImageFormat)
-        , mFilter(GraphicsFilter::FILTER_GOOD)
-        , mFlags(aFlags)
-    {}
-
-    // Moz2D equivalent...
-    TextureImage(const gfx::IntSize& aSize,
-                 GLenum aWrapMode, ContentType aContentType,
-                 Flags aFlags = NoFlags);
+                 ImageFormat aImageFormat = gfxImageFormat::Unknown);
 
     // Protected destructor, to discourage deletion outside of Release():
     virtual ~TextureImage() {}
 
     virtual gfx::IntRect GetSrcTileRect();
 
     gfx::IntSize mSize;
     GLenum mWrapMode;
@@ -253,23 +241,16 @@ protected:
  */
 class BasicTextureImage
     : public TextureImage
 {
 public:
     virtual ~BasicTextureImage();
 
     BasicTextureImage(GLuint aTexture,
-                      const nsIntSize& aSize,
-                      GLenum aWrapMode,
-                      ContentType aContentType,
-                      GLContext* aContext,
-                      TextureImage::Flags aFlags = TextureImage::NoFlags,
-                      TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
-    BasicTextureImage(GLuint aTexture,
                       const gfx::IntSize& aSize,
                       GLenum aWrapMode,
                       ContentType aContentType,
                       GLContext* aContext,
                       TextureImage::Flags aFlags = TextureImage::NoFlags,
                       TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
 
     virtual void BindTexture(GLenum aTextureUnit);
--- a/gfx/gl/TextureImageEGL.cpp
+++ b/gfx/gl/TextureImageEGL.cpp
@@ -97,17 +97,17 @@ TextureImageEGL::~TextureImageEGL()
 }
 
 void
 TextureImageEGL::GetUpdateRegion(nsIntRegion& aForRegion)
 {
     if (mTextureState != Valid) {
         // if the texture hasn't been initialized yet, force the
         // client to paint everything
-        aForRegion = nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize));
+        aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
     }
 
     // We can only draw a rectangle, not subregions due to
     // the way that our texture upload functions work.  If
     // needed, we /could/ do multiple texture uploads if we have
     // non-overlapping rects, but that's a tradeoff.
     aForRegion = nsIntRegion(aForRegion.GetBounds());
 }
@@ -117,17 +117,17 @@ TextureImageEGL::BeginUpdate(nsIntRegion
 {
     NS_ASSERTION(!mUpdateDrawTarget, "BeginUpdate() without EndUpdate()?");
 
     // determine the region the client will need to repaint
     GetUpdateRegion(aRegion);
     mUpdateRect = aRegion.GetBounds();
 
     //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
-    if (!nsIntRect(nsIntPoint(0, 0), gfx::ThebesIntSize(mSize)).Contains(mUpdateRect)) {
+    if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
         NS_ERROR("update outside of image");
         return nullptr;
     }
 
     //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
 
     mUpdateDrawTarget = gfx::Factory::CreateDrawTarget(gfx::BackendType::CAIRO,
                                                        gfx::IntSize(mUpdateRect.width, mUpdateRect.height),
@@ -161,17 +161,17 @@ TextureImageEGL::EndUpdate()
         return;
     }
 
     mGLContext->MakeCurrent();
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
 
     if (mTextureState != Valid) {
         NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
-                      mUpdateRect.Size() == gfx::ThebesIntSize(mSize),
+                      mUpdateRect.Size() == mSize,
                       "Bad initial update on non-created texture!");
 
         mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
                                 0,
                                 GLFormatForImage(mUpdateFormat),
                                 mUpdateRect.width,
                                 mUpdateRect.height,
                                 0,
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -101,17 +101,16 @@
  * interfaces:
  * - Compositor (ex. CompositorOGL)
  * - TextureHost (ex. SurfaceTextureHost)
  * Depending on the type of data that needs to be serialized, you may need to
  * add specific TextureClient implementations.
  */
 
 class nsIWidget;
-struct nsIntSize;
 class nsIntRegion;
 
 namespace mozilla {
 namespace gfx {
 class Matrix;
 class Matrix4x4;
 class DrawTarget;
 }
--- a/gfx/layers/ImageLayers.cpp
+++ b/gfx/layers/ImageLayers.cpp
@@ -28,17 +28,17 @@ void ImageLayer::SetContainer(ImageConta
 
 void ImageLayer::ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
 {
   gfx::Matrix4x4 local = GetLocalTransform();
 
   // Snap image edges to pixel boundaries
   gfxRect sourceRect(0, 0, 0, 0);
   if (mContainer) {
-    sourceRect.SizeTo(gfx::ThebesIntSize(mContainer->GetCurrentSize()));
+    sourceRect.SizeTo(mContainer->GetCurrentSize());
   }
   // Snap our local transform first, and snap the inherited transform as well.
   // This makes our snapping equivalent to what would happen if our content
   // was drawn into a PaintedLayer (gfxContext would snap using the local
   // transform, then we'd snap again when compositing the PaintedLayer).
   mEffectiveTransform =
       SnapTransform(local, sourceRect, nullptr) *
       SnapTransformTranslation(aTransformToSurface, nullptr);
--- a/gfx/layers/LayerScope.h
+++ b/gfx/layers/LayerScope.h
@@ -5,18 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_LAYERSCOPE_H
 #define GFX_LAYERSCOPE_H
 
 #include <stdint.h>
 #include <mozilla/UniquePtr.h>
 
-struct nsIntSize;
-
 namespace mozilla {
 
 namespace gl { class GLContext; }
 
 namespace layers {
 
 namespace layerscope { class Packet; }
 
--- a/gfx/layers/LayersLogging.cpp
+++ b/gfx/layers/LayersLogging.cpp
@@ -160,25 +160,16 @@ AppendToString(std::stringstream& aStrea
   }
   if (!e.mVerticalPanRegion.IsEmpty()) {
     AppendToString(aStream, e.mVerticalPanRegion, " VerticalPanRegion=", "");
   }
   aStream << "}" << sfx;
 }
 
 void
-AppendToString(std::stringstream& aStream, const nsIntSize& sz,
-               const char* pfx, const char* sfx)
-{
-  aStream << pfx;
-  aStream << nsPrintfCString("(w=%d, h=%d)", sz.width, sz.height).get();
-  aStream << sfx;
-}
-
-void
 AppendToString(std::stringstream& aStream, const FrameMetrics& m,
                const char* pfx, const char* sfx, bool detailed)
 {
   aStream << pfx;
   AppendToString(aStream, m.mCompositionBounds, "{ [cb=");
   AppendToString(aStream, m.GetScrollableRect(), "] [sr=");
   AppendToString(aStream, m.GetScrollOffset(), "] [s=");
   if (m.GetDoSmoothScroll()) {
--- a/gfx/layers/LayersLogging.h
+++ b/gfx/layers/LayersLogging.h
@@ -14,17 +14,16 @@
 #include "nsAString.h"
 #include "nsPrintfCString.h"            // for nsPrintfCString
 #include "nsRegion.h"                   // for nsRegion, nsIntRegion
 #include "nscore.h"                     // for nsACString, etc
 
 struct gfxRGBA;
 struct nsIntPoint;
 struct nsIntRect;
-struct nsIntSize;
 
 namespace mozilla {
 namespace gfx {
 class Matrix4x4;
 template <class units> struct RectTyped;
 }
 
 namespace layers {
@@ -129,20 +128,16 @@ AppendToString(std::stringstream& aStrea
   aStream << sfx;
 }
 
 void
 AppendToString(std::stringstream& aStream, const EventRegions& e,
                const char* pfx="", const char* sfx="");
 
 void
-AppendToString(std::stringstream& aStream, const nsIntSize& sz,
-               const char* pfx="", const char* sfx="");
-
-void
 AppendToString(std::stringstream& aStream, const FrameMetrics& m,
                const char* pfx="", const char* sfx="", bool detailed = false);
 
 void
 AppendToString(std::stringstream& aStream, const ScrollableLayerGuid& s,
                const char* pfx="", const char* sfx="");
 
 template<class T>
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -16,18 +16,16 @@
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsPoint.h"                    // for nsIntPoint
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "LayersTypes.h"
 
-struct nsIntSize;
-
 namespace mozilla {
 namespace gfx {
 class Matrix;
 }
 
 namespace layers {
 
 class TextureClient;
@@ -384,17 +382,17 @@ protected:
   static bool IsClippingCheap(gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);
 
 protected:
   /**
    * Return the buffer's content type.  Requires a valid buffer or
    * buffer provider.
    */
   gfxContentType BufferContentType();
-  bool BufferSizeOkFor(const nsIntSize& aSize);
+  bool BufferSizeOkFor(const gfx::IntSize& aSize);
   /**
    * If the buffer hasn't been mapped, map it.
    */
   bool EnsureBuffer();
   bool EnsureBufferOnWhite();
 
   // Flush our buffers if they are mapped.
   void FlushBuffers();
--- a/gfx/layers/basic/X11BasicCompositor.cpp
+++ b/gfx/layers/basic/X11BasicCompositor.cpp
@@ -30,22 +30,22 @@ X11DataTextureSourceBasic::Update(gfx::D
     gfxImageFormat imageFormat = SurfaceFormatToImageFormat(aSurface->GetFormat());
     Display *display = DefaultXDisplay();
     Screen *screen = DefaultScreenOfDisplay(display);
     XRenderPictFormat *xrenderFormat =
       gfxXlibSurface::FindRenderFormat(display, imageFormat);
 
     if (xrenderFormat) {
       surf = gfxXlibSurface::Create(screen, xrenderFormat,
-                                    ThebesIntSize(aSurface->GetSize()));
+                                    aSurface->GetSize());
     }
 
     if (!surf) {
       NS_WARNING("Couldn't create native surface, fallback to image surface");
-      surf = new gfxImageSurface(ThebesIntSize(aSurface->GetSize()), imageFormat);
+      surf = new gfxImageSurface(aSurface->GetSize(), imageFormat);
     }
 
     mBufferDrawTarget = gfxPlatform::GetPlatform()->
       CreateDrawTargetForSurface(surf, aSurface->GetSize());
   }
 
   // Image contents have changed, upload to our DrawTarget
   // If aDestRegion is null, means we're updating the whole surface
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -471,17 +471,17 @@ ClientLayerManager::MakeSnapshotIfRequir
 
       nsIntRect bounds = ToOutsideIntRect(mShadowTarget->GetClipExtents());
       if (mTargetRotation) {
         bounds = RotateRect(bounds, outerBounds, mTargetRotation);
       }
 
       SurfaceDescriptor inSnapshot;
       if (!bounds.IsEmpty() &&
-          mForwarder->AllocSurfaceDescriptor(bounds.Size().ToIntSize(),
+          mForwarder->AllocSurfaceDescriptor(bounds.Size(),
                                              gfxContentType::COLOR_ALPHA,
                                              &inSnapshot) &&
           remoteRenderer->SendMakeSnapshot(inSnapshot, bounds)) {
         RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(inSnapshot);
         DrawTarget* dt = mShadowTarget->GetDrawTarget();
 
         Rect dstRect(bounds.x, bounds.y, bounds.width, bounds.height);
         Rect srcRect(0, 0, bounds.width, bounds.height);
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -54,18 +54,16 @@
 #include "nsRegion.h"                   // for nsIntRegion, etc
 #ifdef MOZ_WIDGET_ANDROID
 #include <android/log.h>
 #endif
 #include "GeckoProfiler.h"
 #include "TextRenderer.h"               // for TextRenderer
 
 class gfxContext;
-struct nsIntSize;
-
 
 namespace mozilla {
 namespace layers {
 
 class ImageLayer;
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -26,18 +26,16 @@
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsRect.h"                     // for nsIntRect
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nscore.h"                     // for nsAString, etc
 #include "LayerTreeInvalidation.h"
 
 class gfxContext;
-struct nsIntPoint;
-struct nsIntSize;
 
 #ifdef XP_WIN
 #include <windows.h>
 #endif
 
 namespace mozilla {
 namespace gfx {
 class DrawTarget;
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -25,18 +25,16 @@
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"                   // for nsIntRegion
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nscore.h"                     // for nsACString
 #include "mozilla/layers/AtomicRefCountedWithFinalize.h"
 
 class gfxReusableSurfaceWrapper;
-struct nsIntPoint;
-struct nsIntSize;
 struct nsIntRect;
 
 namespace mozilla {
 namespace gl {
 class SharedSurface;
 }
 namespace ipc {
 class Shmem;
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -29,17 +29,16 @@
 
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
 #include <ui/Fence.h>
 #endif
 
 class gfxReusableSurfaceWrapper;
 struct nsIntPoint;
 struct nsIntRect;
-struct nsIntSize;
 
 namespace mozilla {
 namespace gfx {
 class Matrix4x4;
 }
 
 namespace layers {
 
@@ -304,17 +303,17 @@ private:
                   const gfxRGBA* aBackgroundColor,
                   EffectChain& aEffectChain,
                   float aOpacity,
                   const gfx::Matrix4x4& aTransform,
                   const gfx::Filter& aFilter,
                   const gfx::Rect& aClipRect,
                   const nsIntRegion& aScreenRegion,
                   const nsIntPoint& aTextureOffset,
-                  const nsIntSize& aTextureBounds);
+                  const gfx::IntSize& aTextureBounds);
 
   void EnsureTileStore() {}
 
   TiledLayerBufferComposite    mTiledBuffer;
   TiledLayerBufferComposite    mLowPrecisionTiledBuffer;
   TiledLayerBufferComposite    mOldTiledBuffer;
   TiledLayerBufferComposite    mOldLowPrecisionTiledBuffer;
   bool                         mPendingUpload;
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -1260,17 +1260,17 @@ CompositorD3D11::UpdateRenderTarget()
   nsRefPtr<ID3D11Texture2D> backBuf;
 
   hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuf.StartAssignment());
   if (Failed(hr)) {
     return;
   }
 
   mDefaultRT = new CompositingRenderTargetD3D11(backBuf, IntPoint(0, 0));
-  mDefaultRT->SetSize(mSize.ToIntSize());
+  mDefaultRT->SetSize(mSize);
 }
 
 bool
 CompositorD3D11::CreateShaders()
 {
   HRESULT hr;
 
   hr = mDevice->CreateVertexShader(LayerQuadVS,
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -703,17 +703,17 @@ CairoTextureClientD3D9::BorrowDrawTarget
       return nullptr;
     }
   } else {
     // gfxWindowsSurface don't support transparency so we can't use the d3d9
     // windows surface optimization.
     // Instead we have to use a gfxImageSurface and fallback for font drawing.
     D3DLOCKED_RECT rect;
     mD3D9Surface->LockRect(&rect, nullptr, 0);
-    mSurface = new gfxImageSurface((uint8_t*)rect.pBits, ThebesIntSize(mSize),
+    mSurface = new gfxImageSurface((uint8_t*)rect.pBits, mSize,
                                    rect.Pitch, SurfaceFormatToImageFormat(mFormat));
     mLockRect = true;
   }
 
   mDrawTarget =
     gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize);
 
   return mDrawTarget;
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -1,16 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 using struct gfxPoint from "gfxPoint.h";
 using struct nsIntRect from "nsRect.h";
 using nsIntRegion from "nsRegion.h";
-using struct nsIntSize from "nsSize.h";
 using struct mozilla::layers::MagicGrallocBufferHandle from "gfxipc/ShadowLayerUtils.h";
 using struct mozilla::layers::GrallocBufferRef from "gfxipc/ShadowLayerUtils.h";
 using struct mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h";
 using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
 using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
 using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
 using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
 using gfxImageFormat from "gfxTypes.h";
--- a/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsX11.cpp
@@ -59,17 +59,17 @@ GetXRenderPictFormatFromId(Display* aDis
 {
   XRenderPictFormat tmplate;
   tmplate.id = aFormatId;
   return XRenderFindFormat(aDisplay, PictFormatID, &tmplate, 0);
 }
 
 SurfaceDescriptorX11::SurfaceDescriptorX11(gfxXlibSurface* aSurf)
   : mId(aSurf->XDrawable())
-  , mSize(aSurf->GetSize().ToIntSize())
+  , mSize(aSurf->GetSize())
 {
   const XRenderPictFormat *pictFormat = aSurf->XRenderFormat();
   if (pictFormat) {
     mFormat = pictFormat->id;
   } else {
     mFormat = cairo_xlib_surface_get_visual(aSurf->CairoSurface())->visualid;
   }
 }
@@ -85,25 +85,25 @@ already_AddRefed<gfxXlibSurface>
 SurfaceDescriptorX11::OpenForeign() const
 {
   Display* display = DefaultXDisplay();
   Screen* screen = DefaultScreenOfDisplay(display);
 
   nsRefPtr<gfxXlibSurface> surf;
   XRenderPictFormat* pictFormat = GetXRenderPictFormatFromId(display, mFormat);
   if (pictFormat) {
-    surf = new gfxXlibSurface(screen, mId, pictFormat, gfx::ThebesIntSize(mSize));
+    surf = new gfxXlibSurface(screen, mId, pictFormat, mSize);
   } else {
     Visual* visual;
     int depth;
     FindVisualAndDepth(display, mFormat, &visual, &depth);
     if (!visual)
       return nullptr;
 
-    surf = new gfxXlibSurface(display, mId, visual, gfx::ThebesIntSize(mSize));
+    surf = new gfxXlibSurface(display, mId, visual, mSize);
   }
   return surf->CairoStatus() ? nullptr : surf.forget();
 }
 
 /*static*/ void
 ShadowLayerForwarder::PlatformSyncBeforeUpdate()
 {
   if (UsingXCompositing()) {
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -215,17 +215,17 @@ GrallocTextureHostOGL::GetRenderState()
     }
     if (mFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
       flags |= LayerRenderStateFlags::ORIGIN_BOTTOM_LEFT;
     }
     if (mFlags & TextureFlags::RB_SWAPPED) {
       flags |= LayerRenderStateFlags::FORMAT_RB_SWAP;
     }
     return LayerRenderState(graphicBuffer,
-                            gfx::ThebesIntSize(mDescriptorSize),
+                            mDescriptorSize,
                             flags,
                             this);
   }
 
   return LayerRenderState();
 }
 
 TemporaryRef<gfx::DataSourceSurface>
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -275,25 +275,25 @@ TextureImageTextureSourceOGL::Update(gfx
   return true;
 }
 
 void
 TextureImageTextureSourceOGL::EnsureBuffer(const nsIntSize& aSize,
                                            gfxContentType aContentType)
 {
   if (!mTexImage ||
-      mTexImage->GetSize() != aSize.ToIntSize() ||
+      mTexImage->GetSize() != aSize ||
       mTexImage->GetContentType() != aContentType) {
     mTexImage = CreateTextureImage(mCompositor->gl(),
-                                   aSize.ToIntSize(),
+                                   aSize,
                                    aContentType,
                                    LOCAL_GL_CLAMP_TO_EDGE,
                                    FlagsToGLFlags(mFlags));
   }
-  mTexImage->Resize(aSize.ToIntSize());
+  mTexImage->Resize(aSize);
 }
 
 void
 TextureImageTextureSourceOGL::CopyTo(const nsIntRect& aSourceRect,
                                      DataTextureSource *aDest,
                                      const nsIntRect& aDestRect)
 {
   MOZ_ASSERT(aDest->AsSourceOGL(), "Incompatible destination type!");
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -36,17 +36,16 @@
 #include <ui/Fence.h>
 #endif
 #endif
 
 class gfxReusableSurfaceWrapper;
 class nsIntRegion;
 struct nsIntPoint;
 struct nsIntRect;
-struct nsIntSize;
 
 namespace mozilla {
 namespace gfx {
 class DataSourceSurface;
 }
 
 namespace gl {
 class AndroidSurfaceTexture;
@@ -197,18 +196,18 @@ public:
   {}
 
   // DataTextureSource
 
   virtual bool Update(gfx::DataSourceSurface* aSurface,
                       nsIntRegion* aDestRegion = nullptr,
                       gfx::IntPoint* aSrcOffset = nullptr) override;
 
-  void EnsureBuffer(const nsIntSize& aSize,
-                            gfxContentType aContentType);
+  void EnsureBuffer(const gfx::IntSize& aSize,
+                    gfxContentType aContentType);
 
   void CopyTo(const nsIntRect& aSourceRect,
                       DataTextureSource* aDest,
                       const nsIntRect& aDestRect);
 
   virtual TextureImageTextureSourceOGL* AsTextureImageTextureSource() override { return this; }
 
   // TextureSource
--- a/gfx/src/nsITheme.h
+++ b/gfx/src/nsITheme.h
@@ -7,20 +7,20 @@
 /* service providing platform-specific native rendering for widgets */
 
 #ifndef nsITheme_h_
 #define nsITheme_h_
 
 #include "nsISupports.h"
 #include "nsCOMPtr.h"
 #include "nsColor.h"
+#include "nsSize.h"
 
 struct nsRect;
 struct nsIntRect;
-struct nsIntSize;
 class nsIntRegion;
 struct nsFont;
 struct nsIntMargin;
 class nsPresContext;
 class nsRenderingContext;
 class nsDeviceContext;
 class nsIFrame;
 class nsIContent;
--- a/gfx/src/nsSize.h
+++ b/gfx/src/nsSize.h
@@ -8,17 +8,17 @@
 
 #include "nsCoord.h"
 #include "mozilla/gfx/BaseSize.h"
 #include "mozilla/gfx/Point.h"
 
 // Maximum allowable size
 #define NS_MAXSIZE nscoord_MAX
 
-struct nsIntSize;
+typedef mozilla::gfx::IntSize nsIntSize;
 typedef nsIntSize gfxIntSize;
 
 struct nsSize : public mozilla::gfx::BaseSize<nscoord, nsSize> {
   typedef mozilla::gfx::BaseSize<nscoord, nsSize> Super;
 
   nsSize() : Super() {}
   nsSize(nscoord aWidth, nscoord aHeight) : Super(aWidth, aHeight) {}
 
@@ -30,29 +30,16 @@ struct nsSize : public mozilla::gfx::Bas
    * Return this size scaled to a different appunits per pixel (APP) ratio.
    * @param aFromAPP the APP to scale from
    * @param aToAPP the APP to scale to
    */
   MOZ_WARN_UNUSED_RESULT inline nsSize
     ScaleToOtherAppUnits(int32_t aFromAPP, int32_t aToAPP) const;
 };
 
-struct nsIntSize : public mozilla::gfx::BaseSize<int32_t, nsIntSize> {
-  typedef mozilla::gfx::BaseSize<int32_t, nsIntSize> Super;
-
-  nsIntSize() : Super() {}
-  nsIntSize(int32_t aWidth, int32_t aHeight) : Super(aWidth, aHeight) {}
-
-  inline nsSize ToAppUnits(nscoord aAppUnitsPerPixel) const;
-  mozilla::gfx::IntSize ToIntSize() const
-  {
-    return mozilla::gfx::IntSize(width, height);
-  };
-};
-
 inline nsIntSize
 nsSize::ScaleToNearestPixels(float aXScale, float aYScale,
                              nscoord aAppUnitsPerPixel) const
 {
   return nsIntSize(
       NSToIntRoundUp(NSAppUnitsToDoublePixels(width, aAppUnitsPerPixel) * aXScale),
       NSToIntRoundUp(NSAppUnitsToDoublePixels(height, aAppUnitsPerPixel) * aYScale));
 }
@@ -70,15 +57,15 @@ nsSize::ScaleToOtherAppUnits(int32_t aFr
     size.width = NSToCoordRound(NSCoordScale(width, aFromAPP, aToAPP));
     size.height = NSToCoordRound(NSCoordScale(height, aFromAPP, aToAPP));
     return size;
   }
   return *this;
 }
 
 inline nsSize
-nsIntSize::ToAppUnits(nscoord aAppUnitsPerPixel) const
+IntSizeToAppUnits(mozilla::gfx::IntSize aSize, nscoord aAppUnitsPerPixel)
 {
-  return nsSize(NSIntPixelsToAppUnits(width, aAppUnitsPerPixel),
-                NSIntPixelsToAppUnits(height, aAppUnitsPerPixel));
+  return nsSize(NSIntPixelsToAppUnits(aSize.width, aAppUnitsPerPixel),
+                NSIntPixelsToAppUnits(aSize.height, aAppUnitsPerPixel));
 }
 
 #endif /* NSSIZE_H */
--- a/gfx/tests/gtest/TestTextures.cpp
+++ b/gfx/tests/gtest/TestTextures.cpp
@@ -184,17 +184,17 @@ void TestTextureClientSurface(TextureCli
   // Compositor to do that. We could add a DummyComposior for testing but I am
   // not sure it'll be worth it. Maybe always test against a BasicCompositor,
   // but the latter needs a widget...
   if (host->Lock()) {
     RefPtr<mozilla::gfx::DataSourceSurface> hostDataSurface = host->GetAsSurface();
 
     nsRefPtr<gfxImageSurface> hostSurface =
       new gfxImageSurface(hostDataSurface->GetData(),
-                          ThebesIntSize(hostDataSurface->GetSize()),
+                          hostDataSurface->GetSize(),
                           hostDataSurface->Stride(),
                           SurfaceFormatToImageFormat(hostDataSurface->GetFormat()));
     AssertSurfacesEqual(surface, hostSurface.get());
     host->Unlock();
   }
 }
 
 // Same as above, for YCbCr surfaces
@@ -292,19 +292,19 @@ TEST(Layers, TextureYCbCrSerialization) 
   SetupSurface(ySurface.get());
   SetupSurface(cbSurface.get());
   SetupSurface(crSurface.get());
 
   PlanarYCbCrData clientData;
   clientData.mYChannel = ySurface->Data();
   clientData.mCbChannel = cbSurface->Data();
   clientData.mCrChannel = crSurface->Data();
-  clientData.mYSize = ySurface->GetSize().ToIntSize();
-  clientData.mPicSize = ySurface->GetSize().ToIntSize();
-  clientData.mCbCrSize = cbSurface->GetSize().ToIntSize();
+  clientData.mYSize = ySurface->GetSize();
+  clientData.mPicSize = ySurface->GetSize();
+  clientData.mCbCrSize = cbSurface->GetSize();
   clientData.mYStride = ySurface->Stride();
   clientData.mCbCrStride = cbSurface->Stride();
   clientData.mStereoMode = StereoMode::MONO;
   clientData.mYSkip = 0;
   clientData.mCbSkip = 0;
   clientData.mCrSkip = 0;
   clientData.mCrSkip = 0;
   clientData.mPicX = 0;
--- a/gfx/thebes/gfx2DGlue.h
+++ b/gfx/thebes/gfx2DGlue.h
@@ -152,21 +152,16 @@ inline gfxPoint ThebesPoint(const Point 
   return gfxPoint(aPoint.x, aPoint.y);
 }
 
 inline gfxSize ThebesSize(const Size &aSize)
 {
   return gfxSize(aSize.width, aSize.height);
 }
 
-inline gfxIntSize ThebesIntSize(const IntSize &aSize)
-{
-  return gfxIntSize(aSize.width, aSize.height);
-}
-
 inline gfxRect ThebesRect(const Rect &aRect)
 {
   return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
 }
 
 inline nsIntRect ThebesIntRect(const IntRect &aRect)
 {
   return nsIntRect(aRect.x, aRect.y, aRect.width, aRect.height);
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -127,18 +127,17 @@ gfxAndroidPlatform::~gfxAndroidPlatform(
     gPlatformFTLibrary = nullptr;
 }
 
 already_AddRefed<gfxASurface>
 gfxAndroidPlatform::CreateOffscreenSurface(const IntSize& size,
                                            gfxContentType contentType)
 {
     nsRefPtr<gfxASurface> newSurface;
-    newSurface = new gfxImageSurface(ThebesIntSize(size),
-                                     OptimalFormatForContent(contentType));
+    newSurface = new gfxImageSurface(size, OptimalFormatForContent(contentType));
 
     return newSurface.forget();
 }
 
 static bool
 IsJapaneseLocale()
 {
     static bool sInitialized = false;
--- a/gfx/thebes/gfxDrawable.cpp
+++ b/gfx/thebes/gfxDrawable.cpp
@@ -110,17 +110,17 @@ gfxCallbackDrawable::gfxCallbackDrawable
 }
 
 already_AddRefed<gfxSurfaceDrawable>
 gfxCallbackDrawable::MakeSurfaceDrawable(const GraphicsFilter aFilter)
 {
     SurfaceFormat format =
         gfxPlatform::GetPlatform()->Optimal2DFormatForContent(gfxContentType::COLOR_ALPHA);
     RefPtr<DrawTarget> dt =
-        gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(mSize.ToIntSize(),
+        gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(mSize,
                                                                      format);
     if (!dt)
         return nullptr;
 
     nsRefPtr<gfxContext> ctx = new gfxContext(dt);
     Draw(ctx, gfxRect(0, 0, mSize.width, mSize.height), false, aFilter);
 
     RefPtr<SourceSurface> surface = dt->Snapshot();
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -99,34 +99,34 @@ gfxPlatformGtk::CreateOffscreenSurface(c
         if (UseXRender() && !UseImageOffscreenSurfaces()) {
             Screen *screen = gdk_x11_screen_get_xscreen(gdkScreen);
             XRenderPictFormat* xrenderFormat =
                 gfxXlibSurface::FindRenderFormat(DisplayOfScreen(screen),
                                                  imageFormat);
 
             if (xrenderFormat) {
                 newSurface = gfxXlibSurface::Create(screen, xrenderFormat,
-                                                    ThebesIntSize(size));
+                                                    size);
             }
         } else {
             // We're not going to use XRender, so we don't need to
             // search for a render format
-            newSurface = new gfxImageSurface(ThebesIntSize(size), imageFormat);
+            newSurface = new gfxImageSurface(size, imageFormat);
             // The gfxImageSurface ctor zeroes this for us, no need to
             // waste time clearing again
             needsClear = false;
         }
     }
 #endif
 
     if (!newSurface) {
         // We couldn't create a native surface for whatever reason;
         // e.g., no display, no RENDER, bad size, etc.
         // Fall back to image surface for the data.
-        newSurface = new gfxImageSurface(ThebesIntSize(size), imageFormat);
+        newSurface = new gfxImageSurface(size, imageFormat);
     }
 
     if (newSurface->CairoStatus()) {
         newSurface = nullptr; // surface isn't valid for some reason
     }
 
     if (newSurface && needsClear) {
         gfxUtils::ClearThebesSurface(newSurface);
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -111,18 +111,17 @@ gfxPlatformMac::CreatePlatformFontList()
     return nullptr;
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformMac::CreateOffscreenSurface(const IntSize& size,
                                        gfxContentType contentType)
 {
     nsRefPtr<gfxASurface> newSurface =
-      new gfxQuartzSurface(ThebesIntSize(size),
-                           OptimalFormatForContent(contentType));
+      new gfxQuartzSurface(size, OptimalFormatForContent(contentType));
     return newSurface.forget();
 }
 
 TemporaryRef<ScaledFont>
 gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
     gfxMacFont *font = static_cast<gfxMacFont*>(aFont);
     return font->GetScaledFont(aTarget);
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -768,28 +768,28 @@ gfxWindowsPlatform::CreatePlatformFontLi
 already_AddRefed<gfxASurface>
 gfxWindowsPlatform::CreateOffscreenSurface(const IntSize& size,
                                            gfxContentType contentType)
 {
     nsRefPtr<gfxASurface> surf = nullptr;
 
 #ifdef CAIRO_HAS_WIN32_SURFACE
     if (mRenderMode == RENDER_GDI)
-        surf = new gfxWindowsSurface(ThebesIntSize(size),
+        surf = new gfxWindowsSurface(size,
                                      OptimalFormatForContent(contentType));
 #endif
 
 #ifdef CAIRO_HAS_D2D_SURFACE
     if (mRenderMode == RENDER_DIRECT2D)
-        surf = new gfxD2DSurface(ThebesIntSize(size),
+        surf = new gfxD2DSurface(size,
                                  OptimalFormatForContent(contentType));
 #endif
 
     if (!surf || surf->CairoStatus()) {
-        surf = new gfxImageSurface(ThebesIntSize(size),
+        surf = new gfxImageSurface(size,
                                    OptimalFormatForContent(contentType));
     }
 
     return surf.forget();
 }
 
 TemporaryRef<ScaledFont>
 gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
--- a/gfx/thebes/gfxXlibNativeRenderer.h
+++ b/gfx/thebes/gfxXlibNativeRenderer.h
@@ -15,17 +15,16 @@ namespace gfx {
   class DrawTarget;
 }
 }
 
 class gfxASurface;
 class gfxContext;
 struct nsIntRect;
 struct nsIntPoint;
-struct nsIntSize;
 typedef struct _cairo cairo_t;
 typedef struct _cairo_surface cairo_surface_t;
 
 /**
  * This class lets us take code that draws into an X drawable and lets us
  * use it to draw into any Thebes context. The user should subclass this class,
  * override DrawWithXib, and then call Draw(). The drawing will be subjected
  * to all Thebes transformations, clipping etc.
@@ -77,28 +76,28 @@ public:
      * (0,0,size.width,size.height).
      * @param screen a Screen to use for the drawing if ctx doesn't have one.
      * @param visual a Visual to use for the drawing if ctx doesn't have one.
      * @param result if non-null, we will try to capture a copy of the
      * rendered image into a surface similar to the surface of ctx; if
      * successful, a pointer to the new gfxASurface is stored in *resultSurface,
      * otherwise *resultSurface is set to nullptr.
      */
-    void Draw(gfxContext* ctx, nsIntSize size,
+    void Draw(gfxContext* ctx, mozilla::gfx::IntSize size,
               uint32_t flags, Screen *screen, Visual *visual);
 
 private:
-    bool DrawDirect(gfxContext *ctx, nsIntSize bounds,
+    bool DrawDirect(gfxContext *ctx, mozilla::gfx::IntSize bounds,
                     uint32_t flags, Screen *screen, Visual *visual);
 
-    bool DrawCairo(cairo_t* cr, nsIntSize size,
+    bool DrawCairo(cairo_t* cr, mozilla::gfx::IntSize size,
                    uint32_t flags, Screen *screen, Visual *visual);
 
     void DrawFallback(mozilla::gfx::DrawTarget* dt, gfxContext* ctx,
-                      gfxASurface* aSurface, nsIntSize& size,
+                      gfxASurface* aSurface, mozilla::gfx::IntSize& size,
                       nsIntRect& drawingRect, bool canDrawOverBackground,
                       uint32_t flags, Screen* screen, Visual* visual);
 
     bool DrawOntoTempSurface(cairo_surface_t *tempXlibSurface,
                              nsIntPoint offset);
 
 };
 
--- a/image/src/Decoder.cpp
+++ b/image/src/Decoder.cpp
@@ -431,17 +431,17 @@ Decoder::EnsureFrame(uint32_t aFrameNum,
 
   // Reset our state.
   mInFrame = false;
   RawAccessFrameRef ref = Move(mCurrentFrame);
 
   MOZ_ASSERT(ref, "No ref to current frame?");
 
   // Reinitialize the old frame.
-  nsIntSize oldSize = ThebesIntSize(aPreviousFrame->GetImageSize());
+  nsIntSize oldSize = aPreviousFrame->GetImageSize();
   bool nonPremult =
     aDecodeFlags & imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA;
   if (NS_FAILED(aPreviousFrame->ReinitForDecoder(oldSize, aFrameRect, aFormat,
                                                  aPaletteDepth, nonPremult))) {
     NS_WARNING("imgFrame::ReinitForDecoder should succeed");
     mFrameCount = 0;
     aPreviousFrame->Abort();
     return RawAccessFrameRef();
@@ -465,17 +465,17 @@ Decoder::InternalAddFrame(uint32_t aFram
   }
 
   if (aTargetSize.width <= 0 || aTargetSize.height <= 0 ||
       aFrameRect.width <= 0 || aFrameRect.height <= 0) {
     NS_WARNING("Trying to add frame with zero or negative size");
     return RawAccessFrameRef();
   }
 
-  if (!SurfaceCache::CanHold(aTargetSize.ToIntSize())) {
+  if (!SurfaceCache::CanHold(aTargetSize)) {
     NS_WARNING("Trying to add frame that's too large for the SurfaceCache");
     return RawAccessFrameRef();
   }
 
   nsRefPtr<imgFrame> frame = new imgFrame();
   bool nonPremult =
     aDecodeFlags & imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA;
   if (NS_FAILED(frame->InitForDecoder(aTargetSize, aFrameRect, aFormat,
@@ -487,17 +487,17 @@ Decoder::InternalAddFrame(uint32_t aFram
   RawAccessFrameRef ref = frame->RawAccessRef();
   if (!ref) {
     frame->Abort();
     return RawAccessFrameRef();
   }
 
   InsertOutcome outcome =
     SurfaceCache::Insert(frame, ImageKey(mImage.get()),
-                         RasterSurfaceKey(aTargetSize.ToIntSize(),
+                         RasterSurfaceKey(aTargetSize,
                                           aDecodeFlags,
                                           aFrameNum),
                          Lifetime::Persistent);
   if (outcome != InsertOutcome::SUCCESS) {
     // We either hit InsertOutcome::FAILURE, which is a temporary failure due to
     // low memory (we know it's not permanent because we checked CanHold()
     // above), or InsertOutcome::FAILURE_ALREADY_PRESENT, which means that
     // another decoder beat us to decoding this frame. Either way, we should
--- a/image/src/FrameAnimator.cpp
+++ b/image/src/FrameAnimator.cpp
@@ -439,17 +439,17 @@ FrameAnimator::DoBlend(nsIntRect* aDirty
     return true;
   }
 
   bool needToBlankComposite = false;
 
   // Create the Compositing Frame
   if (!mCompositingFrame) {
     nsRefPtr<imgFrame> newFrame = new imgFrame;
-    nsresult rv = newFrame->InitForDecoder(ThebesIntSize(mSize),
+    nsresult rv = newFrame->InitForDecoder(mSize,
                                            SurfaceFormat::B8G8R8A8);
     if (NS_FAILED(rv)) {
       mCompositingFrame.reset();
       return false;
     }
     mCompositingFrame = newFrame->RawAccessRef();
     needToBlankComposite = true;
   } else if (int32_t(aNextFrameIndex) != mLastCompositedFrameIndex+1) {
@@ -579,17 +579,17 @@ FrameAnimator::DoBlend(nsIntRect* aDirty
   // too
   if ((nextFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) &&
       (prevFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS)) {
     // We are storing the whole image.
     // It would be better if we just stored the area that nextFrame is going to
     // overwrite.
     if (!mCompositingPrevFrame) {
       nsRefPtr<imgFrame> newFrame = new imgFrame;
-      nsresult rv = newFrame->InitForDecoder(ThebesIntSize(mSize),
+      nsresult rv = newFrame->InitForDecoder(mSize,
                                              SurfaceFormat::B8G8R8A8);
       if (NS_FAILED(rv)) {
         mCompositingPrevFrame.reset();
         return false;
       }
 
       mCompositingPrevFrame = newFrame->RawAccessRef();
     }
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -156,17 +156,17 @@ public:
 
     // Everything worked, so commit to these objects and mark ourselves ready.
     mDstRef = Move(tentativeDstRef);
     mState = eReady;
 
     // Insert the new surface into the cache immediately. We need to do this so
     // that we won't start multiple scaling jobs for the same size.
     SurfaceCache::Insert(mDstRef.get(), ImageKey(mImage.get()),
-                         RasterSurfaceKey(mDstSize.ToIntSize(), mImageFlags, 0),
+                         RasterSurfaceKey(mDstSize, mImageFlags, 0),
                          Lifetime::Transient);
 
     return true;
   }
 
   NS_IMETHOD Run() override
   {
     if (mState == eReady) {
@@ -205,17 +205,17 @@ public:
       mSrcRef.reset();
       mDstRef.reset();
     } else if (mState == eFinishWithError) {
       MOZ_ASSERT(NS_IsMainThread());
       NS_WARNING("HQ scaling failed");
 
       // Remove the frame from the cache since we know we don't need it.
       SurfaceCache::RemoveSurface(ImageKey(mImage.get()),
-                                  RasterSurfaceKey(mDstSize.ToIntSize(),
+                                  RasterSurfaceKey(mDstSize,
                                                    mImageFlags, 0));
 
       // Release everything we're holding, too.
       mSrcRef.reset();
       mDstRef.reset();
     } else {
       // mState must be eNew, which is invalid in Run().
       MOZ_ASSERT(false, "Need to call Init() before dispatching");
@@ -499,31 +499,30 @@ RasterImage::LookupFrameInternal(uint32_
 DrawableFrameRef
 RasterImage::LookupFrame(uint32_t aFrameNum,
                          const nsIntSize& aSize,
                          uint32_t aFlags)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   IntSize requestedSize = CanDownscaleDuringDecode(aSize, aFlags)
-                        ? aSize.ToIntSize()
-                        : mSize.ToIntSize();
+                        ? aSize : mSize;
 
   DrawableFrameRef ref = LookupFrameInternal(aFrameNum, requestedSize, aFlags);
 
   if (!ref && !mHasSize) {
     // We can't request a decode without knowing our intrinsic size. Give up.
     return DrawableFrameRef();
   }
 
   if (!ref || ref->GetImageSize() != requestedSize) {
     // The OS threw this frame away. We need to redecode if we can.
     MOZ_ASSERT(!mAnim, "Animated frames should be locked");
 
-    Decode(Some(ThebesIntSize(requestedSize)), aFlags);
+    Decode(Some(requestedSize), aFlags);
 
     // If we can sync decode, we should already have the frame.
     if (aFlags & FLAG_SYNC_DECODE) {
       ref = LookupFrameInternal(aFrameNum, requestedSize, aFlags);
     }
   }
 
   if (!ref) {
@@ -930,17 +929,17 @@ RasterImage::OnAddedFrame(uint32_t aNewF
              "Frame count running backwards");
 
   if (aNewFrameCount > mFrameCount) {
     mFrameCount = aNewFrameCount;
 
     if (aNewFrameCount == 2) {
       // We're becoming animated, so initialize animation stuff.
       MOZ_ASSERT(!mAnim, "Already have animation state?");
-      mAnim = MakeUnique<FrameAnimator>(this, mSize.ToIntSize(), mAnimationMode);
+      mAnim = MakeUnique<FrameAnimator>(this, mSize, mAnimationMode);
 
       // We don't support discarding animated images (See bug 414259).
       // Lock the image and throw away the key.
       //
       // Note that this is inefficient, since we could get rid of the source data
       // too. However, doing this is actually hard, because we're probably
       // mid-decode, and thus we're decoding out of the source buffer. Since we're
       // going to fix this anyway later, and since we didn't kill the source data
@@ -1607,17 +1606,17 @@ RasterImage::CanScale(GraphicsFilter aFi
   if (aSize.width > mSize.width || aSize.height > mSize.height) {
     uint32_t scaledSize = static_cast<uint32_t>(aSize.width * aSize.height);
     if (scaledSize > gfxPrefs::ImageHQUpscalingMaxSize()) {
       return false;
     }
   }
 
   // There's no point in scaling if we can't store the result.
-  if (!SurfaceCache::CanHold(aSize.ToIntSize())) {
+  if (!SurfaceCache::CanHold(aSize)) {
     return false;
   }
 
   // XXX(seth): It's not clear what this check buys us over
   // gfxPrefs::ImageHQUpscalingMaxSize().
   // The default value of this pref is 1000, which means that we never upscale.
   // If that's all it's getting us, I'd rather we just forbid that explicitly.
   gfx::Size scale(double(aSize.width) / mSize.width,
@@ -1649,17 +1648,17 @@ RasterImage::CanDownscaleDuringDecode(co
   }
 
   // Zero or negative width or height is unacceptable.
   if (aSize.width < 1 || aSize.height < 1) {
     return false;
   }
 
   // There's no point in scaling if we can't store the result.
-  if (!SurfaceCache::CanHold(aSize.ToIntSize())) {
+  if (!SurfaceCache::CanHold(aSize)) {
     return false;
   }
 
   return true;
 }
 
 void
 RasterImage::NotifyNewScaledFrame()
@@ -1710,17 +1709,17 @@ RasterImage::DrawWithPreDownscaleIfNeede
                                           GraphicsFilter aFilter,
                                           uint32_t aFlags)
 {
   DrawableFrameRef frameRef;
 
   if (CanScale(aFilter, aSize, aFlags)) {
     frameRef =
       SurfaceCache::Lookup(ImageKey(this),
-                           RasterSurfaceKey(aSize.ToIntSize(),
+                           RasterSurfaceKey(aSize,
                                             DecodeFlags(aFlags),
                                             0));
     if (!frameRef) {
       // We either didn't have a matching scaled frame or the OS threw it away.
       // Request a new one so we'll be ready next time. For now, we'll fall back
       // to aFrameRef below.
       RequestScale(aFrameRef.get(), aFlags, aSize);
     }
@@ -1738,17 +1737,17 @@ RasterImage::DrawWithPreDownscaleIfNeede
     frameRef = Move(aFrameRef);
     frameIsComplete = frameRef->IsImageComplete();
   }
 
   // By now we may have a frame with the requested size. If not, we need to
   // adjust the drawing parameters accordingly.
   IntSize finalSize = frameRef->GetImageSize();
   bool couldRedecodeForBetterFrame = false;
-  if (ThebesIntSize(finalSize) != aSize) {
+  if (finalSize != aSize) {
     gfx::Size scale(double(aSize.width) / finalSize.width,
                     double(aSize.height) / finalSize.height);
     aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height));
     region.Scale(1.0 / scale.width, 1.0 / scale.height);
 
     couldRedecodeForBetterFrame = mDownscaleDuringDecode &&
                                   CanDownscaleDuringDecode(aSize, aFlags);
   }
@@ -2091,17 +2090,17 @@ RasterImage::OptimalImageSizeForDest(con
   nsIntSize destSize(ceil(aDest.width), ceil(aDest.height));
 
   if (aFilter == GraphicsFilter::FILTER_GOOD &&
       CanDownscaleDuringDecode(destSize, aFlags)) {
     return destSize;
   } else if (CanScale(aFilter, destSize, aFlags)) {
     DrawableFrameRef frameRef =
       SurfaceCache::Lookup(ImageKey(this),
-                           RasterSurfaceKey(destSize.ToIntSize(),
+                           RasterSurfaceKey(destSize,
                                             DecodeFlags(aFlags),
                                             0));
 
     if (frameRef && frameRef->IsImageComplete()) {
         return destSize;  // We have an existing HQ scale for this size.
     }
     if (!frameRef) {
       // We could HQ scale to this size, but we haven't. Request a scale now.
--- a/image/src/SVGDocumentWrapper.h
+++ b/image/src/SVGDocumentWrapper.h
@@ -10,23 +10,23 @@
 
 #include "mozilla/Attributes.h"
 
 #include "nsCOMPtr.h"
 #include "nsIStreamListener.h"
 #include "nsIObserver.h"
 #include "nsIContentViewer.h"
 #include "nsWeakReference.h"
+#include "nsSize.h"
 
 class nsIAtom;
 class nsIPresShell;
 class nsIRequest;
 class nsILoadGroup;
 class nsIFrame;
-struct nsIntSize;
 
 #define OBSERVER_SVC_CID "@mozilla.org/observer-service;1"
 
 // undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
 #undef GetCurrentTime
 
 namespace mozilla {
 namespace dom {
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -802,17 +802,17 @@ VectorImage::Draw(gfxContext* aContext,
                                           params.svgContext,
                                           params.animationTime));
 
   // Draw.
   if (frameRef) {
     RefPtr<SourceSurface> surface = frameRef->GetSurface();
     if (surface) {
       nsRefPtr<gfxDrawable> svgDrawable =
-        new gfxSurfaceDrawable(surface, ThebesIntSize(frameRef->GetSize()));
+        new gfxSurfaceDrawable(surface, frameRef->GetSize());
       Show(svgDrawable, params);
       return DrawResult::SUCCESS;
     }
 
     // We lost our surface due to some catastrophic event.
     RecoverFromLossOfSurfaces();
   }
 
@@ -829,17 +829,17 @@ VectorImage::CreateSurfaceAndShow(const 
 
   nsRefPtr<gfxDrawingCallback> cb =
     new SVGDrawingCallback(mSVGDocumentWrapper,
                            nsIntRect(nsIntPoint(0, 0), aParams.viewportSize),
                            aParams.size,
                            aParams.flags);
 
   nsRefPtr<gfxDrawable> svgDrawable =
-    new gfxCallbackDrawable(cb, ThebesIntSize(aParams.size));
+    new gfxCallbackDrawable(cb, aParams.size);
 
   bool bypassCache = bool(aParams.flags & FLAG_BYPASS_SURFACE_CACHE) ||
                      // Refuse to cache animated images:
                      // XXX(seth): We may remove this restriction in bug 922893.
                      mHaveAnimations ||
                      // The image is too big to fit in the cache:
                      !SurfaceCache::CanHold(aParams.size);
   if (bypassCache)
@@ -852,17 +852,17 @@ VectorImage::CreateSurfaceAndShow(const 
   // will become locked again when Draw touches them, and the remainder will
   // eventually expire.
   SurfaceCache::UnlockSurfaces(ImageKey(this));
 
   // Try to create an imgFrame, initializing the surface it contains by drawing
   // our gfxDrawable into it. (We use FILTER_NEAREST since we never scale here.)
   nsRefPtr<imgFrame> frame = new imgFrame;
   nsresult rv =
-    frame->InitWithDrawable(svgDrawable, ThebesIntSize(aParams.size),
+    frame->InitWithDrawable(svgDrawable, aParams.size,
                             SurfaceFormat::B8G8R8A8,
                             GraphicsFilter::FILTER_NEAREST, aParams.flags);
 
   // If we couldn't create the frame, it was probably because it would end
   // up way too big. Generally it also wouldn't fit in the cache, but the prefs
   // could be set such that the cache isn't the limiting factor.
   if (NS_FAILED(rv))
     return Show(svgDrawable, aParams);
@@ -877,32 +877,32 @@ VectorImage::CreateSurfaceAndShow(const 
   SurfaceCache::Insert(frame, ImageKey(this),
                        VectorSurfaceKey(aParams.size,
                                         aParams.svgContext,
                                         aParams.animationTime),
                        Lifetime::Persistent);
 
   // Draw.
   nsRefPtr<gfxDrawable> drawable =
-    new gfxSurfaceDrawable(surface, ThebesIntSize(aParams.size));
+    new gfxSurfaceDrawable(surface, aParams.size);
   Show(drawable, aParams);
 
   // Send out an invalidation so that surfaces that are still in use get
   // re-locked. See the discussion of the UnlockSurfaces call above.
   mProgressTracker->SyncNotifyProgress(FLAG_FRAME_COMPLETE,
                                        nsIntRect::GetMaxSizedIntRect());
 }
 
 
 void
 VectorImage::Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams)
 {
   MOZ_ASSERT(aDrawable, "Should have a gfxDrawable by now");
   gfxUtils::DrawPixelSnapped(aParams.context, aDrawable,
-                             ThebesIntSize(aParams.size),
+                             aParams.size,
                              aParams.region,
                              SurfaceFormat::B8G8R8A8,
                              aParams.filter, aParams.flags, aParams.opacity);
 
   MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now");
   mRenderingObserver->ResumeHonoringInvalidations();
 }
 
--- a/image/src/imgFrame.cpp
+++ b/image/src/imgFrame.cpp
@@ -249,17 +249,17 @@ imgFrame::InitForDecoder(const nsIntSize
   // Assert for properties that should be verified by decoders,
   // warn for properties related to bad content.
   if (!AllowedImageAndFrameDimensions(aImageSize, aRect)) {
     NS_WARNING("Should have legal image size");
     mAborted = true;
     return NS_ERROR_FAILURE;
   }
 
-  mImageSize = aImageSize.ToIntSize();
+  mImageSize = aImageSize;
   mOffset.MoveTo(aRect.x, aRect.y);
   mSize.SizeTo(aRect.width, aRect.height);
 
   mFormat = aFormat;
   mPaletteDepth = aPaletteDepth;
   mNonPremult = aNonPremult;
 
   if (aPaletteDepth != 0) {
@@ -314,17 +314,17 @@ imgFrame::InitWithDrawable(gfxDrawable* 
   // Assert for properties that should be verified by decoders,
   // warn for properties related to bad content.
   if (!AllowedImageSize(aSize.width, aSize.height)) {
     NS_WARNING("Should have legal image size");
     mAborted = true;
     return NS_ERROR_FAILURE;
   }
 
-  mImageSize = aSize.ToIntSize();
+  mImageSize = aSize;
   mOffset.MoveTo(0, 0);
   mSize.SizeTo(aSize.width, aSize.height);
 
   mFormat = aFormat;
   mPaletteDepth = 0;
 
   RefPtr<DrawTarget> target;
 
@@ -369,17 +369,17 @@ imgFrame::InitWithDrawable(gfxDrawable* 
   if (!target) {
     mAborted = true;
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // Draw using the drawable the caller provided.
   nsIntRect imageRect(0, 0, mSize.width, mSize.height);
   nsRefPtr<gfxContext> ctx = new gfxContext(target);
-  gfxUtils::DrawPixelSnapped(ctx, aDrawable, ThebesIntSize(mSize),
+  gfxUtils::DrawPixelSnapped(ctx, aDrawable, mSize,
                              ImageRegion::Create(imageRect),
                              mFormat, aFilter, aImageFlags);
 
   if (canUseDataSurface && !mImageSurface) {
     NS_WARNING("Failed to create VolatileDataSourceSurface");
     mAborted = true;
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -552,17 +552,17 @@ imgFrame::SurfaceForDrawing(bool        
                             SourceSurface*     aSurface)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mMonitor.AssertCurrentThreadOwns();
 
   IntSize size(int32_t(aImageRect.Width()), int32_t(aImageRect.Height()));
   if (!aDoPadding && !aDoPartialDecode) {
     NS_ASSERTION(!mSinglePixel, "This should already have been handled");
-    return SurfaceWithFormat(new gfxSurfaceDrawable(aSurface, ThebesIntSize(size)), mFormat);
+    return SurfaceWithFormat(new gfxSurfaceDrawable(aSurface, size), mFormat);
   }
 
   gfxRect available = gfxRect(mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height);
 
   if (aDoTile || mSinglePixel) {
     // Create a temporary surface.
     // Give this surface an alpha channel because there are
     // transparent pixels in the padding or undecoded area
@@ -580,17 +580,17 @@ imgFrame::SurfaceForDrawing(bool        
     } else {
       SurfacePattern pattern(aSurface,
                              ExtendMode::REPEAT,
                              Matrix::Translation(mDecoded.x, mDecoded.y));
       target->FillRect(ToRect(aRegion.Intersect(available).Rect()), pattern);
     }
 
     RefPtr<SourceSurface> newsurf = target->Snapshot();
-    return SurfaceWithFormat(new gfxSurfaceDrawable(newsurf, ThebesIntSize(size)), target->GetFormat());
+    return SurfaceWithFormat(new gfxSurfaceDrawable(newsurf, size), target->GetFormat());
   }
 
   // Not tiling, and we have a surface, so we can account for
   // padding and/or a partial decode just by twiddling parameters.
   gfxPoint paddingTopLeft(aPadding.left, aPadding.top);
   aRegion = aRegion.Intersect(available) - paddingTopLeft;
   aContext->Multiply(gfxMatrix::Translation(paddingTopLeft));
   aImageRect = gfxRect(0, 0, mSize.width, mSize.height);
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -483,17 +483,17 @@ SimdTypeDescr::lanes(Type t)
  */
 static TypedProto*
 CreatePrototypeObjectForComplexTypeInstance(JSContext* cx, HandleObject ctorPrototype)
 {
     RootedObject ctorPrototypePrototype(cx, GetPrototype(cx, ctorPrototype));
     if (!ctorPrototypePrototype)
         return nullptr;
 
-    return NewObjectWithProto<TypedProto>(cx, ctorPrototypePrototype, TenuredObject);
+    return NewObjectWithProto<TypedProto>(cx, ctorPrototypePrototype, SingletonObject);
 }
 
 const Class ArrayTypeDescr::class_ = {
     "ArrayType",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS) | JSCLASS_BACKGROUND_FINALIZE,
     nullptr, /* addProperty */
     nullptr, /* delProperty */
     nullptr, /* getProperty */
@@ -1665,75 +1665,60 @@ OutlineTypedObject::obj_trace(JSTracer* 
 
     if (!descr.opaque() || !typedObj.maybeForwardedIsAttached())
         return;
 
     descr.traceInstances(trc, newData, 1);
 }
 
 bool
-TypedObject::obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
-                                MutableHandleObject objp, MutableHandleShape propp)
+TypeDescr::hasProperty(const JSAtomState& names, jsid id)
 {
-    MOZ_ASSERT(obj->is<TypedObject>());
-
-    Rooted<TypeDescr*> descr(cx, &obj->as<TypedObject>().typeDescr());
-    switch (descr->kind()) {
+    switch (kind()) {
       case type::Scalar:
       case type::Reference:
       case type::Simd:
-        break;
+        return false;
 
       case type::Array:
       {
         uint32_t index;
-        if (IdIsIndex(id, &index))
-            return obj_lookupElement(cx, obj, index, objp, propp);
-
-        if (JSID_IS_ATOM(id, cx->names().length)) {
-            MarkNonNativePropertyFound<CanGC>(propp);
-            objp.set(obj);
-            return true;
-        }
-        break;
+        return IdIsIndex(id, &index) || JSID_IS_ATOM(id, names.length);
       }
 
       case type::Struct:
       {
-        StructTypeDescr& structDescr = descr->as<StructTypeDescr>();
         size_t index;
-        if (structDescr.fieldIndex(id, &index)) {
-            MarkNonNativePropertyFound<CanGC>(propp);
-            objp.set(obj);
-            return true;
-        }
-        break;
+        return as<StructTypeDescr>().fieldIndex(id, &index);
       }
     }
 
+    MOZ_CRASH("Unexpected kind");
+}
+
+/* static */ bool
+TypedObject::obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
+                                MutableHandleObject objp, MutableHandleShape propp)
+{
+    if (obj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id)) {
+        MarkNonNativePropertyFound<CanGC>(propp);
+        objp.set(obj);
+        return true;
+    }
+
     RootedObject proto(cx, obj->getProto());
     if (!proto) {
         objp.set(nullptr);
         propp.set(nullptr);
         return true;
     }
 
     return LookupProperty(cx, proto, id, objp, propp);
 }
 
-bool
-TypedObject::obj_lookupElement(JSContext* cx, HandleObject obj, uint32_t index,
-                               MutableHandleObject objp, MutableHandleShape propp)
-{
-    MOZ_ASSERT(obj->is<TypedObject>());
-    MarkNonNativePropertyFound<CanGC>(propp);
-    objp.set(obj);
-    return true;
-}
-
 static bool
 ReportPropertyError(JSContext* cx,
                     const unsigned errorNumber,
                     HandleId id)
 {
     RootedValue idVal(cx, IdToValue(id));
     RootedString str(cx, ValueToSource(cx, idVal));
     if (!str)
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -169,16 +169,19 @@ class TypeDescr : public NativeObject
     int32_t alignment() const {
         return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
     }
 
     int32_t size() const {
         return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
     }
 
+    // Whether id is an 'own' property of objects with this descriptor.
+    bool hasProperty(const JSAtomState& names, jsid id);
+
     // Type descriptors may contain a list of their references for use during
     // scanning. Marking code is optimized to use this list to mark inline
     // typed objects, rather than the slower trace hook. This list is only
     // specified when (a) the descriptor is short enough that it can fit in an
     // InlineTypedObject, and (b) the descriptor contains at least one
     // reference. Otherwise its value is undefined.
     //
     // The list is three consecutive arrays of int32_t offsets, with each array
@@ -520,19 +523,16 @@ class TypedObject : public JSObject
 
   protected:
     HeapPtrShape shape_;
 
     static bool obj_lookupProperty(JSContext* cx, HandleObject obj,
                                    HandleId id, MutableHandleObject objp,
                                    MutableHandleShape propp);
 
-    static bool obj_lookupElement(JSContext* cx, HandleObject obj, uint32_t index,
-                                  MutableHandleObject objp, MutableHandleShape propp);
-
     static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
                                    Handle<JSPropertyDescriptor> desc,
                                    ObjectOpResult& result);
 
     static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
 
     static bool obj_getProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
                                 HandleId id, MutableHandleValue vp);
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -3289,18 +3289,16 @@ EffectlesslyLookupProperty(JSContext* cx
             return true;
         }
 
         *domProxyHasGeneration = (*shadowsResult == DoesntShadowUnique);
 
         checkObj = GetDOMProxyProto(obj);
         if (!checkObj)
             return true;
-    } else if (!obj->isNative() && !obj->is<UnboxedPlainObject>()) {
-        return true;
     }
 
     if (LookupPropertyPure(cx, checkObj, NameToId(name), holder.address(), shape.address()))
         return true;
 
     holder.set(nullptr);
     shape.set(nullptr);
     return true;
@@ -3317,23 +3315,27 @@ CheckHasNoSuchProperty(JSContext* cx, Ha
     while (curObj) {
         if (curObj->isNative()) {
             // Don't handle proto chains with resolve hooks.
             if (curObj->getClass()->resolve)
                 return false;
 
             if (curObj->as<NativeObject>().contains(cx, NameToId(name)))
                 return false;
-        } else {
-            // Handle unboxed plain objects as the original receiver.
-            if (!curObj->is<UnboxedPlainObject>() || curObj != obj)
+        } else if (curObj != obj) {
+            // Non-native objects are only handled as the original receiver.
+            return false;
+        } else if (curObj->is<UnboxedPlainObject>()) {
+            if (curObj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, NameToId(name)))
                 return false;
-
-            if (curObj->as<UnboxedPlainObject>().layout().lookup(name))
+        } else if (curObj->is<TypedObject>()) {
+            if (curObj->as<TypedObject>().typeDescr().hasProperty(cx->names(), NameToId(name)))
                 return false;
+        } else {
+            return false;
         }
 
         JSObject* proto = curObj->getTaggedProto().toObjectOrNull();
         if (!proto)
             break;
 
         curObj = proto;
         depth++;
@@ -3345,17 +3347,17 @@ CheckHasNoSuchProperty(JSContext* cx, Ha
 }
 
 static bool
 IsCacheableProtoChain(JSObject* obj, JSObject* holder, bool isDOMProxy=false)
 {
     MOZ_ASSERT_IF(isDOMProxy, IsCacheableDOMProxy(obj));
 
     if (!isDOMProxy && !obj->isNative()) {
-        if (!obj->is<UnboxedPlainObject>() || obj == holder)
+        if (obj == holder || !obj->is<UnboxedPlainObject>() || !obj->is<TypedObject>())
             return false;
     }
 
     // Don't handle objects which require a prototype guard. This should
     // be uncommon so handling it is likely not worth the complexity.
     if (obj->hasUncacheableProto())
         return false;
 
@@ -6593,17 +6595,17 @@ TryAttachNativeGetPropStub(JSContext* cx
         if (!newStub)
             return false;
         stub->addNewStub(newStub);
         *attached = true;
         return true;
     }
 
     const Class* outerClass = nullptr;
-    if (!isDOMProxy && !obj->isNative() && !obj->is<UnboxedPlainObject>()) {
+    if (!isDOMProxy && !obj->isNative()) {
         outerClass = obj->getClass();
         DebugOnly<JSObject*> outer = obj.get();
         obj = GetInnerObject(obj);
         MOZ_ASSERT(script->global().isNative());
         if (obj != &script->global())
             return true;
         // ICGetProp_CallNative*::Compiler::generateStubCode depends on this.
         MOZ_ASSERT(&((GetProxyDataLayout(outer)->values->privateSlot).toObject()) == obj);
@@ -7208,19 +7210,19 @@ ICGetPropNativeCompiler::getStub(ICStubS
       }
 
       default:
         MOZ_CRASH("Bad stub kind");
     }
 }
 
 static void
-GuardNativeOrUnboxedReceiver(MacroAssembler& masm, ReceiverGuard::StackGuard guard,
-                             Register object, Register scratch,
-                             size_t receiverGuardOffset, Label* failure)
+GuardReceiverObject(MacroAssembler& masm, ReceiverGuard::StackGuard guard,
+                    Register object, Register scratch,
+                    size_t receiverGuardOffset, Label* failure)
 {
     Address groupAddress(BaselineStubReg, receiverGuardOffset + ReceiverGuard::offsetOfGroup());
     Address shapeAddress(BaselineStubReg, receiverGuardOffset + ReceiverGuard::offsetOfShape());
     Address expandoAddress(object, UnboxedPlainObject::offsetOfExpando());
 
     if (guard.group) {
         masm.loadPtr(groupAddress, scratch);
         masm.branchTestObjGroup(Assembler::NotEqual, object, scratch, failure);
@@ -7265,18 +7267,18 @@ ICGetPropNativeCompiler::generateStubCod
         masm.branchTestObject(Assembler::NotEqual, R0, &failure);
         objReg = masm.extractObject(R0, ExtractTemp0);
     }
     regs.takeUnchecked(objReg);
 
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Shape/group guard.
-    GuardNativeOrUnboxedReceiver(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
-                                 ICGetPropNativeStub::offsetOfReceiverGuard(), &failure);
+    GuardReceiverObject(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
+                        ICGetPropNativeStub::offsetOfReceiverGuard(), &failure);
 
     Register holderReg;
     if (obj_ == holder_) {
         if (obj_->is<UnboxedPlainObject>()) {
             // We are loading off the expando object, so use that for the holder.
             holderReg = regs.takeAny();
             masm.loadPtr(Address(objReg, UnboxedPlainObject::offsetOfExpando()), holderReg);
         } else {
@@ -7413,18 +7415,18 @@ ICGetPropNativeDoesNotExistCompiler::gen
     }
 #endif // DEBUG
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
     // Unbox and guard against old shape/group.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
-    GuardNativeOrUnboxedReceiver(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
-                                 ICGetProp_NativeDoesNotExist::offsetOfGuard(), &failure);
+    GuardReceiverObject(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
+                        ICGetProp_NativeDoesNotExist::offsetOfGuard(), &failure);
 
     Register protoReg = regs.takeAny();
     // Check the proto chain.
     for (size_t i = 0; i < protoChainDepth_; i++) {
         masm.loadObjProto(i == 0 ? objReg : protoReg, protoReg);
         masm.branchTestPtr(Assembler::Zero, protoReg, protoReg, &failure);
         size_t shapeOffset = ICGetProp_NativeDoesNotExistImpl<0>::offsetOfShape(i);
         masm.loadPtr(Address(BaselineStubReg, shapeOffset), scratch);
@@ -7452,18 +7454,18 @@ ICGetProp_CallScripted::Compiler::genera
     AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Guard input is an object.
     masm.branchTestObject(Assembler::NotEqual, R0, &failure);
 
     // Unbox and shape guard.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
-    GuardNativeOrUnboxedReceiver(masm, ReceiverGuard::StackGuard(receiver_), objReg, scratch,
-                                 ICGetProp_CallScripted::offsetOfReceiverGuard(), &failure);
+    GuardReceiverObject(masm, ReceiverGuard::StackGuard(receiver_), objReg, scratch,
+                        ICGetProp_CallScripted::offsetOfReceiverGuard(), &failure);
 
     if (receiver_ != holder_) {
         Register holderReg = regs.takeAny();
         masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallScripted::offsetOfHolder()), holderReg);
         masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallScripted::offsetOfHolderShape()), scratch);
         masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failure);
         regs.add(holderReg);
     }
@@ -7560,18 +7562,18 @@ ICGetProp_CallNative::Compiler::generate
             regs.add(tmp);
         }
     }
     regs.takeUnchecked(objReg);
 
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Shape guard.
-    GuardNativeOrUnboxedReceiver(masm, ReceiverGuard::StackGuard(receiver_), objReg, scratch,
-                                 ICGetProp_CallNative::offsetOfReceiverGuard(), &failure);
+    GuardReceiverObject(masm, ReceiverGuard::StackGuard(receiver_), objReg, scratch,
+                        ICGetProp_CallNative::offsetOfReceiverGuard(), &failure);
 
     if (receiver_ != holder_ ) {
         Register holderReg = regs.takeAny();
         masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallNative::offsetOfHolder()), holderReg);
         masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallNative::offsetOfHolderShape()), scratch);
         masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failure);
         regs.add(holderReg);
     }
@@ -8889,18 +8891,18 @@ ICSetProp_CallScripted::Compiler::genera
     // Stow R0 and R1 to free up registers.
     EmitStowICValues(masm, 2);
 
     AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Unbox and shape guard.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
-    GuardNativeOrUnboxedReceiver(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
-                                 ICSetProp_CallScripted::offsetOfGuard(), &failureUnstow);
+    GuardReceiverObject(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
+                        ICSetProp_CallScripted::offsetOfGuard(), &failureUnstow);
 
     Register holderReg = regs.takeAny();
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallScripted::offsetOfHolder()), holderReg);
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallScripted::offsetOfHolderShape()), scratch);
     masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failureUnstow);
     regs.add(holderReg);
 
     // Push a stub frame so that we can perform a non-tail call.
@@ -9008,18 +9010,18 @@ ICSetProp_CallNative::Compiler::generate
     // Stow R0 and R1 to free up registers.
     EmitStowICValues(masm, 2);
 
     AllocatableGeneralRegisterSet regs(availableGeneralRegs(1));
     Register scratch = regs.takeAnyExcluding(BaselineTailCallReg);
 
     // Unbox and shape guard.
     Register objReg = masm.extractObject(R0, ExtractTemp0);
-    GuardNativeOrUnboxedReceiver(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
-                                 ICSetProp_CallNative::offsetOfGuard(), &failureUnstow);
+    GuardReceiverObject(masm, ReceiverGuard::StackGuard(obj_), objReg, scratch,
+                        ICSetProp_CallNative::offsetOfGuard(), &failureUnstow);
 
     Register holderReg = regs.takeAny();
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfHolder()), holderReg);
     masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfHolderShape()), scratch);
     masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failureUnstow);
     regs.add(holderReg);
 
     // Push a stub frame so that we can perform a non-tail call.
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -3837,27 +3837,27 @@ class ICGetProp_StringLength : public IC
 
         ICStub* getStub(ICStubSpace* space) {
             return ICStub::New<ICGetProp_StringLength>(space, getStubCode());
         }
     };
 };
 
 // Structure encapsulating the guarding that needs to be done on an object
-// before it can be accessed or modified.
+// before it can be accessed or modified by an inline cache.
 class ReceiverGuard
 {
-    // Group to guard on, or null. If the object is not unboxed and the IC does
-    // not require the object to have a specific group, this is null.
-    // Otherwise, this is the object's group.
+    // Group to guard on, or null. If the object is not unboxed or typed and
+    // the IC does  not require the object to have a specific group, this is
+    // null. Otherwise, this is the object's group.
     HeapPtrObjectGroup group_;
 
-    // Shape to guard on, or null. If the object is not unboxed then this is
-    // the object's shape. If the object is unboxed, then this is the shape of
-    // the object's expando, null if the object has no expando.
+    // Shape to guard on, or null. If the object is not unboxed or typed then
+    // this is the object's shape. If the object is unboxed, then this is the
+    // shape of the object's expando, null if the object has no expando.
     HeapPtrShape shape_;
 
   public:
     struct StackGuard;
 
     struct RootedStackGuard
     {
         RootedObjectGroup group;
@@ -3880,21 +3880,24 @@ class ReceiverGuard
         MOZ_IMPLICIT StackGuard(const RootedStackGuard& guard)
           : group(guard.group), shape(guard.shape)
         {}
 
         explicit StackGuard(JSObject* obj)
           : group(nullptr), shape(nullptr)
         {
             if (obj) {
-                shape = obj->maybeShape();
-                if (!shape) {
+                if (obj->is<UnboxedPlainObject>()) {
                     group = obj->group();
                     if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
                         shape = expando->lastProperty();
+                } else if (obj->is<TypedObject>()) {
+                    group = obj->group();
+                } else {
+                    shape = obj->maybeShape();
                 }
             }
         }
 
         explicit StackGuard(Shape* shape)
           : group(nullptr), shape(shape)
         {}
 
@@ -3937,19 +3940,27 @@ class ReceiverGuard
     }
     static size_t offsetOfGroup() {
         return offsetof(ReceiverGuard, group_);
     }
 
     // Bits to munge into IC compiler keys when that IC has a ReceiverGuard.
     // This uses at two bits for data.
     static int32_t keyBits(JSObject* obj) {
-        if (obj->maybeShape())
-            return 0;
-        return obj->as<UnboxedPlainObject>().maybeExpando() ? 1 : 2;
+        if (obj->is<UnboxedPlainObject>()) {
+            // Both the group and shape need to be guarded for unboxed objects.
+            return obj->as<UnboxedPlainObject>().maybeExpando() ? 0 : 1;
+        }
+        if (obj->is<TypedObject>()) {
+            // Only the group needs to be guarded for typed objects.
+            return 2;
+        }
+        // Other objects only need the shape to be guarded, except for ICs
+        // which always guard the group.
+        return 3;
     }
 };
 
 // Base class for native GetProp stubs.
 class ICGetPropNativeStub : public ICMonitoredStub
 {
     // Object shape/group.
     ReceiverGuard receiverGuard_;
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -7049,32 +7049,41 @@ IonBuilder::maybeInsertResume()
         return true;
 
     MNop* ins = MNop::New(alloc());
     current->add(ins);
 
     return resumeAfter(ins);
 }
 
+// Return whether property lookups can be performed effectlessly on clasp.
 static bool
-ClassHasEffectlessLookup(const Class* clasp, PropertyName* name)
+ClassHasEffectlessLookup(const Class* clasp)
 {
     return (clasp == &UnboxedPlainObject::class_) ||
+           IsTypedObjectClass(clasp) ||
            (clasp->isNative() && !clasp->ops.lookupProperty);
 }
 
+// Return whether an object might have a property for name which is not
+// accounted for by type information.
 static bool
-ClassHasResolveHook(CompileCompartment* comp, const Class* clasp, PropertyName* name)
-{
-    // While arrays do not have resolve hooks, the types of their |length|
-    // properties are not reflected in type information, so pretend there is a
-    // resolve hook for this property.
+ObjectHasExtraOwnProperty(CompileCompartment* comp, TypeSet::ObjectKey* object, PropertyName* name)
+{
+    // Some typed object properties are not reflected in type information.
+    if (object->isGroup() && object->group()->maybeTypeDescr())
+        return object->group()->typeDescr().hasProperty(comp->runtime()->names(), NameToId(name));
+
+    const Class* clasp = object->clasp();
+
+    // Array |length| properties are not reflected in type information.
     if (clasp == &ArrayObject::class_)
         return name == comp->runtime()->names().length;
 
+    // Resolve hooks can install new properties on objects on demand.
     if (!clasp->resolve)
         return false;
 
     if (clasp->resolve == str_resolve) {
         // str_resolve only resolves integers, not names.
         return false;
     }
 
@@ -7121,34 +7130,34 @@ IonBuilder::testSingletonProperty(JSObje
     // If the access definitely goes through obj, either directly or on the
     // prototype chain, and the object has singleton type, then the type
     // information for that property reflects the value that will definitely be
     // read on accesses to the object. If the property is later deleted or
     // reconfigured as a getter/setter then the type information for the
     // property will change and trigger invalidation.
 
     while (obj) {
-        if (!ClassHasEffectlessLookup(obj->getClass(), name))
+        if (!ClassHasEffectlessLookup(obj->getClass()))
             return nullptr;
 
         TypeSet::ObjectKey* objKey = TypeSet::ObjectKey::get(obj);
         if (analysisContext)
             objKey->ensureTrackedProperty(analysisContext, NameToId(name));
 
         if (objKey->unknownProperties())
             return nullptr;
 
         HeapTypeSetKey property = objKey->property(NameToId(name));
         if (property.isOwnProperty(constraints())) {
             if (obj->isSingleton())
                 return property.singleton(constraints());
             return nullptr;
         }
 
-        if (ClassHasResolveHook(compartment, obj->getClass(), name))
+        if (ObjectHasExtraOwnProperty(compartment, objKey, name))
             return nullptr;
 
         obj = obj->getProto();
     }
 
     return nullptr;
 }
 
@@ -7210,17 +7219,17 @@ IonBuilder::testSingletonPropertyTypes(M
         for (unsigned i = 0; i < types->getObjectCount(); i++) {
             TypeSet::ObjectKey* key = types->getObject(i);
             if (!key)
                 continue;
             if (analysisContext)
                 key->ensureTrackedProperty(analysisContext, NameToId(name));
 
             const Class* clasp = key->clasp();
-            if (!ClassHasEffectlessLookup(clasp, name) || ClassHasResolveHook(compartment, clasp, name))
+            if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, name))
                 return false;
             if (key->unknownProperties())
                 return false;
             HeapTypeSetKey property = key->property(NameToId(name));
             if (property.isOwnProperty(constraints()))
                 return false;
 
             if (JSObject* proto = key->proto().toObjectOrNull()) {
@@ -9631,29 +9640,28 @@ IonBuilder::objectsHaveCommonPrototype(T
         if (!key)
             continue;
 
         while (key) {
             if (key->unknownProperties())
                 return false;
 
             const Class* clasp = key->clasp();
-            if (!ClassHasEffectlessLookup(clasp, name))
+            if (!ClassHasEffectlessLookup(clasp))
                 return false;
             JSObject* singleton = key->isSingleton() ? key->singleton() : nullptr;
-            if (ClassHasResolveHook(compartment, clasp, name)) {
+            if (ObjectHasExtraOwnProperty(compartment, key, name)) {
                 if (!singleton || !singleton->is<GlobalObject>())
                     return false;
                 *guardGlobal = true;
             }
 
             // Look for a getter/setter on the class itself which may need
-            // to be called. Ignore the getProperty op for typed arrays, it
-            // only handles integers and forwards names to the prototype.
-            if (isGetter && clasp->ops.getProperty && !IsAnyTypedArrayClass(clasp))
+            // to be called.
+            if (isGetter && clasp->ops.getProperty)
                 return false;
             if (!isGetter && clasp->ops.setProperty)
                 return false;
 
             // Test for isOwnProperty() without freezing. If we end up
             // optimizing, freezePropertiesForCommonPropFunc will freeze the
             // property type sets later on.
             HeapTypeSetKey property = key->property(NameToId(name));
@@ -9801,17 +9809,17 @@ IonBuilder::annotateGetPropertyCache(MDe
         ObjectGroup* group = objTypes->getGroup(i);
         if (!group)
             continue;
         TypeSet::ObjectKey* key = TypeSet::ObjectKey::get(group);
         if (key->unknownProperties() || !key->proto().isObject())
             continue;
 
         const Class* clasp = key->clasp();
-        if (!ClassHasEffectlessLookup(clasp, name) || ClassHasResolveHook(compartment, clasp, name))
+        if (!ClassHasEffectlessLookup(clasp) || ObjectHasExtraOwnProperty(compartment, key, name))
             continue;
 
         HeapTypeSetKey ownTypes = key->property(NameToId(name));
         if (ownTypes.isOwnProperty(constraints()))
             continue;
 
         JSObject* singleton = testSingletonProperty(key->proto().toObject(), name);
         if (!singleton || !singleton->is<JSFunction>())
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -699,25 +699,17 @@ IsCacheableGetPropCallPropertyOp(JSObjec
     return true;
 }
 
 static void
 TestMatchingReceiver(MacroAssembler& masm, IonCache::StubAttacher& attacher,
                      Register object, JSObject* obj, Label* failure,
                      bool alwaysCheckGroup = false)
 {
-    if (Shape* shape = obj->maybeShape()) {
-        attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
-                                       Address(object, JSObject::offsetOfShape()),
-                                       ImmGCPtr(shape), failure);
-
-        if (alwaysCheckGroup)
-            masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
-    } else {
-        MOZ_ASSERT(obj->is<UnboxedPlainObject>());
+    if (obj->is<UnboxedPlainObject>()) {
         MOZ_ASSERT(failure);
 
         masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
         Address expandoAddress(object, UnboxedPlainObject::offsetOfExpando());
         if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
             masm.branchPtr(Assembler::Equal, expandoAddress, ImmWord(0), failure);
             Label success;
             masm.push(object);
@@ -726,16 +718,30 @@ TestMatchingReceiver(MacroAssembler& mas
                                     &success);
             masm.pop(object);
             masm.jump(failure);
             masm.bind(&success);
             masm.pop(object);
         } else {
             masm.branchPtr(Assembler::NotEqual, expandoAddress, ImmWord(0), failure);
         }
+    } else if (obj->is<TypedObject>()) {
+        attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
+                                       Address(object, JSObject::offsetOfGroup()),
+                                       ImmGCPtr(obj->group()), failure);
+    } else {
+        Shape* shape = obj->maybeShape();
+        MOZ_ASSERT(shape);
+
+        attacher.branchNextStubOrLabel(masm, Assembler::NotEqual,
+                                       Address(object, JSObject::offsetOfShape()),
+                                       ImmGCPtr(shape), failure);
+
+        if (alwaysCheckGroup)
+            masm.branchTestObjGroup(Assembler::NotEqual, object, obj->group(), failure);
     }
 }
 
 static inline void
 EmitLoadSlot(MacroAssembler& masm, NativeObject* holder, Shape* shape, Register holderReg,
              TypedOrValueRegister output, Register scratchReg)
 {
     MOZ_ASSERT(holder);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2931,26 +2931,30 @@ js::LookupPropertyPure(ExclusiveContext*
                 if (!clasp->resolve)
                     break;
                 if (clasp->resolve == fun_resolve && !FunctionHasResolveHook(cx->names(), id))
                     break;
                 if (clasp->resolve == str_resolve && !JSID_IS_INT(id))
                     break;
                 return false;
             } while (0);
-        } else {
-            // Search for a property on an unboxed object. Other non-native objects
-            // are not handled here.
-            if (!obj->is<UnboxedPlainObject>())
-                return false;
+        } else if (obj->is<UnboxedPlainObject>()) {
             if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) {
                 *objp = obj;
                 MarkNonNativePropertyFound<NoGC>(propp);
                 return true;
             }
+        } else if (obj->is<TypedObject>()) {
+            if (obj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id)) {
+                *objp = obj;
+                MarkNonNativePropertyFound<NoGC>(propp);
+                return true;
+            }
+        } else {
+            return false;
         }
 
         obj = obj->getProto();
     } while (obj);
 
     *objp = nullptr;
     *propp = nullptr;
     return true;
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -261,17 +261,17 @@ interface nsIXPCFunctionThisTranslator :
 %{ C++
 // For use with the service manager
 // {CB6593E0-F9B2-11d2-BDD6-000064657374}
 #define NS_XPCONNECT_CID \
 { 0xcb6593e0, 0xf9b2, 0x11d2, \
     { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
 %}
 
-[noscript, uuid(6872bfd6-660b-4aa3-b54b-41ce1d2d69e3)]
+[noscript, uuid(241fbefa-89dc-42b2-b180-08167d4b351b)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
   NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
      * Creates a new global object using the given aCOMObj as the global
@@ -402,24 +402,16 @@ interface nsIXPConnect : nsISupports
     nsIXPConnectWrappedNative
     getWrappedNativeOfJSObject(in JSContextPtr aJSContext,
                                in JSObjectPtr  aJSObj);
 
     [noscript, notxpcom] nsISupports
     getNativeOfWrapper(in JSContextPtr aJSContext,
                        in JSObjectPtr  aJSObj);
 
-    nsIStackFrame
-    createStackFrameLocation(in uint32_t       aLanguage,
-                             in string         aFilename,
-                             in string         aFunctionName,
-                             in int32_t        aLineNumber,
-                             in nsIStackFrame  aCaller);
-
-
     [noscript,notxpcom,nostdcall] JSContextPtr getCurrentJSContext();
     [noscript,notxpcom,nostdcall] JSContextPtr getSafeJSContext();
 
     readonly attribute nsIStackFrame                CurrentJSStack;
     readonly attribute nsAXPCNativeCallContextPtr   CurrentNativeCallContext;
 
     void debugDump(in short depth);
     void debugDumpObject(in nsISupports aCOMObj, in short depth);
--- a/js/xpconnect/loader/XPCOMUtils.jsm
+++ b/js/xpconnect/loader/XPCOMUtils.jsm
@@ -139,17 +139,17 @@ this.XPCOMUtils = {
         _interfaces.push(Ci[iface]);
       }
     }
     return {
       getInterfaces: function XPCU_getInterfaces(countRef) {
         countRef.value = _interfaces.length;
         return _interfaces;
       },
-      getHelperForLanguage: function XPCU_getHelperForLanguage(language) null,
+      getScriptableHelper: function XPCU_getScriptableHelper() null,
       contractID: classInfo.contractID,
       classDescription: classInfo.classDescription,
       classID: classInfo.classID,
       implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
       flags: classInfo.flags,
       QueryInterface: this.generateQI([Ci.nsIClassInfo])
     };
   },
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -148,20 +148,19 @@ nsXPCComponents_Interfaces::GetInterface
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCComponents_Interfaces::GetHelperForLanguage(uint32_t language,
-                                                 nsISupports** retval)
+nsXPCComponents_Interfaces::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents_Interfaces::GetContractID(char * *aContractID)
@@ -392,20 +391,19 @@ nsXPCComponents_InterfacesByID::GetInter
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCComponents_InterfacesByID::GetHelperForLanguage(uint32_t language,
-                                                     nsISupports** retval)
+nsXPCComponents_InterfacesByID::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents_InterfacesByID::GetContractID(char * *aContractID)
@@ -638,20 +636,19 @@ nsXPCComponents_Classes::GetInterfaces(u
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCComponents_Classes::GetHelperForLanguage(uint32_t language,
-                                              nsISupports** retval)
+nsXPCComponents_Classes::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents_Classes::GetContractID(char * *aContractID)
@@ -864,20 +861,19 @@ nsXPCComponents_ClassesByID::GetInterfac
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCComponents_ClassesByID::GetHelperForLanguage(uint32_t language,
-                                                  nsISupports** retval)
+nsXPCComponents_ClassesByID::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents_ClassesByID::GetContractID(char * *aContractID)
@@ -1113,20 +1109,19 @@ nsXPCComponents_Results::GetInterfaces(u
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCComponents_Results::GetHelperForLanguage(uint32_t language,
-                                              nsISupports** retval)
+nsXPCComponents_Results::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents_Results::GetContractID(char * *aContractID)
@@ -1319,20 +1314,19 @@ nsXPCComponents_ID::GetInterfaces(uint32
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCComponents_ID::GetHelperForLanguage(uint32_t language,
-                                         nsISupports** retval)
+nsXPCComponents_ID::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents_ID::GetContractID(char * *aContractID)
@@ -1536,20 +1530,19 @@ nsXPCComponents_Exception::GetInterfaces
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCComponents_Exception::GetHelperForLanguage(uint32_t language,
-                                                nsISupports** retval)
+nsXPCComponents_Exception::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents_Exception::GetContractID(char * *aContractID)
@@ -1926,20 +1919,19 @@ nsXPCConstructor::GetInterfaces(uint32_t
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCConstructor::GetHelperForLanguage(uint32_t language,
-                                       nsISupports** retval)
+nsXPCConstructor::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCConstructor::GetContractID(char * *aContractID)
@@ -2181,20 +2173,19 @@ nsXPCComponents_Constructor::GetInterfac
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper(); */
 NS_IMETHODIMP
-nsXPCComponents_Constructor::GetHelperForLanguage(uint32_t language,
-                                                  nsISupports** retval)
+nsXPCComponents_Constructor::GetScriptableHelper(nsIXPCScriptable** retval)
 {
     *retval = nullptr;
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 nsXPCComponents_Constructor::GetContractID(char * *aContractID)
@@ -3730,17 +3721,17 @@ public:
     {
     }
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIXPCSCRIPTABLE
     // The NS_IMETHODIMP isn't really accurate here, but NS_CALLBACK requires
     // the referent to be declared __stdcall on Windows, and this is the only
     // macro that does that.
-    static NS_IMETHODIMP Get(uint32_t aLangId, nsISupports** helper)
+    static NS_IMETHODIMP Get(nsIXPCScriptable** helper)
     {
         *helper = &singleton;
         return NS_OK;
     }
 
 private:
     static ComponentsSH singleton;
 };
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -234,25 +234,21 @@ static void EnsureClassObjectsInitialize
 {
     if (!gClassObjectsWereInited) {
         gSharedScriptableHelperForJSIID = new SharedScriptableHelperForJSIID();
 
         gClassObjectsWereInited = true;
     }
 }
 
-NS_METHOD GetSharedScriptableHelperForJSIID(uint32_t language,
-                                            nsISupports** helper)
+NS_METHOD GetSharedScriptableHelperForJSIID(nsIXPCScriptable** helper)
 {
     EnsureClassObjectsInitialized();
-    if (language == nsIProgrammingLanguage::JAVASCRIPT) {
-        nsCOMPtr<nsIXPCScriptable> temp = gSharedScriptableHelperForJSIID.get();
-        temp.forget(helper);
-    } else
-        *helper = nullptr;
+    nsCOMPtr<nsIXPCScriptable> temp = gSharedScriptableHelperForJSIID.get();
+    temp.forget(helper);
     return NS_OK;
 }
 
 /******************************************************/
 
 #define NULL_CID                                                              \
 { 0x00000000, 0x0000, 0x0000,                                                 \
   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
--- a/js/xpconnect/src/XPCRuntimeService.cpp
+++ b/js/xpconnect/src/XPCRuntimeService.cpp
@@ -109,24 +109,22 @@ BackstagePass::GetInterfaces(uint32_t* a
 oom:
     while (index)
         nsMemory::Free(array[--index]);
     nsMemory::Free(array);
     *aArray = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
 }
 
-/* nsISupports getHelperForLanguage (in uint32_t language); */
+/* nsIXPCScriptable getScriptableHelper (); */
 NS_IMETHODIMP
-BackstagePass::GetHelperForLanguage(uint32_t language,
-                                    nsISupports** retval)
+BackstagePass::GetScriptableHelper(nsIXPCScriptable** retval)
 {
-    nsCOMPtr<nsISupports> supports =
-        do_QueryInterface(static_cast<nsIGlobalObject*>(this));
-    supports.forget(retval);
+    nsCOMPtr<nsIXPCScriptable> scriptable = this;
+    scriptable.forget(retval);
     return NS_OK;
 }
 
 /* readonly attribute string contractID; */
 NS_IMETHODIMP
 BackstagePass::GetContractID(char * *aContractID)
 {
     *aContractID = nullptr;
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -650,26 +650,22 @@ XPCWrappedNative::GatherProtoScriptableC
           dont_AddRef(static_cast<nsIXPCScriptable*>(classInfoHelper));
         uint32_t flags = classInfoHelper->GetScriptableFlags();
         sciProto.SetCallback(helper.forget());
         sciProto.SetFlags(XPCNativeScriptableFlags(flags));
 
         return;
     }
 
-    nsCOMPtr<nsISupports> possibleHelper;
-    nsresult rv = classInfo->GetHelperForLanguage(nsIProgrammingLanguage::JAVASCRIPT,
-                                                  getter_AddRefs(possibleHelper));
-    if (NS_SUCCEEDED(rv) && possibleHelper) {
-        nsCOMPtr<nsIXPCScriptable> helper(do_QueryInterface(possibleHelper));
-        if (helper) {
-            uint32_t flags = helper->GetScriptableFlags();
-            sciProto.SetCallback(helper.forget());
-            sciProto.SetFlags(XPCNativeScriptableFlags(flags));
-        }
+    nsCOMPtr<nsIXPCScriptable> helper;
+    nsresult rv = classInfo->GetScriptableHelper(getter_AddRefs(helper));
+    if (NS_SUCCEEDED(rv) && helper) {
+        uint32_t flags = helper->GetScriptableFlags();
+        sciProto.SetCallback(helper.forget());
+        sciProto.SetFlags(XPCNativeScriptableFlags(flags));
     }
 }
 
 // static
 const XPCNativeScriptableCreateInfo&
 XPCWrappedNative::GatherScriptableCreateInfo(nsISupports* obj,
                                              nsIClassInfo* classInfo,
                                              XPCNativeScriptableCreateInfo& sciProto,
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -685,37 +685,16 @@ nsXPConnect::GetWrappedNativeOfNativeObj
 
     nsresult rv = XPCWrappedNative::GetUsedOnly(aCOMObj, scope, iface, &wrapper);
     if (NS_FAILED(rv))
         return NS_ERROR_FAILURE;
     *_retval = static_cast<nsIXPConnectWrappedNative*>(wrapper);
     return NS_OK;
 }
 
-/* nsIStackFrame createStackFrameLocation (in uint32_t aLanguage, in string aFilename, in string aFunctionName, in int32_t aLineNumber, in nsIStackFrame aCaller); */
-NS_IMETHODIMP
-nsXPConnect::CreateStackFrameLocation(uint32_t aLanguage,
-                                      const char* aFilename,
-                                      const char* aFunctionName,
-                                      int32_t aLineNumber,
-                                      nsIStackFrame* aCaller,
-                                      nsIStackFrame** _retval)
-{
-    MOZ_ASSERT(_retval, "bad param");
-
-    nsCOMPtr<nsIStackFrame> stackFrame =
-        exceptions::CreateStackFrameLocation(aLanguage,
-                                             aFilename,
-                                             aFunctionName,
-                                             aLineNumber,
-                                             aCaller);
-    stackFrame.forget(_retval);
-    return NS_OK;
-}
-
 /* readonly attribute nsIStackFrame CurrentJSStack; */
 NS_IMETHODIMP
 nsXPConnect::GetCurrentJSStack(nsIStackFrame * *aCurrentJSStack)
 {
     MOZ_ASSERT(aCurrentJSStack, "bad param");
 
     nsCOMPtr<nsIStackFrame> currentStack = dom::GetCurrentJSStack();
     currentStack.forget(aCurrentJSStack);
--- a/js/xpconnect/tests/unit/component-blob.js
+++ b/js/xpconnect/tests/unit/component-blob.js
@@ -63,17 +63,17 @@ BlobComponent.prototype =
   flags: 0,
 
   getInterfaces: function getInterfaces(aCount) {
     var interfaces = [Components.interfaces.nsIClassInfo];
     aCount.value = interfaces.length;
     return interfaces;
   },
 
-  getHelperForLanguage: function getHelperForLanguage(aLanguage) {
+  getScriptableHelper: function getScriptableHelper() {
     return null;
   },
 
   // nsISupports
   QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIClassInfo])
 };
 
 var gComponentsArray = [BlobComponent];
--- a/js/xpconnect/tests/unit/component-file.js
+++ b/js/xpconnect/tests/unit/component-file.js
@@ -88,17 +88,17 @@ FileComponent.prototype =
   flags: 0,
 
   getInterfaces: function getInterfaces(aCount) {
     var interfaces = [Components.interfaces.nsIClassInfo];
     aCount.value = interfaces.length;
     return interfaces;
   },
 
-  getHelperForLanguage: function getHelperForLanguage(aLanguage) {
+  getScriptableHelper: function getScriptableHelper() {
     return null;
   },
 
   // nsISupports
   QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIClassInfo])
 };
 
 var gComponentsArray = [FileComponent];
--- a/js/xpconnect/tests/unit/component_import.js
+++ b/js/xpconnect/tests/unit/component_import.js
@@ -30,17 +30,17 @@ FooComponent.prototype =
     } catch (ex) {
       do_check_true(ex.lineNumber == 28);
     }
     do_check_true(threw);
     
     return interfaces;
   },
 
-  getHelperForLanguage: function getHelperForLanguage(aLanguage) {
+  getScriptableHelper: function getScriptableHelper() {
     return null;
   },
 
   // nsISupports
   QueryInterface: function QueryInterface(aIID) {
     if (aIID.equals(Components.interfaces.nsIClassInfo) ||
         aIID.equals(Components.interfaces.nsISupports))
       return this;
@@ -63,17 +63,17 @@ BarComponent.prototype =
   flags: 0,
 
   getInterfaces: function getInterfaces(aCount) {
     var interfaces = [Components.interfaces.nsIClassInfo];
     aCount.value = interfaces.length;
     return interfaces;
   },
 
-  getHelperForLanguage: function getHelperForLanguage(aLanguage) {
+  getScriptableHelper: function getScriptableHelper() {
     return null;
   },
 
   // nsISupports
   QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIClassInfo])
 };
 
 function do_check_true(cond, text) {
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2792,17 +2792,17 @@ PaintInactiveLayer(nsDisplayListBuilder*
 #ifdef MOZ_DUMP_PAINTING
   int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
   nsIntRect itemVisibleRect =
     aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
 
   RefPtr<DrawTarget> tempDT;
   if (gfxUtils::sDumpPainting) {
     tempDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
-                                      itemVisibleRect.Size().ToIntSize(),
+                                      itemVisibleRect.Size(),
                                       SurfaceFormat::B8G8R8A8);
     if (tempDT) {
       context = new gfxContext(tempDT);
       context->SetMatrix(gfxMatrix::Translation(-itemVisibleRect.x,
                                                 -itemVisibleRect.y));
     }
   }
 #endif
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -4732,19 +4732,20 @@ nsImageRenderer::ComputeIntrinsicSize()
         // SVG images have no intrinsic size
         if (!mPaintServerFrame->IsFrameOfType(nsIFrame::eSVG)) {
           // The intrinsic image size for a generic nsIFrame paint server is
           // the union of the border-box rects of all of its continuations,
           // rounded to device pixels.
           int32_t appUnitsPerDevPixel =
             mForFrame->PresContext()->AppUnitsPerDevPixel();
           result.SetSize(
-            nsSVGIntegrationUtils::GetContinuationUnionSize(mPaintServerFrame).
-              ToNearestPixels(appUnitsPerDevPixel).
-              ToAppUnits(appUnitsPerDevPixel));
+            IntSizeToAppUnits(
+              nsSVGIntegrationUtils::GetContinuationUnionSize(mPaintServerFrame).
+                ToNearestPixels(appUnitsPerDevPixel),
+              appUnitsPerDevPixel));
         }
       } else {
         NS_ASSERTION(mImageElementSurface.mSourceSurface, "Surface should be ready.");
         gfxIntSize surfaceSize = mImageElementSurface.mSize;
         result.SetSize(
           nsSize(nsPresContext::CSSPixelsToAppUnits(surfaceSize.width),
                  nsPresContext::CSSPixelsToAppUnits(surfaceSize.height)));
       }
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -406,23 +406,21 @@ AddAnimationForProperty(nsIFrame* aFrame
 static void
 AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
                          AnimationPlayerPtrArray& aPlayers,
                          Layer* aLayer, AnimationData& aData,
                          bool aPending)
 {
   for (size_t playerIdx = 0; playerIdx < aPlayers.Length(); playerIdx++) {
     AnimationPlayer* player = aPlayers[playerIdx];
-    if (!player->IsRunning()) {
+    if (!player->IsPlaying()) {
       continue;
     }
     dom::Animation* anim = player->GetSource();
-    if (!anim) {
-      continue;
-    }
+    MOZ_ASSERT(anim, "A playing player should have a source animation");
     const AnimationProperty* property =
       anim->GetAnimationOfProperty(aProperty);
     if (!property) {
       continue;
     }
 
     if (!property->mWinsInCascade) {
       // We have an animation or transition, but it isn't actually
@@ -3014,21 +3012,16 @@ nsDisplayThemedBackground::GetBounds(nsD
 nsRect
 nsDisplayThemedBackground::GetBoundsInternal() {
   nsPresContext* presContext = mFrame->PresContext();
 
   nsRect r(nsPoint(0,0), mFrame->GetSize());
   presContext->GetTheme()->
       GetWidgetOverflow(presContext->DeviceContext(), mFrame,
                         mFrame->StyleDisplay()->mAppearance, &r);
-#ifdef XP_MACOSX
-  // Bug 748219
-  r.Inflate(mFrame->PresContext()->AppUnitsPerDevPixel());
-#endif
-
   return r + ToReferenceFrame();
 }
 
 void
 nsDisplayBackgroundColor::ApplyOpacity(nsDisplayListBuilder* aBuilder,
                                        float aOpacity,
                                        const DisplayItemClip* aClip)
 {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6782,17 +6782,17 @@ nsLayoutUtils::SurfaceFromElement(HTMLVi
   if (aTarget) {
     RefPtr<SourceSurface> opt = aTarget->OptimizeSourceSurface(result.mSourceSurface);
     if (opt) {
       result.mSourceSurface = opt;
     }
   }
 
   result.mCORSUsed = aElement->GetCORSMode() != CORS_NONE;
-  result.mSize = ThebesIntSize(size);
+  result.mSize = size;
   result.mPrincipal = principal.forget();
   result.mIsWriteOnly = false;
 
   return result;
 }
 
 nsLayoutUtils::SurfaceFromElementResult
 nsLayoutUtils::SurfaceFromElement(dom::Element* aElement,
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -1429,21 +1429,21 @@ nsPluginFrame::BuildLayer(nsDisplayListB
     if (!layer) {
       layer = aManager->CreateReadbackLayer();
       if (!layer)
         return nullptr;
     }
     NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type");
 
     ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get());
-    if (readback->GetSize() != ThebesIntSize(size)) {
+    if (readback->GetSize() != size) {
       // This will destroy any old background sink and notify us that the
       // background is now unknown
       readback->SetSink(nullptr);
-      readback->SetSize(ThebesIntSize(size));
+      readback->SetSize(size);
 
       if (mBackgroundSink) {
         // Maybe we still have a background sink associated with another
         // readback layer that wasn't recycled for some reason? Unhook it
         // now so that if this frame goes away, it doesn't have a dangling
         // reference to us.
         mBackgroundSink->Destroy();
       }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/invalidation/masklayer-1.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Moving a layer in a box with a rounded clip shouldn't invalidate.</title>
+
+<style>
+
+#outer {
+  position: absolute;
+  top: 50px;
+  left: 50px;
+  width: 300px;
+  height: 200px;
+  background-color: #DDD;
+  overflow: hidden;
+  border-radius: 10px;
+}
+
+#animatedLeft {
+  position: absolute;
+  top: 50px;
+  left: 40px;
+  box-model: border-box;
+  border: 1px solid lime;
+  width: 100px;
+  height: 100px;
+}
+
+</style>
+
+<body>
+
+<div id="outer">
+  <div id="animatedLeft" class="reftest-no-paint"></div>
+</div>
+
+<script>
+
+var animatedLeft = document.getElementById("animatedLeft");
+
+function doTest() {
+  animatedLeft.style.left = "100px";
+  document.documentElement.removeAttribute("class");
+}
+
+// Layerize #animatedLeft
+animatedLeft.offsetLeft;
+animatedLeft.style.left = "60px";
+animatedLeft.offsetLeft;
+animatedLeft.style.left = "40px";
+animatedLeft.offsetLeft;
+
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/invalidation/masklayer-2.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Moving a layer in a box with a rounded clip shouldn't invalidate.</title>
+
+<style>
+
+#scrollbox {
+  position: absolute;
+  top: 50px;
+  left: 50px;
+  width: 300px;
+  height: 200px;
+  background-color: #DDD;
+  overflow: auto;
+  border-radius: 10px;
+}
+
+#scrollable {
+  width: 600px;
+}
+
+#scrolledLayer {
+  margin-top: 50px;
+  margin-left: 100px;
+  box-model: border-box;
+  border: 1px solid lime;
+  width: 100px;
+  height: 100px;
+}
+
+</style>
+
+<body>
+
+<div id="scrollbox">
+  <div id="scrollable">
+    <div id="scrolledLayer" class="reftest-no-paint"></div>
+  </div>
+</div>
+
+<script>
+
+var scrollbox = document.getElementById("scrollbox");
+
+function doTest() {
+  scrollbox.scrollLeft = 0;
+  document.documentElement.removeAttribute("class");
+}
+
+// Make #scrollbox have active scrolling
+scrollbox.scrollLeft = 60;
+scrollbox.offsetLeft;
+scrollbox.scrollLeft = 40;
+scrollbox.offsetLeft;
+
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
--- a/layout/reftests/invalidation/reftest.list
+++ b/layout/reftests/invalidation/reftest.list
@@ -50,8 +50,10 @@ pref(layout.animated-image-layers.enable
 != clipped-animated-transform-1.html about:blank
 != paintedlayer-recycling-1.html about:blank
 != paintedlayer-recycling-2.html about:blank
 != paintedlayer-recycling-3.html about:blank
 != paintedlayer-recycling-4.html about:blank
 != paintedlayer-recycling-5.html about:blank
 != paintedlayer-recycling-6.html about:blank
 != paintedlayer-recycling-7.html about:blank
+!= masklayer-1.html about:blank
+!= masklayer-2.html about:blank
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -552,37 +552,42 @@ AnimationPlayerCollection::CanPerformOnC
       message.Append(")");
       LogAsyncAnimationFailure(message, mElement);
     }
     return false;
   }
 
   for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) {
     const AnimationPlayer* player = mPlayers[playerIdx];
-    if (!player->IsRunning() || !player->GetSource()) {
+    if (!player->IsPlaying()) {
       continue;
     }
+
     const Animation* anim = player->GetSource();
+    MOZ_ASSERT(anim, "A playing player should have a source animation");
+
     for (size_t propIdx = 0, propEnd = anim->Properties().Length();
          propIdx != propEnd; ++propIdx) {
       if (IsGeometricProperty(anim->Properties()[propIdx].mProperty)) {
         aFlags = CanAnimateFlags(aFlags | CanAnimate_HasGeometricProperty);
         break;
       }
     }
   }
 
   bool existsProperty = false;
   for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) {
     const AnimationPlayer* player = mPlayers[playerIdx];
-    if (!player->IsRunning() || !player->GetSource()) {
+    if (!player->IsPlaying()) {
       continue;
     }
 
     const Animation* anim = player->GetSource();
+    MOZ_ASSERT(anim, "A playing player should have a source animation");
+
     existsProperty = existsProperty || anim->Properties().Length() > 0;
 
     for (size_t propIdx = 0, propEnd = anim->Properties().Length();
          propIdx != propEnd; ++propIdx) {
       const AnimationProperty& prop = anim->Properties()[propIdx];
       if (!CanAnimatePropertyOnCompositor(mElement,
                                           prop.mProperty,
                                           aFlags) ||
@@ -849,18 +854,21 @@ AnimationPlayerCollection::HasCurrentAni
   return false;
 }
 
 bool
 AnimationPlayerCollection::HasCurrentAnimationsForProperty(nsCSSProperty
                                                              aProperty) const
 {
   for (size_t playerIdx = mPlayers.Length(); playerIdx-- != 0; ) {
-    const Animation* anim = mPlayers[playerIdx]->GetSource();
-    if (anim && anim->IsCurrent() && anim->HasAnimationOfProperty(aProperty)) {
+    const AnimationPlayer& player = *mPlayers[playerIdx];
+    const Animation* anim = player.GetSource();
+    if (anim &&
+        anim->IsCurrent(player) &&
+        anim->HasAnimationOfProperty(aProperty)) {
       return true;
     }
   }
 
   return false;
 }
 
 }
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -2490,24 +2490,23 @@ BuildStyleRule(nsCSSProperty aProperty,
   nsIDocument* doc = aTargetElement->OwnerDoc();
   nsCOMPtr<nsIURI> baseURI = aTargetElement->GetBaseURI();
   nsCSSParser parser(doc->CSSLoader());
 
   nsCSSProperty propertyToCheck = nsCSSProps::IsShorthand(aProperty) ?
     nsCSSProps::SubpropertyEntryFor(aProperty)[0] : aProperty;
 
   // Get a parser, parse the property, and check for CSS parsing errors.
-  // If any of these steps fails, we bail out and delete the declaration.
-  if (NS_FAILED(parser.ParseProperty(aProperty, aSpecifiedValue,
-                                     doc->GetDocumentURI(), baseURI,
-                                     aTargetElement->NodePrincipal(),
-                                     declaration, &changed, false,
-                                     aUseSVGMode)) ||
-      // check whether property parsed without CSS parsing errors
-      !declaration->HasNonImportantValueFor(propertyToCheck)) {
+  // If this fails, we bail out and delete the declaration.
+  parser.ParseProperty(aProperty, aSpecifiedValue, doc->GetDocumentURI(),
+                       baseURI, aTargetElement->NodePrincipal(), declaration,
+                       &changed, false, aUseSVGMode);
+
+  // check whether property parsed without CSS parsing errors
+  if (!declaration->HasNonImportantValueFor(propertyToCheck)) {
     NS_WARNING("failure in BuildStyleRule");
     return nullptr;
   }
 
   nsRefPtr<css::StyleRule> rule = new css::StyleRule(nullptr,
                                                      declaration.forget(),
                                                      0, 0);
   return rule.forget();
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -139,47 +139,47 @@ public:
                              bool*           aChanged);
 
   nsresult ParseRule(const nsAString&        aRule,
                      nsIURI*                 aSheetURL,
                      nsIURI*                 aBaseURL,
                      nsIPrincipal*           aSheetPrincipal,
                      css::Rule**             aResult);
 
-  nsresult ParseProperty(const nsCSSProperty aPropID,
-                         const nsAString& aPropValue,
-                         nsIURI* aSheetURL,
-                         nsIURI* aBaseURL,
-                         nsIPrincipal* aSheetPrincipal,
-                         css::Declaration* aDeclaration,
-                         bool* aChanged,
-                         bool aIsImportant,
-                         bool aIsSVGMode);
+  void ParseProperty(const nsCSSProperty aPropID,
+                     const nsAString& aPropValue,
+                     nsIURI* aSheetURL,
+                     nsIURI* aBaseURL,
+                     nsIPrincipal* aSheetPrincipal,
+                     css::Declaration* aDeclaration,
+                     bool* aChanged,
+                     bool aIsImportant,
+                     bool aIsSVGMode);
 
   void ParseMediaList(const nsSubstring& aBuffer,
                       nsIURI* aURL, // for error reporting
                       uint32_t aLineNumber, // for error reporting
                       nsMediaList* aMediaList,
                       bool aHTMLMode);
 
   bool ParseSourceSizeList(const nsAString& aBuffer,
                            nsIURI* aURI, // for error reporting
                            uint32_t aLineNumber, // for error reporting
                            InfallibleTArray< nsAutoPtr<nsMediaQuery> >& aQueries,
                            InfallibleTArray<nsCSSValue>& aValues,
                            bool aHTMLMode);
 
-  nsresult ParseVariable(const nsAString& aVariableName,
-                         const nsAString& aPropValue,
-                         nsIURI* aSheetURL,
-                         nsIURI* aBaseURL,
-                         nsIPrincipal* aSheetPrincipal,
-                         css::Declaration* aDeclaration,
-                         bool* aChanged,
-                         bool aIsImportant);
+  void ParseVariable(const nsAString& aVariableName,
+                     const nsAString& aPropValue,
+                     nsIURI* aSheetURL,
+                     nsIURI* aBaseURL,
+                     nsIPrincipal* aSheetPrincipal,
+                     css::Declaration* aDeclaration,
+                     bool* aChanged,
+                     bool aIsImportant);
 
   bool ParseFontFamilyListString(const nsSubstring& aBuffer,
                                  nsIURI* aURL, // for error reporting
                                  uint32_t aLineNumber, // for error reporting
                                  nsCSSValue& aValue);
 
   bool ParseColorString(const nsSubstring& aBuffer,
                         nsIURI* aURL, // for error reporting
@@ -1610,17 +1610,17 @@ CSSParserImpl::ParseRule(const nsAString
 
 // See Bug 723197
 #ifdef _MSC_VER
 #pragma optimize( "", off )
 #pragma warning( push )
 #pragma warning( disable : 4748 )
 #endif
 
-nsresult
+void
 CSSParserImpl::ParseProperty(const nsCSSProperty aPropID,
                              const nsAString& aPropValue,
                              nsIURI* aSheetURI,
                              nsIURI* aBaseURI,
                              nsIPrincipal* aSheetPrincipal,
                              css::Declaration* aDeclaration,
                              bool* aChanged,
                              bool aIsImportant,
@@ -1649,17 +1649,17 @@ CSSParserImpl::ParseProperty(const nsCSS
         (mUnsafeRulesEnabled &&
          nsCSSProps::PropHasFlags(aPropID,
                                   CSS_PROPERTY_ALWAYS_ENABLED_IN_UA_SHEETS)))) {
     NS_ConvertASCIItoUTF16 propName(nsCSSProps::GetStringValue(aPropID));
     REPORT_UNEXPECTED_P(PEUnknownProperty, propName);
     REPORT_UNEXPECTED(PEDeclDropped);
     OUTPUT_ERROR();
     ReleaseScanner();
-    return NS_OK;
+    return;
   }
 
   bool parsedOK = ParseProperty(aPropID);
   // We should now be at EOF
   if (parsedOK && GetToken(true)) {
     REPORT_UNEXPECTED_TOKEN(PEExpectEndValue);
     parsedOK = false;
   }
@@ -1688,20 +1688,19 @@ CSSParserImpl::ParseProperty(const nsCSS
       aDeclaration->CompressFrom(&mData);
     }
     CLEAR_ERROR();
   }
 
   mTempData.AssertInitialState();
 
   ReleaseScanner();
-  return NS_OK;
-}
-
-nsresult
+}
+
+void
 CSSParserImpl::ParseVariable(const nsAString& aVariableName,
                              const nsAString& aPropValue,
                              nsIURI* aSheetURI,
                              nsIURI* aBaseURI,
                              nsIPrincipal* aSheetPrincipal,
                              css::Declaration* aDeclaration,
                              bool* aChanged,
                              bool aIsImportant)
@@ -1744,17 +1743,16 @@ CSSParserImpl::ParseVariable(const nsASt
     aDeclaration->AddVariableDeclaration(aVariableName, variableType,
                                          variableValue, aIsImportant, true);
     *aChanged = true;
   }
 
   mTempData.AssertInitialState();
 
   ReleaseScanner();
-  return NS_OK;
 }
 
 #ifdef _MSC_VER
 #pragma warning( pop )
 #pragma optimize( "", on )
 #endif
 
 void
@@ -15563,44 +15561,44 @@ nsCSSParser::ParseRule(const nsAString& 
                        nsIURI*                 aBaseURI,
                        nsIPrincipal*           aSheetPrincipal,
                        css::Rule**             aResult)
 {
   return static_cast<CSSParserImpl*>(mImpl)->
     ParseRule(aRule, aSheetURI, aBaseURI, aSheetPrincipal, aResult);
 }
 
-nsresult
+void
 nsCSSParser::ParseProperty(const nsCSSProperty aPropID,
                            const nsAString&    aPropValue,
                            nsIURI*             aSheetURI,
                            nsIURI*             aBaseURI,
                            nsIPrincipal*       aSheetPrincipal,
                            css::Declaration*   aDeclaration,
                            bool*               aChanged,
                            bool                aIsImportant,
                            bool                aIsSVGMode)
 {
-  return static_cast<CSSParserImpl*>(mImpl)->
+  static_cast<CSSParserImpl*>(mImpl)->
     ParseProperty(aPropID, aPropValue, aSheetURI, aBaseURI,
                   aSheetPrincipal, aDeclaration, aChanged,
                   aIsImportant, aIsSVGMode);
 }
 
-nsresult
+void
 nsCSSParser::ParseVariable(const nsAString&    aVariableName,
                            const nsAString&    aPropValue,
                            nsIURI*             aSheetURI,
                            nsIURI*             aBaseURI,
                            nsIPrincipal*       aSheetPrincipal,
                            css::Declaration*   aDeclaration,
                            bool*               aChanged,
                            bool                aIsImportant)
 {
-  return static_cast<CSSParserImpl*>(mImpl)->
+  static_cast<CSSParserImpl*>(mImpl)->
     ParseVariable(aVariableName, aPropValue, aSheetURI, aBaseURI,
                   aSheetPrincipal, aDeclaration, aChanged, aIsImportant);
 }
 
 void
 nsCSSParser::ParseMediaList(const nsSubstring& aBuffer,
                             nsIURI*            aURI,
                             uint32_t           aLineNumber,
--- a/layout/style/nsCSSParser.h
+++ b/layout/style/nsCSSParser.h
@@ -117,35 +117,35 @@ public:
   // Parse the value of a single CSS property, and add or replace that
   // property in aDeclaration.
   //
   // SVG "mapped attributes" (which correspond directly to CSS
   // properties) are parsed slightly differently from regular CSS; in
   // particular, units may be omitted from <length>.  The 'aIsSVGMode'
   // argument controls this quirk.  Note that this *only* applies to
   // mapped attributes, not inline styles or full style sheets in SVG.
-  nsresult ParseProperty(const nsCSSProperty aPropID,
-                         const nsAString&    aPropValue,
-                         nsIURI*             aSheetURL,
-                         nsIURI*             aBaseURL,
-                         nsIPrincipal*       aSheetPrincipal,
-                         mozilla::css::Declaration* aDeclaration,
-                         bool*               aChanged,
-                         bool                aIsImportant,
-                         bool                aIsSVGMode = false);
+  void ParseProperty(const nsCSSProperty aPropID,
+                     const nsAString&    aPropValue,
+                     nsIURI*             aSheetURL,
+                     nsIURI*             aBaseURL,
+                     nsIPrincipal*       aSheetPrincipal,
+                     mozilla::css::Declaration* aDeclaration,
+                     bool*               aChanged,
+                     bool                aIsImportant,
+                     bool                aIsSVGMode = false);
 
   // The same as ParseProperty but for a variable.
-  nsresult ParseVariable(const nsAString&    aVariableName,
-                         const nsAString&    aPropValue,
-                         nsIURI*             aSheetURL,
-                         nsIURI*             aBaseURL,
-                         nsIPrincipal*       aSheetPrincipal,
-                         mozilla::css::Declaration* aDeclaration,
-                         bool*               aChanged,
-                         bool                aIsImportant);
+  void ParseVariable(const nsAString&    aVariableName,
+                     const nsAString&    aPropValue,
+                     nsIURI*             aSheetURL,
+                     nsIURI*             aBaseURL,
+                     nsIPrincipal*       aSheetPrincipal,
+                     mozilla::css::Declaration* aDeclaration,
+                     bool*               aChanged,
+                     bool                aIsImportant);
   /**
    * Parse aBuffer into a media list |aMediaList|, which must be
    * non-null, replacing its current contents.  If aHTMLMode is true,
    * parse according to HTML rules, with commas as the most important
    * delimiter.  Otherwise, parse according to CSS rules, with
    * parentheses and strings more important than commas.  |aURL| and
    * |aLineNumber| are used for error reporting.
    */
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -326,24 +326,24 @@ nsDOMCSSDeclaration::ParsePropertyValue(
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
   css::Declaration* decl = olddecl->EnsureMutable();
 
   nsCSSParser cssParser(env.mCSSLoader);
   bool changed;
-  nsresult result = cssParser.ParseProperty(aPropID, aPropValue, env.mSheetURI,
-                                            env.mBaseURI, env.mPrincipal, decl,
-                                            &changed, aIsImportant);
-  if (NS_FAILED(result) || !changed) {
+  cssParser.ParseProperty(aPropID, aPropValue, env.mSheetURI, env.mBaseURI,
+                          env.mPrincipal, decl, &changed, aIsImportant);
+  if (!changed) {
     if (decl != olddecl) {
       delete decl;
     }
-    return result;
+    // Parsing failed -- but we don't throw an exception for that.
+    return NS_OK;
   }
 
   return SetCSSDeclaration(decl);
 }
 
 nsresult
 nsDOMCSSDeclaration::ParseCustomPropertyValue(const nsAString& aPropertyName,
                                               const nsAString& aPropValue,
@@ -367,27 +367,27 @@ nsDOMCSSDeclaration::ParseCustomProperty
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
   css::Declaration* decl = olddecl->EnsureMutable();
 
   nsCSSParser cssParser(env.mCSSLoader);
   bool changed;
-  nsresult result =
-    cssParser.ParseVariable(Substring(aPropertyName,
-                                      CSS_CUSTOM_NAME_PREFIX_LENGTH),
-                            aPropValue, env.mSheetURI,
-                            env.mBaseURI, env.mPrincipal, decl,
-                            &changed, aIsImportant);
-  if (NS_FAILED(result) || !changed) {
+  cssParser.ParseVariable(Substring(aPropertyName,
+                                    CSS_CUSTOM_NAME_PREFIX_LENGTH),
+                          aPropValue, env.mSheetURI,
+                          env.mBaseURI, env.mPrincipal, decl,
+                          &changed, aIsImportant);
+  if (!changed) {
     if (decl != olddecl) {
       delete decl;
     }
-    return result;
+    // Parsing failed -- but we don't throw an exception for that.
+    return NS_OK;
   }
 
   return SetCSSDeclaration(decl);
 }
 
 nsresult
 nsDOMCSSDeclaration::RemoveProperty(const nsCSSProperty aPropID)
 {
--- a/layout/svg/nsSVGPatternFrame.cpp
+++ b/layout/svg/nsSVGPatternFrame.cpp
@@ -341,17 +341,17 @@ nsSVGPatternFrame::PaintPattern(const Dr
 
   // Now that we have all of the necessary geometries, we can
   // create our surface.
   gfxRect transformedBBox = ThebesRect(patternTransform.TransformBounds(ToRect(bbox)));
 
   bool resultOverflows;
   IntSize surfaceSize =
     nsSVGUtils::ConvertToSurfaceSize(
-      transformedBBox.Size(), &resultOverflows).ToIntSize();
+      transformedBBox.Size(), &resultOverflows);
 
   // 0 disables rendering, < 0 is an error
   if (surfaceSize.width <= 0 || surfaceSize.height <= 0) {
     return nullptr;
   }
 
   gfxFloat patternWidth = bbox.Width();
   gfxFloat patternHeight = bbox.Height();
--- a/layout/tools/reftest/reftest-content.js
+++ b/layout/tools/reftest/reftest-content.js
@@ -237,56 +237,65 @@ function setupDisplayport(contentRootEle
 
     if (contentRootElement.hasAttribute("reftest-async-scroll")) {
         setupDisplayportForElementSubtree(contentRootElement, windowUtils());
     } else {
         setupDisplayportForElement(contentRootElement, windowUtils());
     }
 }
 
+// Returns whether any offsets were updated
 function setupAsyncScrollOffsets(options) {
     var currentDoc = content.document;
     var contentRootElement = currentDoc ? currentDoc.documentElement : null;
 
     if (!contentRootElement) {
-        return;
+        return false;
     }
 
     function setupAsyncScrollOffsetsForElement(element, winUtils) {
         var sx = attrOrDefault(element, "reftest-async-scroll-x", 0);
         var sy = attrOrDefault(element, "reftest-async-scroll-y", 0);
         if (sx != 0 || sy != 0) {
             try {
                 // This might fail when called from RecordResult since layers
                 // may not have been constructed yet
                 winUtils.setAsyncScrollOffset(element, sx, sy);
+                return true;
             } catch (e) {
                 if (!options.allowFailure) {
                     throw e;
                 }
             }
         }
+        return false;
     }
 
     function setupAsyncScrollOffsetsForElementSubtree(element, winUtils) {
-        setupAsyncScrollOffsetsForElement(element, winUtils);
+        var updatedAny = setupAsyncScrollOffsetsForElement(element, winUtils);
         for (var c = element.firstElementChild; c; c = c.nextElementSibling) {
-            setupAsyncScrollOffsetsForElementSubtree(c, winUtils);
+            if (setupAsyncScrollOffsetsForElementSubtree(c, winUtils)) {
+                updatedAny = true;
+            }
         }
         if (element.contentDocument) {
             LogInfo("Descending into subdocument (async offsets)");
-            setupAsyncScrollOffsetsForElementSubtree(element.contentDocument.documentElement,
-                                                     windowUtilsForWindow(element.contentWindow));
+            if (setupAsyncScrollOffsetsForElementSubtree(element.contentDocument.documentElement,
+                                                         windowUtilsForWindow(element.contentWindow))) {
+                updatedAny = true;
+            }
         }
+        return updatedAny;
     }
 
     var asyncScroll = contentRootElement.hasAttribute("reftest-async-scroll");
     if (asyncScroll) {
-        setupAsyncScrollOffsetsForElementSubtree(contentRootElement, windowUtils());
+        return setupAsyncScrollOffsetsForElementSubtree(contentRootElement, windowUtils());
     }
+    return false;
 }
 
 function resetDisplayportAndViewport() {
     // XXX currently the displayport configuration lives on the
     // presshell and so is "reset" on nav when we get a new presshell.
 }
 
 function shouldWaitForExplicitPaintWaiters() {
@@ -789,18 +798,23 @@ function RecordResult()
         }
 
         SendScriptResults(currentTestRunTime, error, results);
         FinishTestItem();
         return;
     }
 
     // Setup async scroll offsets now in case SynchronizeForSnapshot is not
-    // called (due to reftest-no-sync-layers being supplied).
-    setupAsyncScrollOffsets({allowFailure:true});
+    // called (due to reftest-no-sync-layers being supplied, or in the single
+    // process case).
+    var changedAsyncScrollOffsets = setupAsyncScrollOffsets({allowFailure:true}) ;
+    if (changedAsyncScrollOffsets && !gBrowserIsRemote) {
+        sendAsyncMessage("reftest:UpdateWholeCanvasForInvalidation");
+    }
+
     SendTestDone(currentTestRunTime);
     FinishTestItem();
 }
 
 function LoadFailed()
 {
     if (gTimeoutHook) {
         gTimeoutHook();
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -2805,34 +2805,37 @@ nsresult
 PeerConnectionImpl::BuildStatsQuery_m(
     mozilla::dom::MediaStreamTrack *aSelector,
     RTCStatsQuery *query) {
 
   if (!HasMedia()) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  // Note: mMedia->ice_ctx() is deleted on STS thread; so make sure we grab and hold
-  // a ref instead of making multiple calls.  NrIceCtx uses threadsafe refcounting.
-  query->iceCtx = mMedia->ice_ctx();
-  if (!query->iceCtx) {
-    CSFLogError(logTag, "Could not build stats query, no ice_ctx");
-    return NS_ERROR_UNEXPECTED;
-  }
   if (!mThread) {
     CSFLogError(logTag, "Could not build stats query, no MainThread");
     return NS_ERROR_UNEXPECTED;
   }
 
   nsresult rv = GetTimeSinceEpoch(&(query->now));
   if (NS_FAILED(rv)) {
     CSFLogError(logTag, "Could not build stats query, could not get timestamp");
     return rv;
   }
 
+  // Note: mMedia->ice_ctx() is deleted on STS thread; so make sure we grab and hold
+  // a ref instead of making multiple calls.  NrIceCtx uses threadsafe refcounting.
+  // NOTE: Do this after all other failure tests, to ensure we don't
+  // accidentally release the Ctx on Mainthread.
+  query->iceCtx = mMedia->ice_ctx();
+  if (!query->iceCtx) {
+    CSFLogError(logTag, "Could not build stats query, no ice_ctx");
+    return NS_ERROR_UNEXPECTED;
+  }
+
   // We do not use the pcHandle here, since that's risky to expose to content.
   query->report = new RTCStatsReportInternalConstruct(
       NS_ConvertASCIItoUTF16(mName.c_str()),
       query->now);
 
   query->iceStartTime = mIceStartTime;
   query->failed = isFailed(mIceConnectionState);
 
--- a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp
@@ -162,33 +162,41 @@ WebrtcGlobalInformation::GetAllStats(
          p != ctx->mPeerConnections.end();
          ++p) {
       MOZ_ASSERT(p->second);
 
       if (!pcIdFilter.WasPassed() ||
           pcIdFilter.Value().EqualsASCII(p->second->GetIdAsAscii().c_str())) {
         if (p->second->HasMedia()) {
           queries->append(nsAutoPtr<RTCStatsQuery>(new RTCStatsQuery(true)));
-          p->second->BuildStatsQuery_m(nullptr, // all tracks
-                                       queries->back());
+          if (NS_WARN_IF(NS_FAILED(p->second->BuildStatsQuery_m(nullptr, // all tracks
+                                                                queries->back())))) {
+            queries->popBack();
+          } else {
+            MOZ_ASSERT(queries->back()->report);
+          }
         }
       }
     }
   }
 
-  // CallbackObject does not support threadsafe refcounting, and must be
-  // destroyed on main.
-  nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> callbackHandle(
-    new nsMainThreadPtrHolder<WebrtcGlobalStatisticsCallback>(&aStatsCallback));
+  if (!queries->empty()) {
+    // CallbackObject does not support threadsafe refcounting, and must be
+    // destroyed on main.
+    nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> callbackHandle(
+      new nsMainThreadPtrHolder<WebrtcGlobalStatisticsCallback>(&aStatsCallback));
 
-  rv = RUN_ON_THREAD(stsThread,
-                     WrapRunnableNM(&GetAllStats_s, callbackHandle, queries),
-                     NS_DISPATCH_NORMAL);
+    rv = RUN_ON_THREAD(stsThread,
+                       WrapRunnableNM(&GetAllStats_s, callbackHandle, queries),
+                       NS_DISPATCH_NORMAL);
 
-  aRv = rv;
+    aRv = rv;
+  } else {
+    aRv = NS_OK;
+  }
 }
 
 void
 WebrtcGlobalInformation::GetLogging(
   const GlobalObject& aGlobal,
   const nsAString& aPattern,
   WebrtcGlobalLoggingCallback& aLoggingCallback,
   ErrorResult& aRv)
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -342,18 +342,18 @@ SessionStore.prototype = {
 
   onTabClose: function ss_onTabClose(aWindow, aBrowser, aTabIndex) {
     if (this._maxTabsUndo == 0)
       return;
 
     if (aWindow.BrowserApp.tabs.length > 0) {
       // Bundle this browser's data and extra data and save in the closedTabs
       // window property
-      let data = aBrowser.__SS_data;
-      data.extData = aBrowser.__SS_extdata;
+      let data = aBrowser.__SS_data || {};
+      data.extData = aBrowser.__SS_extdata || {};
 
       this._windows[aWindow.__SSID].closedTabs.unshift(data);
       let length = this._windows[aWindow.__SSID].closedTabs.length;
       if (length > this._maxTabsUndo)
         this._windows[aWindow.__SSID].closedTabs.splice(this._maxTabsUndo, length - this._maxTabsUndo);
 
       this._lastClosedTabIndex = aTabIndex;
 
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -161,17 +161,17 @@ NS_IMETHODIMP
 nsJARURI::GetInterfaces(uint32_t *count, nsIID * **array)
 {
     *count = 0;
     *array = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsJARURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
+nsJARURI::GetScriptableHelper(nsIXPCScriptable **_retval)
 {
     *_retval = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsJARURI::GetContractID(char * *aContractID)
 {
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -552,17 +552,17 @@ NS_IMETHODIMP
 nsSimpleURI::GetInterfaces(uint32_t *count, nsIID * **array)
 {
     *count = 0;
     *array = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsSimpleURI::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
+nsSimpleURI::GetScriptableHelper(nsIXPCScriptable **_retval)
 {
     *_retval = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsSimpleURI::GetContractID(char * *aContractID)
 {
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -2434,17 +2434,17 @@ nsSocketTransport::GetInterface(const ns
 
 NS_IMETHODIMP
 nsSocketTransport::GetInterfaces(uint32_t *count, nsIID * **array)
 {
     return NS_CI_INTERFACE_GETTER_NAME(nsSocketTransport)(count, array);
 }
 
 NS_IMETHODIMP
-nsSocketTransport::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
+nsSocketTransport::GetScriptableHelper(nsIXPCScriptable **_retval)
 {
     *_retval = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSocketTransport::GetContractID(char * *aContractID)
 {
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -3174,17 +3174,17 @@ NS_IMETHODIMP
 nsStandardURL::GetInterfaces(uint32_t *count, nsIID * **array)
 {
     *count = 0;
     *array = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsStandardURL::GetHelperForLanguage(uint32_t language, nsISupports **_retval)
+nsStandardURL::GetScriptableHelper(nsIXPCScriptable **_retval)
 {
     *_retval = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsStandardURL::GetContractID(char * *aContractID)
 {
--- a/security/manager/ssl/src/TransportSecurityInfo.cpp
+++ b/security/manager/ssl/src/TransportSecurityInfo.cpp
@@ -442,18 +442,17 @@ NS_IMETHODIMP
 TransportSecurityInfo::GetInterfaces(uint32_t *count, nsIID * **array)
 {
   *count = 0;
   *array = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TransportSecurityInfo::GetHelperForLanguage(uint32_t language,
-                                            nsISupports **_retval)
+TransportSecurityInfo::GetScriptableHelper(nsIXPCScriptable **_retval)
 {
   *_retval = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TransportSecurityInfo::GetContractID(char * *aContractID)
 {
--- a/security/manager/ssl/src/nsNSSCertificate.cpp
+++ b/security/manager/ssl/src/nsNSSCertificate.cpp
@@ -1916,18 +1916,17 @@ NS_IMETHODIMP
 nsNSSCertificate::GetInterfaces(uint32_t* count, nsIID*** array)
 {
   *count = 0;
   *array = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNSSCertificate::GetHelperForLanguage(uint32_t language,
-                                       nsISupports** _retval)
+nsNSSCertificate::GetScriptableHelper(nsIXPCScriptable** _retval)
 {
   *_retval = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNSSCertificate::GetContractID(char** aContractID)
 {
--- a/security/manager/ssl/src/nsNSSCertificateFakeTransport.cpp
+++ b/security/manager/ssl/src/nsNSSCertificateFakeTransport.cpp
@@ -285,18 +285,17 @@ NS_IMETHODIMP
 nsNSSCertificateFakeTransport::GetInterfaces(uint32_t* count, nsIID*** array)
 {
   *count = 0;
   *array = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNSSCertificateFakeTransport::GetHelperForLanguage(uint32_t,
-                                                    nsISupports** _retval)
+nsNSSCertificateFakeTransport::GetScriptableHelper(nsIXPCScriptable** _retval)
 {
   *_retval = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNSSCertificateFakeTransport::GetContractID(char** aContractID)
 {
--- a/security/manager/ssl/src/nsSSLStatus.cpp
+++ b/security/manager/ssl/src/nsSSLStatus.cpp
@@ -209,17 +209,17 @@ NS_IMETHODIMP
 nsSSLStatus::GetInterfaces(uint32_t* aCount, nsIID*** aArray)
 {
   *aCount = 0;
   *aArray = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSSLStatus::GetHelperForLanguage(uint32_t aLanguage, nsISupports** aHelper)
+nsSSLStatus::GetScriptableHelper(nsIXPCScriptable** aHelper)
 {
   *aHelper = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSSLStatus::GetContractID(char** aContractID)
 {
--- a/services/common/observers.js
+++ b/services/common/observers.js
@@ -144,11 +144,11 @@ function Subject(object) {
   // as one of our wrappers to distinguish between subjects that are one of our
   // wrappers (which we should unwrap when notifying our observers) and those
   // that are real JS XPCOM components (which we should pass through unaltered).
   this.wrappedJSObject = { observersModuleSubjectWrapper: true, object: object };
 }
 
 Subject.prototype = {
   QueryInterface: XPCOMUtils.generateQI([]),
-  getHelperForLanguage: function() {},
+  getScriptableHelper: function() {},
   getInterfaces: function() {}
 };
--- a/storage/src/mozStorageAsyncStatement.cpp
+++ b/storage/src/mozStorageAsyncStatement.cpp
@@ -53,25 +53,20 @@ public:
 
   NS_IMETHODIMP
   GetInterfaces(uint32_t *_count, nsIID ***_array) override
   {
     return NS_CI_INTERFACE_GETTER_NAME(AsyncStatement)(_count, _array);
   }
 
   NS_IMETHODIMP
-  GetHelperForLanguage(uint32_t aLanguage, nsISupports **_helper) override
+  GetScriptableHelper(nsIXPCScriptable **_helper) override
   {
-    if (aLanguage == nsIProgrammingLanguage::JAVASCRIPT) {
-      static AsyncStatementJSHelper sJSHelper;
-      *_helper = &sJSHelper;
-      return NS_OK;
-    }
-
-    *_helper = nullptr;
+    static AsyncStatementJSHelper sJSHelper;
+    *_helper = &sJSHelper;
     return NS_OK;
   }
 
   NS_IMETHODIMP
   GetContractID(char **_contractID) override
   {
     *_contractID = nullptr;
     return NS_OK;
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -55,25 +55,20 @@ public:
 
   NS_IMETHODIMP
   GetInterfaces(uint32_t *_count, nsIID ***_array) override
   {
     return NS_CI_INTERFACE_GETTER_NAME(Statement)(_count, _array);
   }
 
   NS_IMETHODIMP
-  GetHelperForLanguage(uint32_t aLanguage, nsISupports **_helper) override
+  GetScriptableHelper(nsIXPCScriptable **_helper) override
   {
-    if (aLanguage == nsIProgrammingLanguage::JAVASCRIPT) {
-      static StatementJSHelper sJSHelper;
-      *_helper = &sJSHelper;
-      return NS_OK;
-    }
-
-    *_helper = nullptr;
+    static StatementJSHelper sJSHelper;
+    *_helper = &sJSHelper;
     return NS_OK;
   }
 
   NS_IMETHODIMP
   GetContractID(char **_contractID) override
   {
     *_contractID = nullptr;
     return NS_OK;
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -3433,115 +3433,277 @@
   "PLACES_MAINTENANCE_DAYSFROMLAST": {
     "expires_in_version" : "never",
     "kind": "exponential",
     "low": 7,
     "high": 60,
     "n_buckets" : 10,
     "description": "PLACES: Days from last maintenance"
   },
-  "UPDATER_BACKGROUND_CHECK_CODE_EXTERNAL": {
-    "expires_in_version": "default",
-    "kind": "enumerated",
-    "n_values": 50,
-    "description": "Updater: externally initiated (typically by the application) background update check result code (see PING_BGUC_* constants defined in /toolkit/mozapps/update/nsUpdateService.js)"
-  },
-  "UPDATER_BACKGROUND_CHECK_CODE_NOTIFY": {
-    "expires_in_version": "40",
+  "UPDATE_CHECK_NO_UPDATE_EXTERNAL" : {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of no updates were found for a background update check (externally initiated)"
+  },
+  "UPDATE_CHECK_NO_UPDATE_NOTIFY" : {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of no updates were found for a background update check (timer initiated)"
+  },
+  "UPDATE_CHECK_CODE_EXTERNAL": {
+    "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 50,
-    "description": "Updater: timer initiated background update check result code (see PING_BGUC_* constants defined in /toolkit/mozapps/update/nsUpdateService.js)"
-  },
-  "UPDATER_INVALID_LASTUPDATETIME_EXTERNAL": {
-    "expires_in_version": "40",
-    "kind": "boolean",
-    "description": "Updater: Whether the last update time is invalid when a background update check was externally requested (typically by the application)"
-  },
-  "UPDATER_INVALID_LASTUPDATETIME_NOTIFY": {
-    "expires_in_version": "40",
-    "kind": "boolean",
-    "description": "Updater: Whether the last update time is invalid when a background update check was timer initiated"
-  },
-  "UPDATER_LAST_NOTIFY_INTERVAL_DAYS_EXTERNAL": {
-    "expires_in_version": "40",
-    "kind": "exponential",
-    "n_buckets": 10,
-    "high": "60",
-    "description": "Updater: The interval in days between the previous and the current background update check when the check was externally requested (typically by the application)"
-  },
-  "UPDATER_LAST_NOTIFY_INTERVAL_DAYS_NOTIFY": {
-    "expires_in_version": "40",
-    "kind": "exponential",
-    "n_buckets": 10,
-    "high": "60",
-    "description": "Updater: The interval in days between the previous and the current background update check when the check was timer initiated"
-  },
-  "UPDATER_STATUS_CODES": {
+    "description": "Update: background update check result code except for no updates found (externally initiated)"
+  },
+  "UPDATE_CHECK_CODE_NOTIFY": {
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 50,
-    "description": "Updater: the status of the latest update performed"
-  },
-  "UPDATER_UPDATES_ENABLED": {
-    "expires_in_version": "default",
-    "kind": "boolean",
-    "description": "Updater: Whether or not updates are enabled"
-  },
-  "UPDATER_UPDATES_METRO_ENABLED": {
-    "expires_in_version": "default",
-    "kind": "boolean",
-    "description": "Updater: Whether or not Metro updates are enabled"
-  },
-  "UPDATER_UPDATES_AUTOMATIC": {
-    "expires_in_version": "40",
-    "kind": "boolean",
-    "description": "Updater: Whether or not updates are automatic"
-  },
-  "UPDATER_SERVICE_ENABLED": {
-    "expires_in_version": "default",
-    "kind": "boolean",
-    "description": "Updater: Whether or not the MozillaMaintenance service is enabled"
-  },
-  "UPDATER_SERVICE_ERROR_CODE": {
-    "expires_in_version": "default",
+    "description": "Update: background update check result code except for no updates found (timer initiated)"
+  },
+  "UPDATE_CHECK_EXTENDED_ERROR_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "keyed": true,
+    "description": "Update: keyed count (key names are prefixed with AUS_CHECK_EX_ERR_) of background update check extended error code (externally initiated)"
+  },
+  "UPDATE_CHECK_EXTENDED_ERROR_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "keyed": true,
+    "description": "Update: keyed count (key names are prefixed with AUS_CHECK_EX_ERR_) of background update check extended error code (timer initiated)"
+  },
+  "UPDATE_INVALID_LASTUPDATETIME_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of systems that have a last update time greater than the current time (externally initiated)"
+  },
+  "UPDATE_INVALID_LASTUPDATETIME_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of systems that have a last update time greater than the current time (timer initiated)"
+  },
+  "UPDATE_LAST_NOTIFY_INTERVAL_DAYS_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "n_buckets": 60,
+    "high": "365",
+    "description": "Update: interval in days since the last background update check (externally initiated)"
+  },
+  "UPDATE_LAST_NOTIFY_INTERVAL_DAYS_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "n_buckets": 30,
+    "high": "180",
+    "description": "Update: interval in days since the last background update check (timer initiated)"
+  },
+  "UPDATE_SERVICE_INSTALLED_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "boolean",
+    "description": "Update: whether the service is installed (externally initiated)"
+  },
+  "UPDATE_SERVICE_INSTALLED_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "boolean",
+    "description": "Update: whether the service is installed (timer initiated)"
+  },
+  "UPDATE_SERVICE_MANUALLY_UNINSTALLED_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of systems that manually uninstalled the service (externally initiated)"
+  },
+  "UPDATE_SERVICE_MANUALLY_UNINSTALLED_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of systems that manually uninstalled the service (timer initiated)"
+  },
+  "UPDATE_CANNOT_APPLY_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "boolean",
+    "description": "Update: systems that cannot apply updates (externally initiated)"
+  },
+  "UPDATE_CANNOT_APPLY_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "boolean",
+    "description": "Update: systems that cannot apply updates (timer initiated)"
+  },
+  "UPDATE_CANNOT_STAGE_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of systems that cannot stage updates (externally initiated)"
+  },
+  "UPDATE_CANNOT_STAGE_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of systems that cannot stage updates (timer initiated)"
+  },
+  "UPDATE_HAS_PREF_URL_OVERRIDE_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of systems that have an app.update.url.override preference (externally initiated)"
+  },
+  "UPDATE_HAS_PREF_URL_OVERRIDE_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of systems that have an app.update.url.override preference (timer initiated)"
+  },
+  "UPDATE_PREF_UPDATE_CANCELATIONS_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 100,
+    "description": "Update: number of sequential update elevation request cancelations greater than 0 (externally initiated)"
+  },
+  "UPDATE_PREF_UPDATE_CANCELATIONS_NOTIFY": {
+    "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 100,
-    "description": "Updater: 0=success else SERVICE_* error code defined in /toolkit/mozapps/update/common/errors.h"
-  },
-  "UPDATER_SERVICE_ERRORS": {
-    "expires_in_version": "default",
+    "description": "Update: number of sequential update elevation request cancelations greater than 0 (timer initiated)"
+  },
+  "UPDATE_PREF_SERVICE_ERRORS_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 30,
+    "description": "Update: number of sequential update service errors greater than 0 (externally initiated)"
+  },
+  "UPDATE_PREF_SERVICE_ERRORS_NOTIFY": {
+    "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 30,
-    "description": "Updater: The number of MozillaMaintenance service errors that have occurred"
-  },
-  "UPDATER_SERVICE_INSTALLED": {
-    "expires_in_version": "default",
-    "kind": "boolean",
-    "description": "Updater: Whether or not the MozillaMaintenance service is installed"
-  },
-  "UPDATER_SERVICE_MANUALLY_UNINSTALLED": {
-    "expires_in_version": "default",
-    "kind": "boolean",
-    "description": "Updater: Whether or not someone manually uninstalled the service."
-  },
-  "UPDATER_STAGE_ENABLED": {
-    "expires_in_version": "40",
-    "kind": "boolean",
-    "description": "Updater: Whether or not staging updates are enabled"
-  },
-  "UPDATER_HAS_PERMISSIONS": {
-    "expires_in_version": "40",
-    "kind": "boolean",
-    "description": "Updater: Whether or not the updater has permissions"
-  },
-  "UPDATER_WIZ_LAST_PAGE_CODE": {
-    "expires_in_version": "40",
-    "kind": "enumerated",
-    "n_values": 25,
-    "description": "Updater: The update wizard page displayed when the UI was closed (mapped in toolkit/mozapps/update/content/updates.js)"
+    "description": "Update: number of sequential update service errors greater than 0 (timer initiated)"
+  },
+  "UPDATE_NOT_PREF_UPDATE_AUTO_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of when the app.update.auto boolean preference is not the default value of true (true values are not submitted)"
+  },
+  "UPDATE_NOT_PREF_UPDATE_AUTO_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of when the app.update.auto boolean preference is not the default value of true (true values are not submitted)"
+  },
+  "UPDATE_NOT_PREF_UPDATE_ENABLED_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of when the app.update.enabled boolean preference is not the default value of true (true values are not submitted)"
+  },
+  "UPDATE_NOT_PREF_UPDATE_ENABLED_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of when the app.update.enabled boolean preference is not the default value of true (true values are not submitted)"
+  },
+  "UPDATE_NOT_PREF_UPDATE_STAGING_ENABLED_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of when the app.update.staging.enabled boolean preference is not the default value of true (true values are not submitted)"
+  },
+  "UPDATE_NOT_PREF_UPDATE_STAGING_ENABLED_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of when the app.update.staging.enabled boolean preference is not the default value of true (true values are not submitted)"
+  },
+  "UPDATE_NOT_PREF_UPDATE_SERVICE_ENABLED_EXTERNAL": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of when the app.update.service.enabled boolean preference is not the default value of true (true values are not submitted)"
+  },
+  "UPDATE_NOT_PREF_UPDATE_SERVICE_ENABLED_NOTIFY": {
+    "expires_in_version": "never",
+    "kind": "count",
+    "description": "Update: count of when the app.update.service.enabled boolean preference is not the default value of true (true values are not submitted)"
+  },
+  "UPDATE_DOWNLOAD_CODE_COMPLETE": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 50,
+    "description": "Update: complete patch download result code"
+  },
+  "UPDATE_DOWNLOAD_CODE_PARTIAL": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 50,
+    "description": "Update: complete patch download result code"
+  },
+  "UPDATE_STATE_CODE_COMPLETE_STARTUP": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 20,
+    "description": "Update: the state of a complete update from update.status on startup"
+  },
+  "UPDATE_STATE_CODE_PARTIAL_STARTUP": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 20,
+    "description": "Update: the state of a partial patch update from update.status on startup"
+  },
+  "UPDATE_STATE_CODE_UNKNOWN_STARTUP": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 20,
+    "description": "Update: the state of an unknown patch update from update.status on startup"
+  },
+  "UPDATE_STATE_CODE_COMPLETE_STAGE": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 20,
+    "description": "Update: the state of a complete patch update from update.status after staging"
+  },
+  "UPDATE_STATE_CODE_PARTIAL_STAGE": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 20,
+    "description": "Update: the state of a partial patch update from update.status after staging"
+  },
+  "UPDATE_STATE_CODE_UNKNOWN_STAGE": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 20,
+    "description": "Update: the state of an unknown patch update from update.status after staging"
+  },
+  "UPDATE_STATUS_ERROR_CODE_COMPLETE_STARTUP": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 100,
+    "description": "Update: the status error code for a failed complete patch update from update.status on startup"
+  },
+  "UPDATE_STATUS_ERROR_CODE_PARTIAL_STARTUP": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 100,
+    "description": "Update: the status error code for a failed partial patch update from update.status on startup"
+  },
+  "UPDATE_STATUS_ERROR_CODE_UNKNOWN_STARTUP": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 100,
+    "description": "Update: the status error code for a failed unknown patch update from update.status on startup"
+  },
+  "UPDATE_STATUS_ERROR_CODE_COMPLETE_STAGE": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 100,
+    "description": "Update: the status error code for a failed complete patch update from update.status after staging"
+  },
+  "UPDATE_STATUS_ERROR_CODE_PARTIAL_STAGE": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 100,
+    "description": "Update: the status error code for a failed partial patch update from update.status after staging"
+  },
+  "UPDATE_STATUS_ERROR_CODE_UNKNOWN_STAGE": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 100,
+    "description": "Update: the status error code for a failed unknown patch update from update.status after staging"
+  },
+  "UPDATE_WIZ_LAST_PAGE_CODE": {
+    "expires_in_version": "never",
+    "kind": "enumerated",
+    "n_values": 30,
+    "description": "Update: the update wizard page displayed when the UI was closed (mapped in toolkit/mozapps/update/UpdateTelemetry.jsm)"
   },
   "THUNDERBIRD_GLODA_SIZE_MB": {
     "expires_in_version": "40",
     "kind": "linear",
     "high": "1000",
     "n_buckets": 40,
     "description": "Gloda: size of global-messages-db.sqlite (MB)"
   },
--- a/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
+++ b/toolkit/modules/tests/xpcshell/test_GMPInstallManager.js
@@ -749,17 +749,17 @@ xhr.prototype = {
       }
     }
   },
   addEventListener: function(aEvent, aValue, aCapturing) {
     eval("this._on" + aEvent + " = aValue");
   },
   flags: Ci.nsIClassInfo.SINGLETON,
   implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
-  getHelperForLanguage: function(aLanguage) null,
+  getScriptableHelper: function() null,
   getInterfaces: function(aCount) {
     let interfaces = [Ci.nsISupports];
     aCount.value = interfaces.length;
     return interfaces;
   },
   classDescription: "XMLHttpRequest",
   contractID: "@mozilla.org/xmlextras/xmlhttprequest;1",
   classID: Components.ID("{c9b37f43-4278-4304-a5e0-600991ab08cb}"),
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/UpdateTelemetry.jsm
@@ -0,0 +1,520 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [
+  "AUSTLMY"
+];
+
+const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm", this);
+
+this.AUSTLMY = {
+  // Telemetry for the application update background update check occurs when
+  // the background update timer fires after the update interval which is
+  // determined by the app.update.interval preference and its telemetry
+  // histogram IDs have the suffix '_NOTIFY'.
+  // Telemetry for the externally initiated background update check occurs when
+  // a call is made to |checkForBackgroundUpdates| which is typically initiated
+  // by an application when it has determined that the application should have
+  // received an update. This has separate telemetry so it is possible to
+  // analyze using the telemetry data systems that have not been updating when
+  // they should have.
+
+  // The update check was performed by the call to checkForBackgroundUpdates in
+  // nsUpdateService.js.
+  EXTERNAL: "EXTERNAL",
+  // The update check was performed by the call to notify in nsUpdateService.js.
+  NOTIFY: "NOTIFY",
+
+  /**
+   * Values for the UPDATE_CHECK_CODE_NOTIFY and UPDATE_CHECK_CODE_EXTERNAL
+   * Telemetry histograms.
+   */
+  // No update found (no notification)
+  CHK_NO_UPDATE_FOUND: 0,
+  // No incompatible add-ons found during incompatible check (background download)
+  CHK_ADDON_NO_INCOMPAT: 1,
+  // Showing prompt due to the update.xml specifying showPrompt
+  // (update notification)
+  CHK_SHOWPROMPT_SNIPPET: 2,
+  // Showing prompt due to preference (update notification)
+  CHK_SHOWPROMPT_PREF: 3,
+  // Incompatible add-on check disabled by preference (background download)
+  CHK_ADDON_PREF_DISABLED: 4,
+  // Incompatible add-on checke not performed due to same app version as the
+  // update's app version (background download)
+  CHK_ADDON_SAME_APP_VER: 5,
+  // Incompatible add-ons found and all of them have updates (background download)
+  CHK_ADDON_UPDATES_FOR_INCOMPAT: 6,
+  // Incompatible add-ons found (update notification)
+  CHK_ADDON_HAVE_INCOMPAT: 7,
+  // Already has an active update in progress (no notification)
+  CHK_HAS_ACTIVEUPDATE: 8,
+  // A background download is already in progress (no notification)
+  CHK_IS_DOWNLOADING: 9,
+  // An update is already staged (no notification)
+  CHK_IS_STAGED: 10,
+  // An update is already downloaded (no notification)
+  CHK_IS_DOWNLOADED: 11,
+  // Background checks disabled by preference (no notification)
+  CHK_PREF_DISABLED: 12,
+  // Update checks disabled by admin locked preference (no notification)
+  CHK_ADMIN_DISABLED: 13,
+  // Unable to check for updates per hasUpdateMutex() (no notification)
+  CHK_NO_MUTEX: 14,
+  // Unable to check for updates per gCanCheckForUpdates (no notification). This
+  // should be covered by other codes and is recorded just in case.
+  CHK_UNABLE_TO_CHECK: 15,
+  // Background checks disabled for the current session (no notification)
+  CHK_DISABLED_FOR_SESSION: 16,
+  // Unable to perform a background check while offline (no notification)
+  CHK_OFFLINE: 17,
+  // No update found certificate check failed and threshold reached
+  // (possible mitm attack notification)
+  CHK_CERT_ATTR_NO_UPDATE_PROMPT: 18,
+  // No update found certificate check failed and threshold not reached
+  // (no notification)
+  CHK_CERT_ATTR_NO_UPDATE_SILENT: 19,
+  // Update found certificate check failed and threshold reached
+  // (possible mitm attack notification)
+  CHK_CERT_ATTR_WITH_UPDATE_PROMPT: 20,
+  // Update found certificate check failed and threshold not reached
+  // (no notification)
+  CHK_CERT_ATTR_WITH_UPDATE_SILENT: 21,
+  // General update check failure and threshold reached
+  // (check failure notification)
+  CHK_GENERAL_ERROR_PROMPT: 22,
+  // General update check failure and threshold not reached (no notification)
+  CHK_GENERAL_ERROR_SILENT: 23,
+  // No compatible update found though there were updates (no notification)
+  CHK_NO_COMPAT_UPDATE_FOUND: 24,
+  // Update found for a previous version (no notification)
+  CHK_UPDATE_PREVIOUS_VERSION: 25,
+  // Update found for a version with the never preference set (no notification)
+  CHK_UPDATE_NEVER_PREF: 26,
+  // Update found without a type attribute (no notification)
+  CHK_UPDATE_INVALID_TYPE: 27,
+  // The system is no longer supported (system unsupported notification)
+  CHK_UNSUPPORTED: 28,
+  // Unable to apply updates (manual install to update notification)
+  CHK_UNABLE_TO_APPLY: 29,
+  // Unable to check for updates due to no OS version (no notification)
+  CHK_NO_OS_VERSION: 30,
+  // Unable to check for updates due to no OS ABI (no notification)
+  CHK_NO_OS_ABI: 31,
+  // Invalid url for app.update.url default preference (no notification)
+  CHK_INVALID_DEFAULT_URL: 32,
+  // Invalid url for app.update.url user preference (no notification)
+  CHK_INVALID_USER_OVERRIDE_URL: 33,
+  // Invalid url for app.update.url.override user preference (no notification)
+  CHK_INVALID_DEFAULT_OVERRIDE_URL: 34,
+
+  /**
+   * Submit a telemetry ping for the update check result code or a telemetry
+   * ping for a count type histogram count when no update was found. The no
+   * update found ping is separate since it is the typical result, is less
+   * interesting than the other result codes, and it is easier to analyze the
+   * other codes without including it.
+   *
+   * @param  aSuffix
+   *         The histogram id suffix for histogram IDs:
+   *         UPDATE_CHECK_CODE_EXTERNAL
+   *         UPDATE_CHECK_CODE_NOTIFY
+   *         UPDATE_CHECK_NO_UPDATE_EXTERNAL
+   *         UPDATE_CHECK_NO_UPDATE_NOTIFY
+   * @param  aCode
+   *         An integer value as defined by the values that start with CHK_ in
+   *         the above section.
+   */
+  pingCheckCode: function UT_pingCheckCode(aSuffix, aCode) {
+    try {
+      if (aCode == this.CHK_NO_UPDATE_FOUND) {
+        let id = "UPDATE_CHECK_NO_UPDATE_" + aSuffix;
+        // count type histogram
+        Services.telemetry.getHistogramById(id).add();
+      } else {
+        let id = "UPDATE_CHECK_CODE_" + aSuffix;
+        // enumerated type histogram
+        Services.telemetry.getHistogramById(id).add(aCode);
+      }
+    } catch (e) {
+      Cu.reportError(e);
+    }
+  },
+
+  /**
+   * Submit a telemetry ping for a failed update check's unhandled error code
+   * when the pingCheckCode is CHK_GENERAL_ERROR_SILENT. The histogram is a
+   * keyed count type with key names that are prefixed with 'AUS_CHECK_EX_ERR_'.
+   *
+   * @param  aSuffix
+   *         The histogram id suffix for histogram IDs:
+   *         UPDATE_CHK_EXTENDED_ERROR_EXTERNAL
+   *         UPDATE_CHK_EXTENDED_ERROR_NOTIFY
+   * @param  aCode
+   *         The extended error value return by a failed update check.
+   */
+  pingCheckExError: function UT_pingCheckExError(aSuffix, aCode) {
+    try {
+      let id = "UPDATE_CHECK_EXTENDED_ERROR_" + aSuffix;
+      let val = "AUS_CHECK_EX_ERR_" + aCode;
+      // keyed count type histogram
+      Services.telemetry.getKeyedHistogramById(id).add(val);
+    } catch (e) {
+      Cu.reportError(e);
+    }
+  },
+
+  // The state code and if present the status error code were read on startup.
+  STARTUP: "STARTUP",
+  // The state code and status error code if present were read after staging.
+  STAGE: "STAGE",
+
+  // Patch type Complete
+  PATCH_COMPLETE: "COMPLETE",
+  // Patch type partial
+  PATCH_PARTIAL: "PARTIAL",
+  // Patch type unknown
+  PATCH_UNKNOWN: "UNKNOWN",
+
+  /**
+   * Values for the UPDATE_DOWNLOAD_CODE_COMPLETE and
+   * UPDATE_DOWNLOAD_CODE_PARTIAL Telemetry histograms.
+   */
+  DWNLD_SUCCESS: 0,
+  DWNLD_RETRY_OFFLINE: 1,
+  DWNLD_RETRY_NET_TIMEOUT: 2,
+  DWNLD_RETRY_CONNECTION_REFUSED: 3,
+  DWNLD_RETRY_NET_RESET: 4,
+  DWNLD_ERR_NO_UPDATE: 5,
+  DWNLD_ERR_NO_UPDATE_PATCH: 6,
+  DWNLD_ERR_NO_PATCH_FILE: 7,
+  DWNLD_ERR_PATCH_SIZE_LARGER: 8,
+  DWNLD_ERR_PATCH_SIZE_NOT_EQUAL: 9,
+  DWNLD_ERR_BINDING_ABORTED: 10,
+  DWNLD_ERR_ABORT: 11,
+  DWNLD_ERR_DOCUMENT_NOT_CACHED: 12,
+  DWNLD_ERR_VERIFY_NO_REQUEST: 13,
+  DWNLD_ERR_VERIFY_PATCH_SIZE_NOT_EQUAL: 14,
+  DWNLD_ERR_VERIFY_NO_HASH_MATCH: 15,
+
+  /**
+   * Submit a telemetry ping for the update download result code.
+   *
+   * @param  aIsComplete
+   *         If true the histogram is for a patch type complete, if false the
+   *         histogram is for a patch type partial, and when undefined the
+   *         histogram is for an unknown patch type. This is used to determine
+   *         the histogram ID out of the following histogram IDs:
+   *         UPDATE_DOWNLOAD_CODE_COMPLETE
+   *         UPDATE_DOWNLOAD_CODE_PARTIAL
+   * @param  aCode
+   *         An integer value as defined by the values that start with DWNLD_ in
+   *         the above section.
+   */
+  pingDownloadCode: function UT_pingDownloadCode(aIsComplete, aCode) {
+    let patchType = this.PATCH_UNKNOWN;
+    if (aIsComplete === true) {
+      patchType = this.PATCH_COMPLETE;
+    } else if (aIsComplete === false) {
+      patchType = this.PATCH_PARTIAL;
+    }
+    try {
+      let id = "UPDATE_DOWNLOAD_CODE_" + patchType;
+      // enumerated type histogram
+      Services.telemetry.getHistogramById(id).add(aCode);
+    } catch (e) {
+      Cu.reportError(e);
+    }
+  },
+
+  /**
+   * Submit a telemetry ping for the update status state code.
+   *
+   * @param  aSuffix
+   *         The histogram id suffix for histogram IDs:
+   *         UPDATE_STATE_CODE_COMPLETE_STARTUP
+   *         UPDATE_STATE_CODE_PARTIAL_STARTUP
+   *         UPDATE_STATE_CODE_UNKNOWN_STARTUP
+   *         UPDATE_STATE_CODE_COMPLETE_STAGE
+   *         UPDATE_STATE_CODE_PARTIAL_STAGE
+   *         UPDATE_STATE_CODE_UNKNOWN_STAGE
+   * @param  aCode
+   *         An integer value as defined by the values that start with STATE_ in
+   *         the above section for the update state from the update.status file.
+   */
+  pingStateCode: function UT_pingStateCode(aSuffix, aCode) {
+    try {
+      let id = "UPDATE_STATE_CODE_" + aSuffix;
+      // enumerated type histogram
+      Services.telemetry.getHistogramById(id).add(aCode);
+    } catch(e) {
+      Cu.reportError(e);
+    }
+  },
+
+  /**
+   * Submit a telemetry ping for the update status error code. This does not
+   * submit a success value which can be determined from the state code.
+   *
+   * @param  aSuffix
+   *         The histogram id suffix for histogram IDs:
+   *         UPDATE_STATUS_ERROR_CODE_COMPLETE_STARTUP
+   *         UPDATE_STATUS_ERROR_CODE_PARTIAL_STARTUP
+   *         UPDATE_STATUS_ERROR_CODE_UNKNOWN_STARTUP
+   *         UPDATE_STATUS_ERROR_CODE_COMPLETE_STAGE
+   *         UPDATE_STATUS_ERROR_CODE_PARTIAL_STAGE
+   *         UPDATE_STATUS_ERROR_CODE_UNKNOWN_STAGE
+   * @param  aCode
+   *         An integer value for the error code from the update.status file.
+   */
+  pingStatusErrorCode: function UT_pingStatusErrorCode(aSuffix, aCode) {
+    try {
+      let id = "UPDATE_STATUS_ERROR_CODE_" + aSuffix;
+      // enumerated type histogram
+      Services.telemetry.getHistogramById(id).add(aCode);
+    } catch(e) {
+      Cu.reportError(e);
+    }
+  },
+
+  /**
+   * Submit the interval in days since the last notification for this background
+   * update check or a boolean if the last notification is in the future.
+   *
+   * @param  aSuffix
+   *         The histogram id suffix for histogram IDs:
+   *         UPDATE_INVALID_LASTUPDATETIME_EXTERNAL
+   *         UPDATE_INVALID_LASTUPDATETIME_NOTIFY
+   *         UPDATE_LAST_NOTIFY_INTERVAL_DAYS_EXTERNAL
+   *         UPDATE_LAST_NOTIFY_INTERVAL_DAYS_NOTIFY
+   */
+  pingLastUpdateTime: function UT_pingLastUpdateTime(aSuffix) {
+    const PREF_APP_UPDATE_LASTUPDATETIME = "app.update.lastUpdateTime.background-update-timer";
+    if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_LASTUPDATETIME)) {
+      let lastUpdateTimeSeconds = Services.prefs.getIntPref(PREF_APP_UPDATE_LASTUPDATETIME);
+      if (lastUpdateTimeSeconds) {
+        let currentTimeSeconds = Math.round(Date.now() / 1000);
+        if (lastUpdateTimeSeconds > currentTimeSeconds) {
+          try {
+            let id = "UPDATE_INVALID_LASTUPDATETIME_" + aSuffix;
+            // count type histogram
+            Services.telemetry.getHistogramById().add();
+          } catch(e) {
+            Cu.reportError(e);
+          }
+        } else {
+          let intervalDays = (currentTimeSeconds - lastUpdateTimeSeconds) /
+                             (60 * 60 * 24);
+          try {
+            let id = "UPDATE_LAST_NOTIFY_INTERVAL_DAYS_" + aSuffix;
+            // exponential type histogram
+            Services.telemetry.getHistogramById(id).add(intervalDays);
+          } catch(e) {
+            Cu.reportError(e);
+          }
+        }
+      }
+    }
+  },
+
+  /**
+   * Submit a telemetry ping for the last page displayed by the update wizard.
+   *
+   * @param  aPageID
+   *         The page id for the last page displayed.
+   */
+  pingWizLastPageCode: function UT_pingWizLastPageCode(aPageID) {
+    let pageMap = { invalid: 0,
+                    dummy: 1,
+                    checking: 2,
+                    pluginupdatesfound: 3,
+                    noupdatesfound: 4,
+                    manualUpdate: 5,
+                    unsupported: 6,
+                    incompatibleCheck: 7,
+                    updatesfoundbasic: 8,
+                    updatesfoundbillboard: 9,
+                    license: 10,
+                    incompatibleList: 11,
+                    downloading: 12,
+                    errors: 13,
+                    errorextra: 14,
+                    errorpatching: 15,
+                    finished: 16,
+                    finishedBackground: 17,
+                    installed: 18 };
+    try {
+      let id = "UPDATE_WIZ_LAST_PAGE_CODE";
+      // enumerated type histogram
+      Services.telemetry.getHistogramById(id).add(pageMap[aPageID] ||
+                                                  pageMap.invalid);
+    } catch (e) {
+      Cu.reportError(e);
+    }
+  },
+
+  /**
+   * Submit a telemetry ping for a boolean type histogram that indicates if the
+   * service is installed and a telemetry ping for a boolean type histogram that
+   * indicates if the service was at some point installed and is now
+   * uninstalled.
+   * Note: the total for the following histogram IDs can be used to determine
+   *       the total number of telemetry timer and externally initiated
+   *       submissions for systems that build with MOZ_MAINTENANCE_SERVICE
+   *       defined:
+   *       UPDATE_SERVICE_INSTALLED_EXTERNAL
+   *       UPDATE_SERVICE_INSTALLED_NOTIFY
+   *
+   * @param  aSuffix
+   *         The histogram id suffix for histogram IDs:
+   *         UPDATE_SERVICE_INSTALLED_EXTERNAL
+   *         UPDATE_SERVICE_INSTALLED_NOTIFY
+   *         UPDATE_SERVICE_MANUALLY_UNINSTALLED_EXTERNAL
+   *         UPDATE_SERVICE_MANUALLY_UNINSTALLED_NOTIFY
+   * @param  aInstalled
+   *         Whether the service is installed.
+   */
+  pingServiceInstallStatus: function UT_PSIS(aSuffix, aInstalled) {
+    // Report the error but don't throw since it is more important to
+    // successfully update than to throw.
+    if (!("@mozilla.org/windows-registry-key;1" in Cc)) {
+      Cu.reportError(Cr.NS_ERROR_NOT_AVAILABLE);
+      return;
+    }
+
+    try {
+      let id = "UPDATE_SERVICE_INSTALLED_" + aSuffix;
+      // boolean type histogram
+      Services.telemetry.getHistogramById(id).add(aInstalled);
+    } catch(e) {
+      Cu.reportError(e);
+    }
+
+    let attempted = 0;
+    try {
+      let wrk = Cc["@mozilla.org/windows-registry-key;1"].
+                createInstance(Ci.nsIWindowsRegKey);
+      wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
+               "SOFTWARE\\Mozilla\\MaintenanceService",
+               wrk.ACCESS_READ | wrk.WOW64_64);
+      // Was the service at some point installed, but is now uninstalled?
+      attempted = wrk.readIntValue("Attempted");
+      wrk.close();
+    } catch(e) {
+      // Since this will throw if the registry key doesn't exist (e.g. the
+      // service has never been installed) don't report an error.
+    }
+
+    try {
+      let id = "UPDATE_SERVICE_MANUALLY_UNINSTALLED_" + aSuffix;
+      if (!aInstalled && attempted) {
+        // count type histogram
+        Services.telemetry.getHistogramById(id).add();
+      }
+    } catch(e) {
+      Cu.reportError(e);
+    }
+  },
+
+  /**
+   * Submit a telemetry ping for a count type histogram when the expected value
+   * does not equal the boolean value of a pref or if the pref isn't present
+   * when the expected value does not equal default value. This lessens the
+   * amount of data submitted to telemetry.
+   *
+   * @param  aID
+   *         The histogram ID to report to.
+   * @param  aPref
+   *         The preference to check.
+   * @param  aDefault
+   *         The default value when the preference isn't present.
+   * @param  aExpected (optional)
+   *         If specified and the value is the same as the value that will be
+   *         added the value won't be added to telemetry.
+   */
+  pingBoolPref: function UT_pingBoolPref(aID, aPref, aDefault, aExpected) {
+    try {
+      let val = aDefault;
+      if (Services.prefs.getPrefType(aPref) != Ci.nsIPrefBranch.PREF_INVALID) {
+        val = Services.prefs.getBoolPref(aPref);
+      }
+      if (val != aExpected) {
+        // count type histogram
+        Services.telemetry.getHistogramById(aID).add();
+      }
+    } catch(e) {
+      Cu.reportError(e);
+    }
+  },
+
+  /**
+   * Submit a telemetry ping for a histogram with the integer value of a
+   * preference when it is not the expected value or the default value when it
+   * is not the expected value. This lessens the amount of data submitted to
+   * telemetry.
+   *
+   * @param  aID
+   *         The histogram ID to report to.
+   * @param  aPref
+   *         The preference to check.
+   * @param  aDefault
+   *         The default value when the pref is not set.
+   * @param  aExpected (optional)
+   *         If specified and the value is the same as the value that will be
+   *         added the value won't be added to telemetry.
+   */
+  pingIntPref: function UT_pingIntPref(aID, aPref, aDefault, aExpected) {
+    try {
+      let val = aDefault;
+      if (Services.prefs.getPrefType(aPref) != Ci.nsIPrefBranch.PREF_INVALID) {
+        val = Services.prefs.getIntPref(aPref);
+      }
+      if (aExpected === undefined || val != aExpected) {
+        // enumerated or exponential type histogram
+        Services.telemetry.getHistogramById(aID).add(val);
+      }
+    } catch(e) {
+      Cu.reportError(e);
+    }
+  },
+
+  /**
+   * Submit a telemetry ping for all histogram types that take a single
+   * parameter to the telemetry add function and the count type histogram when
+   * the aExpected parameter is specified. If the aExpected parameter is
+   * specified and it equals the value specified by the aValue
+   * parameter the telemetry submission will be skipped.
+   * Note: the total for the following histogram IDs can be used to determine
+   *       the total number of telemetry timer and externally initiated
+   *       submissions:
+   *       UPDATE_CANNOT_APPLY_EXTERNAL
+   *       UPDATE_CANNOT_APPLY_NOTIFY
+   *
+   * @param  aID
+   *         The histogram ID to report to.
+   * @param  aValue
+   *         The value to add when aExpected is not defined or the value to
+   *         check if it is equal to when aExpected is defined.
+   * @param  aExpected (optional)
+   *         If specified and the value is the same as the value specified by
+   *         aValue parameter the submission will be skipped.
+   */
+  pingGeneric: function UT_pingGeneric(aID, aValue, aExpected) {
+    try {
+      if (aExpected === undefined) {
+        Services.telemetry.getHistogramById(aID).add(aValue);
+      } else if (aValue != aExpected) {
+        // count type histogram
+        Services.telemetry.getHistogramById(aID).add();
+      }
+    } catch(e) {
+      Cu.reportError(e);
+    }
+  }
+};
+Object.freeze(AUSTLMY);
deleted file mode 100644
--- a/toolkit/mozapps/update/UpdaterHealthProvider.jsm
+++ /dev/null
@@ -1,69 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [
-  "UpdateProvider",
-];
-
-const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-
-Cu.import("resource://gre/modules/Metrics.jsm", this);
-Cu.import("resource://gre/modules/Task.jsm", this);
-
-const DAILY_COUNTER_FIELD = {type: Metrics.Storage.FIELD_DAILY_COUNTER};
-const DAILY_DISCRETE_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_DISCRETE_NUMERIC};
-
-function UpdateMeasurement1() {
-  Metrics.Measurement.call(this);
-}
-
-UpdateMeasurement1.prototype = Object.freeze({
-  __proto__: Metrics.Measurement.prototype,
-
-  name: "update",
-  version: 1,
-
-  fields: {
-    updateCheckStartCount: DAILY_COUNTER_FIELD,
-    updateCheckSuccessCount: DAILY_COUNTER_FIELD,
-    updateCheckFailedCount: DAILY_COUNTER_FIELD,
-    updateCheckFailedStatuses: DAILY_DISCRETE_NUMERIC_FIELD,
-    completeUpdateStartCount: DAILY_COUNTER_FIELD,
-    partialUpdateStartCount: DAILY_COUNTER_FIELD,
-    completeUpdateSuccessCount: DAILY_COUNTER_FIELD,
-    partialUpdateSuccessCount: DAILY_COUNTER_FIELD,
-    updateFailedCount: DAILY_COUNTER_FIELD,
-    updateFailedStatuses: DAILY_DISCRETE_NUMERIC_FIELD,
-  },
-});
-
-this.UpdateProvider = function () {
-  Metrics.Provider.call(this);
-};
-UpdateProvider.prototype = Object.freeze({
-  __proto__: Metrics.Provider.prototype,
-
-  name: "org.mozilla.update",
-
-  measurementTypes: [
-    UpdateMeasurement1,
-  ],
-
-  recordUpdate: function (field, status) {
-    let m = this.getMeasurement(UpdateMeasurement1.prototype.name,
-                                UpdateMeasurement1.prototype.version);
-
-    return this.enqueueStorageOperation(function recordUpdateFields() {
-      return Task.spawn(function recordUpdateFieldsTask() {
-        yield m.incrementDailyCounter(field + "Count");
-
-        if ((field == "updateFailed" || field == "updateCheckFailed") && status) {
-          yield m.addDailyDiscreteNumeric(field + "Statuses", status);
-        }
-      }.bind(this));
-    }.bind(this));
-  },
-});
--- a/toolkit/mozapps/update/common/errors.h
+++ b/toolkit/mozapps/update/common/errors.h
@@ -4,19 +4,22 @@
  * 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 Errors_h__
 #define Errors_h__
 
 #define OK 0
 
-// Old unused error codes:
-// #define MEM_ERROR 1  // Replaced with errors 10-16 (inclusive)
-// #define IO_ERROR 2  // Use READ_ERROR or WRITE_ERROR instead
+// Error codes that are no longer used should not be used again unless they
+// aren't used in client code (e.g. nsUpdateService.js, updates.js,
+// UpdatePrompt.js, etc.).
+
+#define MAR_ERROR_EMPTY_ACTION_LIST 1
+#define LOADSOURCE_ERROR_WRONG_SIZE 2
 
 // Error codes 3-16 are for general update problems.
 #define USAGE_ERROR 3
 #define CRC_ERROR 4
 #define PARSE_ERROR 5
 #define READ_ERROR 6
 #define WRITE_ERROR 7
 // #define UNEXPECTED_ERROR 8 // Replaced with errors 38-42
@@ -34,47 +37,58 @@
 #define CERT_LOAD_ERROR 17
 #define CERT_HANDLING_ERROR 18
 #define CERT_VERIFY_ERROR 19
 #define ARCHIVE_NOT_OPEN 20
 #define COULD_NOT_READ_PRODUCT_INFO_BLOCK_ERROR 21
 #define MAR_CHANNEL_MISMATCH_ERROR 22
 #define VERSION_DOWNGRADE_ERROR 23
 
-// Error codes 24-34 are related to the maintenance service
-// and so are Windows only
+// Error codes 24-33 and 49 are for the Windows maintenance service.
 #define SERVICE_UPDATER_COULD_NOT_BE_STARTED 24
 #define SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS 25
 #define SERVICE_UPDATER_SIGN_ERROR 26
 #define SERVICE_UPDATER_COMPARE_ERROR 27
 #define SERVICE_UPDATER_IDENTITY_ERROR 28
 #define SERVICE_STILL_APPLYING_ON_SUCCESS 29
 #define SERVICE_STILL_APPLYING_ON_FAILURE 30
 #define SERVICE_UPDATER_NOT_FIXED_DRIVE 31
 #define SERVICE_COULD_NOT_LOCK_UPDATER 32
 #define SERVICE_INSTALLDIR_ERROR 33
-#define SERVICE_COULD_NOT_COPY_UPDATER 49
 
 #define NO_INSTALLDIR_ERROR 34
 #define WRITE_ERROR_ACCESS_DENIED 35
 // #define WRITE_ERROR_SHARING_VIOLATION 36 // Replaced with errors 46-48
 #define WRITE_ERROR_CALLBACK_APP 37
-#define INVALID_UPDATER_STATUS_CODE 38
 #define UNEXPECTED_BZIP_ERROR 39
 #define UNEXPECTED_MAR_ERROR 40
 #define UNEXPECTED_BSPATCH_ERROR 41
 #define UNEXPECTED_FILE_OPERATION_ERROR 42
 #define FILESYSTEM_MOUNT_READWRITE_ERROR 43
-#define FOTA_GENERAL_ERROR 44
-#define FOTA_UNKNOWN_ERROR 45
-#define WRITE_ERROR_SHARING_VIOLATION_SIGNALED 46
-#define WRITE_ERROR_SHARING_VIOLATION_NOPROCESSFORPID 47
-#define WRITE_ERROR_SHARING_VIOLATION_NOPID 48
+#define DELETE_ERROR_EXPECTED_DIR 46
+#define DELETE_ERROR_EXPECTED_FILE 47
+#define RENAME_ERROR_EXPECTED_FILE 48
+
+// Error codes 24-33 and 49 are for the Windows maintenance service.
+#define SERVICE_COULD_NOT_COPY_UPDATER 49
+
+#define WRITE_ERROR_FILE_COPY 61
+#define WRITE_ERROR_DELETE_FILE 62
+#define WRITE_ERROR_OPEN_PATCH_FILE 63
+#define WRITE_ERROR_PATCH_FILE 64
+#define WRITE_ERROR_APPLY_DIR_PATH 65
+#define WRITE_ERROR_CALLBACK_PATH 66
+#define WRITE_ERROR_FILE_ACCESS_DENIED 67
+#define WRITE_ERROR_DIR_ACCESS_DENIED 68
+#define WRITE_ERROR_DELETE_BACKUP 69
+#define WRITE_ERROR_EXTRACT 70
+
+// Error codes 80 through 99 are reserved for nsUpdateService.js
 
 // The following error codes are only used by updater.exe
-// when a fallback key exists and XPCShell tests are being run.
+// when a fallback key exists for tests.
 #define FALLBACKKEY_UNKNOWN_ERROR 100
 #define FALLBACKKEY_REGPATH_ERROR 101
 #define FALLBACKKEY_NOKEY_ERROR 102
 #define FALLBACKKEY_SERVICE_NO_STOP_ERROR 103
 #define FALLBACKKEY_LAUNCH_ERROR 104
 
 #endif  // Errors_h__
--- a/toolkit/mozapps/update/content/updates.js
+++ b/toolkit/mozapps/update/content/updates.js
@@ -1,41 +1,41 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
-Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
-Components.utils.import("resource://gre/modules/AddonManager.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-
 // Firefox's macBrowserOverlay.xul includes scripts that define Cc, Ci, and Cr
 // so we have to use different names.
-const CoC = Components.classes;
-const CoI = Components.interfaces;
-const CoR = Components.results;
+const {classes: CoC, interfaces: CoI, results: CoR, utils: CoU} = Components;
+
+CoU.import("resource://gre/modules/DownloadUtils.jsm", this);
+CoU.import("resource://gre/modules/AddonManager.jsm", this);
+CoU.import("resource://gre/modules/Services.jsm", this);
+CoU.import("resource://gre/modules/UpdateTelemetry.jsm", this);
 
 const XMLNS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const PREF_APP_UPDATE_BACKGROUNDERRORS    = "app.update.backgroundErrors";
 const PREF_APP_UPDATE_BILLBOARD_TEST_URL  = "app.update.billboard.test_url";
 const PREF_APP_UPDATE_CERT_ERRORS         = "app.update.cert.errors";
 const PREF_APP_UPDATE_ENABLED             = "app.update.enabled";
 const PREF_APP_UPDATE_LOG                 = "app.update.log";
-const PREF_APP_UPDATE_MANUAL_URL          = "app.update.url.manual";
-const PREF_APP_UPDATE_NEVER_BRANCH        = "app.update.never.";
 const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported";
 const PREF_APP_UPDATE_TEST_LOOP           = "app.update.test.loop";
-const PREF_PLUGINS_UPDATEURL              = "plugins.update.url";
+const PREF_APP_UPDATE_URL_MANUAL          = "app.update.url.manual";
+
+const PREFBRANCH_APP_UPDATE_NEVER         = "app.update.never.";
 
 const PREF_EM_HOTFIX_ID                   = "extensions.hotfix.id";
+const PREF_PLUGINS_UPDATE_URL             = "plugins.update.url";
 
-const UPDATE_TEST_LOOP_INTERVAL     = 2000;
+const UPDATE_TEST_LOOP_INTERVAL = 2000;
 
 const URI_UPDATES_PROPERTIES  = "chrome://mozapps/locale/update/updates.properties";
 
 const STATE_DOWNLOADING       = "downloading";
 const STATE_PENDING           = "pending";
 const STATE_PENDING_SVC       = "pending-service";
 const STATE_APPLYING          = "applying";
 const STATE_APPLIED           = "applied";
@@ -140,48 +140,22 @@ var gUpdates = {
 
   /**
    * Whether to run the unload handler. This will be set to false when the user
    * exits the wizard via onWizardCancel or onWizardFinish.
    */
   _runUnload: true,
 
   /**
-   * Submit the last page code when the wizard exited. The pageid is used to map
-   * to an integer instead of using the pageindex since pages can be added and
-   * removed which would change the page's pageindex.
-   * @param   pageID
+   * Submit on close telemtry values for the update wizard.
+   * @param  pageID
+   *         The page id for the last page displayed.
    */
-  _sendLastPageCodePing: function(pageID) {
-    var pageMap = { invalid: 0,
-                    dummy: 1,
-                    checking: 2,
-                    pluginupdatesfound: 3,
-                    noupdatesfound: 4,
-                    manualUpdate: 5,
-                    unsupported: 6,
-                    incompatibleCheck: 7,
-                    updatesfoundbasic: 8,
-                    updatesfoundbillboard: 9,
-                    license: 10,
-                    incompatibleList: 11,
-                    downloading: 12,
-                    errors: 13,
-                    errorextra: 14,
-                    errorpatching: 15,
-                    finished: 16,
-                    finishedBackground: 17,
-                    installed: 18 };
-    try {
-      Services.telemetry.getHistogramById("UPDATER_WIZ_LAST_PAGE_CODE").
-        add(pageMap[pageID] || pageMap.invalid);
-    }
-    catch (e) {
-      Components.utils.reportError(e);
-    }
+  _submitTelemetry: function(aPageID) {
+    AUSTLMY.pingWizLastPageCode(aPageID);
   },
 
   /**
    * Helper function for setButtons
    * Resets button to original label & accesskey if string is null.
    */
   _setButton: function(button, string) {
     if (string) {
@@ -264,17 +238,17 @@ var gUpdates = {
       return this.strings.getFormattedString(key, strings);
     return this.strings.getString(key);
   },
 
   never: function () {
     // If the user clicks "No Thanks", we should not prompt them to update to
     // this version again unless they manually select "Check for Updates..."
     // which will clear all of the "never" prefs.
-    var neverPrefName = PREF_APP_UPDATE_NEVER_BRANCH + this.update.appVersion;
+    var neverPrefName = PREFBRANCH_APP_UPDATE_NEVER + this.update.appVersion;
     Services.prefs.setBoolPref(neverPrefName, true);
   },
 
   /**
    * A hash of |pageid| attribute to page object. Can be used to dispatch
    * function calls to the appropriate page.
    */
   _pages: { },
@@ -283,29 +257,29 @@ var gUpdates = {
    * Called when the user presses the "Finish" button on the wizard, dispatches
    * the function call to the selected page.
    */
   onWizardFinish: function() {
     this._runUnload = false;
     var pageid = document.documentElement.currentPage.pageid;
     if ("onWizardFinish" in this._pages[pageid])
       this._pages[pageid].onWizardFinish();
-    this._sendLastPageCodePing(pageid);
+    this._submitTelemetry(pageid);
   },
 
   /**
    * Called when the user presses the "Cancel" button on the wizard, dispatches
    * the function call to the selected page.
    */
   onWizardCancel: function() {
     this._runUnload = false;
     var pageid = document.documentElement.currentPage.pageid;
     if ("onWizardCancel" in this._pages[pageid])
       this._pages[pageid].onWizardCancel();
-    this._sendLastPageCodePing(pageid);
+    this._submitTelemetry(pageid);
   },
 
   /**
    * Called when the user presses the "Next" button on the wizard, dispatches
    * the function call to the selected page.
    */
   onWizardNext: function() {
     var cp = document.documentElement.currentPage;
@@ -545,17 +519,17 @@ var gUpdates = {
       addons.forEach(function(addon) {
         // Protect against code that overrides the add-ons manager and doesn't
         // implement the isCompatibleWith or the findUpdates method.
         if (!("isCompatibleWith" in addon) || !("findUpdates" in addon)) {
           let errMsg = "Add-on doesn't implement either the isCompatibleWith " +
                        "or the findUpdates method!";
           if (addon.id)
             errMsg += " Add-on ID: " + addon.id;
-          Components.utils.reportError(errMsg);
+          CoU.reportError(errMsg);
           return;
         }
 
         // If an add-on isn't appDisabled and isn't userDisabled then it is
         // either active now or the user expects it to be active after the
         // restart. If that is the case and the add-on is not installed by the
         // application and is not compatible with the new application version
         // then the user should be warned that the add-on will become
@@ -569,17 +543,17 @@ var gUpdates = {
               !addon.appDisabled && !addon.userDisabled &&
               addon.scope != AddonManager.SCOPE_APPLICATION &&
               addon.isCompatible &&
               !addon.isCompatibleWith(self.update.appVersion,
                                       self.update.platformVersion))
             self.addons.push(addon);
         }
         catch (e) {
-          Components.utils.reportError(e);
+          CoU.reportError(e);
         }
       });
 
       aCallback(self.addons.length != 0);
     });
   },
 
   /**
@@ -622,17 +596,17 @@ var gCheckingPage = {
   onPageShow: function() {
     gUpdates.setButtons(null, null, null, false, true);
     gUpdates.wiz.getButton("cancel").focus();
 
     // Clear all of the "never" prefs to handle the scenario where the user
     // clicked "never" for an update, selected "Check for Updates...", and
     // then canceled.  If we don't clear the "never" prefs future
     // notifications will never happen.
-    Services.prefs.deleteBranch(PREF_APP_UPDATE_NEVER_BRANCH);
+    Services.prefs.deleteBranch(PREFBRANCH_APP_UPDATE_NEVER);
 
     // The user will be notified if there is an error so clear the background
     // check error count.
     if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS))
       Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDERRORS);
 
     // The preference will be set back to true if the system is still
     // unsupported.
@@ -733,28 +707,28 @@ var gCheckingPage = {
 /**
  * The "You have outdated plugins" page
  */
 var gPluginsPage = {
   /**
    * URL of the plugin updates page
    */
   _url: null,
-  
+
   /**
    * Initialize
    */
   onPageShow: function() {
     var prefs = Services.prefs;
-    if (prefs.getPrefType(PREF_PLUGINS_UPDATEURL) == prefs.PREF_INVALID) {
+    if (prefs.getPrefType(PREF_PLUGINS_UPDATE_URL) == prefs.PREF_INVALID) {
       gUpdates.wiz.goTo("noupdatesfound");
       return;
     }
-    
-    this._url = Services.urlFormatter.formatURLPref(PREF_PLUGINS_UPDATEURL);
+
+    this._url = Services.urlFormatter.formatURLPref(PREF_PLUGINS_UPDATE_URL);
     var link = document.getElementById("pluginupdateslink");
     link.setAttribute("href", this._url);
 
 
     var phs = CoC["@mozilla.org/plugin/host;1"].
                  getService(CoI.nsIPluginHost);
     var plugins = phs.getPluginTags();
     var blocklist = CoC["@mozilla.org/extensions/blocklist;1"].
@@ -771,17 +745,17 @@ var gPluginsPage = {
     if (!hasOutdated) {
       gUpdates.wiz.goTo("noupdatesfound");
       return;
     }
 
     gUpdates.setButtons(null, null, "okButton", true);
     gUpdates.wiz.getButton("finish").focus();
   },
-  
+
   /**
    * Finish button clicked.
    */
   onWizardFinish: function() {
     openURL(this._url);
   }
 };
 
@@ -903,17 +877,17 @@ var gIncompatibleCheckPage = {
 };
 
 /**
  * The "Unable to Update" page. Provides the user information about why they
  * were unable to update and a manual download url.
  */
 var gManualUpdatePage = {
   onPageShow: function() {
-    var manualURL = Services.urlFormatter.formatURLPref(PREF_APP_UPDATE_MANUAL_URL);
+    var manualURL = Services.urlFormatter.formatURLPref(PREF_APP_UPDATE_URL_MANUAL);
     var manualUpdateLinkLabel = document.getElementById("manualUpdateLinkLabel");
     manualUpdateLinkLabel.value = manualURL;
     manualUpdateLinkLabel.setAttribute("url", manualURL);
 
     gUpdates.setButtons(null, null, "okButton", true);
     gUpdates.wiz.getButton("finish").focus();
   }
 };
@@ -1706,17 +1680,17 @@ var gErrorsPage = {
     gUpdates.setButtons(null, null, "okButton", true);
     gUpdates.wiz.getButton("finish").focus();
 
     var statusText = gUpdates.update.statusText;
     LOG("gErrorsPage" , "onPageShow - update.statusText: " + statusText);
 
     var errorReason = document.getElementById("errorReason");
     errorReason.value = statusText;
-    var manualURL = Services.urlFormatter.formatURLPref(PREF_APP_UPDATE_MANUAL_URL);
+    var manualURL = Services.urlFormatter.formatURLPref(PREF_APP_UPDATE_URL_MANUAL);
     var errorLinkLabel = document.getElementById("errorLinkLabel");
     errorLinkLabel.value = manualURL;
     errorLinkLabel.setAttribute("url", manualURL);
   }
 };
 
 /**
  * The page shown when there is a background check or a certificate attribute
@@ -1745,17 +1719,17 @@ var gErrorExtraPage = {
     }
     else {
       if (gUpdates.update.errorCode == CERT_ATTR_CHECK_FAILED_NO_UPDATE){
         document.getElementById("errorCertCheckNoUpdateLabel").hidden = false;
         secHistogram.add(CoI.nsISecurityUITelemetry.WARNING_NO_SECURE_UPDATE);
       }
       else
         document.getElementById("genericBackgroundErrorLabel").hidden = false;
-      var manualURL = Services.urlFormatter.formatURLPref(PREF_APP_UPDATE_MANUAL_URL);
+      var manualURL = Services.urlFormatter.formatURLPref(PREF_APP_UPDATE_URL_MANUAL);
       var errorLinkLabel = document.getElementById("errorExtraLinkLabel");
       errorLinkLabel.value = manualURL;
       errorLinkLabel.setAttribute("url", manualURL);
       errorLinkLabel.hidden = false;
     }
   }
 };
 
@@ -1768,17 +1742,17 @@ var gErrorPatchingPage = {
    */
   onPageShow: function() {
     gUpdates.setButtons(null, null, "okButton", true);
   },
 
   onWizardNext: function() {
     switch (gUpdates.update.selectedPatch.state) {
       case STATE_PENDING:
-      case STATE_PENDING_SVC: 
+      case STATE_PENDING_SVC:
         gUpdates.wiz.goTo("finished");
         break;
       case STATE_DOWNLOADING:
         gUpdates.wiz.goTo("downloading");
         break;
       case STATE_DOWNLOAD_FAILED:
         gUpdates.wiz.goTo("errors");
         break;
--- a/toolkit/mozapps/update/moz.build
+++ b/toolkit/mozapps/update/moz.build
@@ -42,12 +42,12 @@ if CONFIG['MOZ_UPDATER']:
         'nsUpdateServiceStub.js',
     ]
 
     EXTRA_PP_COMPONENTS += [
         'nsUpdateService.js',
     ]
 
     EXTRA_JS_MODULES += [
-      'UpdaterHealthProvider.jsm'
+        'UpdateTelemetry.jsm',
     ]
 
 JAR_MANIFESTS += ['jar.mn']
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -2,50 +2,44 @@
 
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/FileUtils.jsm");
-Components.utils.import("resource://gre/modules/AddonManager.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
-Components.utils.import("resource://gre/modules/ctypes.jsm");
-#ifdef MOZ_SERVICES_HEALTHREPORT
-Components.utils.import("resource://gre/modules/UpdaterHealthProvider.jsm");
-#endif
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
+const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
+Cu.import("resource://gre/modules/FileUtils.jsm", this);
+Cu.import("resource://gre/modules/AddonManager.jsm", this);
+Cu.import("resource://gre/modules/Services.jsm", this);
+Cu.import("resource://gre/modules/ctypes.jsm", this);
+Cu.import("resource://gre/modules/UpdateTelemetry.jsm", this);
 
 const UPDATESERVICE_CID = Components.ID("{B3C290A6-3943-4B89-8BBE-C01EB7B3B311}");
 const UPDATESERVICE_CONTRACTID = "@mozilla.org/updates/update-service;1";
 
 const PREF_APP_UPDATE_ALTWINDOWTYPE       = "app.update.altwindowtype";
 const PREF_APP_UPDATE_AUTO                = "app.update.auto";
 const PREF_APP_UPDATE_BACKGROUND_INTERVAL = "app.update.download.backgroundInterval";
 const PREF_APP_UPDATE_BACKGROUNDERRORS    = "app.update.backgroundErrors";
 const PREF_APP_UPDATE_BACKGROUNDMAXERRORS = "app.update.backgroundMaxErrors";
+const PREF_APP_UPDATE_CANCELATIONS        = "app.update.cancelations";
 const PREF_APP_UPDATE_CERTS_BRANCH        = "app.update.certs.";
 const PREF_APP_UPDATE_CERT_CHECKATTRS     = "app.update.cert.checkAttributes";
 const PREF_APP_UPDATE_CERT_ERRORS         = "app.update.cert.errors";
 const PREF_APP_UPDATE_CERT_MAXERRORS      = "app.update.cert.maxErrors";
 const PREF_APP_UPDATE_CERT_REQUIREBUILTIN = "app.update.cert.requireBuiltIn";
 const PREF_APP_UPDATE_CUSTOM              = "app.update.custom";
 const PREF_APP_UPDATE_ENABLED             = "app.update.enabled";
-const PREF_APP_UPDATE_METRO_ENABLED       = "app.update.metro.enabled";
 const PREF_APP_UPDATE_IDLETIME            = "app.update.idletime";
 const PREF_APP_UPDATE_INCOMPATIBLE_MODE   = "app.update.incompatible.mode";
 const PREF_APP_UPDATE_INTERVAL            = "app.update.interval";
-const PREF_APP_UPDATE_LASTUPDATETIME      = "app.update.lastUpdateTime.background-update-timer";
 const PREF_APP_UPDATE_LOG                 = "app.update.log";
 const PREF_APP_UPDATE_MODE                = "app.update.mode";
 const PREF_APP_UPDATE_NEVER_BRANCH        = "app.update.never.";
 const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported";
 const PREF_APP_UPDATE_POSTUPDATE          = "app.update.postupdate";
 const PREF_APP_UPDATE_PROMPTWAITTIME      = "app.update.promptWaitTime";
 const PREF_APP_UPDATE_SHOW_INSTALLED_UI   = "app.update.showInstalledUI";
 const PREF_APP_UPDATE_SILENT              = "app.update.silent";
@@ -67,18 +61,16 @@ const PREF_APP_B2G_VERSION              
 const PREF_EM_HOTFIX_ID                   = "extensions.hotfix.id";
 
 const URI_UPDATE_PROMPT_DIALOG  = "chrome://mozapps/content/update/updates.xul";
 const URI_UPDATE_HISTORY_DIALOG = "chrome://mozapps/content/update/history.xul";
 const URI_BRAND_PROPERTIES      = "chrome://branding/locale/brand.properties";
 const URI_UPDATES_PROPERTIES    = "chrome://mozapps/locale/update/updates.properties";
 const URI_UPDATE_NS             = "http://www.mozilla.org/2005/app-update";
 
-const CATEGORY_UPDATE_TIMER               = "update-timer";
-
 const KEY_GRED            = "GreD";
 const KEY_UPDROOT         = "UpdRootD";
 const KEY_EXECUTABLE      = "XREExeF";
 
 #ifdef MOZ_WIDGET_GONK
 #define USE_UPDATE_ARCHIVE_DIR
 #endif
 
@@ -123,56 +115,88 @@ const STATE_PENDING_SVC     = "pending-s
 const STATE_APPLYING        = "applying";
 const STATE_APPLIED         = "applied";
 const STATE_APPLIED_OS      = "applied-os";
 const STATE_APPLIED_SVC     = "applied-service";
 const STATE_SUCCEEDED       = "succeeded";
 const STATE_DOWNLOAD_FAILED = "download-failed";
 const STATE_FAILED          = "failed";
 
-// From updater/errors.h:
-const WRITE_ERROR        = 7;
-// const UNEXPECTED_ERROR   = 8; // Replaced with errors 38-42
-const ELEVATION_CANCELED = 9;
-
-// Windows service specific errors
+// The values below used by this code are from common/errors.h
+const WRITE_ERROR                          = 7;
+const ELEVATION_CANCELED                   = 9;
 const SERVICE_UPDATER_COULD_NOT_BE_STARTED = 24;
 const SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS = 25;
 const SERVICE_UPDATER_SIGN_ERROR           = 26;
 const SERVICE_UPDATER_COMPARE_ERROR        = 27;
 const SERVICE_UPDATER_IDENTITY_ERROR       = 28;
 const SERVICE_STILL_APPLYING_ON_SUCCESS    = 29;
 const SERVICE_STILL_APPLYING_ON_FAILURE    = 30;
 const SERVICE_UPDATER_NOT_FIXED_DRIVE      = 31;
 const SERVICE_COULD_NOT_LOCK_UPDATER       = 32;
 const SERVICE_INSTALLDIR_ERROR             = 33;
+const WRITE_ERROR_ACCESS_DENIED            = 35;
+const WRITE_ERROR_CALLBACK_APP             = 37;
+const FILESYSTEM_MOUNT_READWRITE_ERROR     = 43;
 const SERVICE_COULD_NOT_COPY_UPDATER       = 49;
-
-const WRITE_ERROR_ACCESS_DENIED                     = 35;
-// const WRITE_ERROR_SHARING_VIOLATION                 = 36; // Replaced with errors 46-48
-const WRITE_ERROR_CALLBACK_APP                      = 37;
-const INVALID_UPDATER_STATUS_CODE                   = 38;
-const UNEXPECTED_BZIP_ERROR                         = 39;
-const UNEXPECTED_MAR_ERROR                          = 40;
-const UNEXPECTED_BSPATCH_ERROR                      = 41;
-const UNEXPECTED_FILE_OPERATION_ERROR               = 42;
-const FILESYSTEM_MOUNT_READWRITE_ERROR              = 43;
-const FOTA_GENERAL_ERROR                            = 44;
-const FOTA_UNKNOWN_ERROR                            = 45;
-const WRITE_ERROR_SHARING_VIOLATION_SIGNALED        = 46;
-const WRITE_ERROR_SHARING_VIOLATION_NOPROCESSFORPID = 47;
-const WRITE_ERROR_SHARING_VIOLATION_NOPID           = 48;
-const FOTA_FILE_OPERATION_ERROR                     = 49;
-const FOTA_RECOVERY_ERROR                           = 50;
-
+const WRITE_ERROR_FILE_COPY                = 61;
+const WRITE_ERROR_DELETE_FILE              = 62;
+const WRITE_ERROR_OPEN_PATCH_FILE          = 63;
+const WRITE_ERROR_PATCH_FILE               = 64;
+const WRITE_ERROR_APPLY_DIR_PATH           = 65;
+const WRITE_ERROR_CALLBACK_PATH            = 66;
+const WRITE_ERROR_FILE_ACCESS_DENIED       = 67;
+const WRITE_ERROR_DIR_ACCESS_DENIED        = 68;
+const WRITE_ERROR_DELETE_BACKUP            = 69;
+const WRITE_ERROR_EXTRACT                  = 70;
+
+// Array of write errors to simplify checks for write errors
+const WRITE_ERRORS = [WRITE_ERROR,
+                      WRITE_ERROR_ACCESS_DENIED,
+                      WRITE_ERROR_CALLBACK_APP,
+                      WRITE_ERROR_FILE_COPY,
+                      WRITE_ERROR_DELETE_FILE,
+                      WRITE_ERROR_OPEN_PATCH_FILE,
+                      WRITE_ERROR_PATCH_FILE,
+                      WRITE_ERROR_APPLY_DIR_PATH,
+                      WRITE_ERROR_CALLBACK_PATH,
+                      WRITE_ERROR_FILE_ACCESS_DENIED,
+                      WRITE_ERROR_DIR_ACCESS_DENIED,
+                      WRITE_ERROR_DELETE_BACKUP,
+                      WRITE_ERROR_EXTRACT];
+
+// Array of write errors to simplify checks for service errors
+const SERVICE_ERRORS = [SERVICE_UPDATER_COULD_NOT_BE_STARTED,
+                        SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS,
+                        SERVICE_UPDATER_SIGN_ERROR,
+                        SERVICE_UPDATER_COMPARE_ERROR,
+                        SERVICE_UPDATER_IDENTITY_ERROR,
+                        SERVICE_STILL_APPLYING_ON_SUCCESS,
+                        SERVICE_STILL_APPLYING_ON_FAILURE,
+                        SERVICE_UPDATER_NOT_FIXED_DRIVE,
+                        SERVICE_COULD_NOT_LOCK_UPDATER,
+                        SERVICE_INSTALLDIR_ERROR,
+                        SERVICE_COULD_NOT_COPY_UPDATER];
+
+// Error codes 80 through 99 are reserved for nsUpdateService.js and are not
+// defined in common/errors.h
+const FOTA_GENERAL_ERROR                   = 80;
+const FOTA_UNKNOWN_ERROR                   = 81;
+const FOTA_FILE_OPERATION_ERROR            = 82;
+const FOTA_RECOVERY_ERROR                  = 83;
+// Staging failed and changed the state to pending
+const STAGE_FAIL_FALLBACK                  = 97;
+const INVALID_UPDATER_STATE_CODE           = 98;
+const INVALID_UPDATER_STATUS_CODE          = 99;
+
+// Custom update error codes
 const CERT_ATTR_CHECK_FAILED_NO_UPDATE  = 100;
 const CERT_ATTR_CHECK_FAILED_HAS_UPDATE = 101;
 const BACKGROUNDCHECK_MULTIPLE_FAILURES = 110;
 const NETWORK_ERROR_OFFLINE             = 111;
-const FILE_ERROR_TOO_BIG                = 112;
 
 // Error codes should be < 1000. Errors above 1000 represent http status codes
 const HTTP_ERROR_OFFSET                 = 1000;
 
 const DOWNLOAD_CHUNK_SIZE           = 300000; // bytes
 const DOWNLOAD_BACKGROUND_INTERVAL  = 600;    // seconds
 const DOWNLOAD_FOREGROUND_INTERVAL  = 0;
 
@@ -184,100 +208,16 @@ const DEFAULT_SERVICE_MAX_ERRORS = 10;
 
 // The number of consecutive socket errors to allow before falling back to
 // downloading a different MAR file or failing if already downloading the full.
 const DEFAULT_SOCKET_MAX_ERRORS = 10;
 
 // The number of milliseconds to wait before retrying a connection error.
 const DEFAULT_UPDATE_RETRY_TIMEOUT = 2000;
 
-// A background download is in progress (no notification)
-const PING_BGUC_IS_DOWNLOADING               = 0;
-// An update is staged (no notification)
-const PING_BGUC_IS_STAGED                    = 1;
-// Invalid url for app.update.url default preference (no notification)
-const PING_BGUC_INVALID_DEFAULT_URL          = 2;
-// Invalid url for app.update.url user preference (no notification)
-const PING_BGUC_INVALID_CUSTOM_URL           = 3;
-// Invalid url for app.update.url.override user preference (no notification)
-const PING_BGUC_INVALID_OVERRIDE_URL         = 4;
-// Unable to check for updates per gCanCheckForUpdates and hasUpdateMutex()
-// (no notification)
-const PING_BGUC_UNABLE_TO_CHECK              = 5;
-// Already has an active update in progress (no notification)
-const PING_BGUC_HAS_ACTIVEUPDATE             = 6;
-// Background checks disabled by preference (no notification)
-const PING_BGUC_PREF_DISABLED                = 7;
-// Background checks disabled for the current session (no notification)
-const PING_BGUC_DISABLED_FOR_SESSION         = 8;
-// Background checks disabled in Metro (no notification)
-const PING_BGUC_METRO_DISABLED               = 9;
-// Unable to perform a background check while offline (no notification)
-const PING_BGUC_OFFLINE                      = 10;
-// No update found certificate check failed and threshold reached
-// (possible mitm attack notification)
-const PING_BGUC_CERT_ATTR_NO_UPDATE_NOTIFY   = 11;
-// No update found certificate check failed and threshold not reached
-// (no notification)
-const PING_BGUC_CERT_ATTR_NO_UPDATE_SILENT   = 12;
-// Update found certificate check failed and threshold reached
-// (possible mitm attack notification)
-const PING_BGUC_CERT_ATTR_WITH_UPDATE_NOTIFY = 13;
-// Update found certificate check failed and threshold not reached
-// (no notification)
-const PING_BGUC_CERT_ATTR_WITH_UPDATE_SILENT = 14;
-// General update check failure and threshold reached
-// (check failure notification)
-const PING_BGUC_GENERAL_ERROR_NOTIFY         = 15;
-// General update check failure and threshold not reached
-// (no notification)
-const PING_BGUC_GENERAL_ERROR_SILENT         = 16;
-// No update found (no notification)
-const PING_BGUC_NO_UPDATE_FOUND              = 17;
-// No compatible update found though there were updates (no notification)
-const PING_BGUC_NO_COMPAT_UPDATE_FOUND       = 18;
-// Update found for a previous version (no notification)
-const PING_BGUC_UPDATE_PREVIOUS_VERSION      = 19;
-// Update found for a version with the never preference set (no notification)
-const PING_BGUC_UPDATE_NEVER_PREF            = 20;
-// Update found without a type attribute (no notification)
-const PING_BGUC_UPDATE_INVALID_TYPE          = 21;
-// The system is no longer supported (system unsupported notification)
-const PING_BGUC_UNSUPPORTED                  = 22;
-// Unable to apply updates (manual install to update notification)
-const PING_BGUC_UNABLE_TO_APPLY              = 23;
-// Showing prompt due to the update.xml specifying showPrompt
-// (update notification)
-const PING_BGUC_SHOWPROMPT_SNIPPET           = 24;
-// Showing prompt due to preference (update notification)
-const PING_BGUC_SHOWPROMPT_PREF              = 25;
-// Incompatible add-on check disabled by preference (background download)
-const PING_BGUC_ADDON_PREF_DISABLED          = 26;
-// Incompatible add-on not checked not performed due to same update version and
-// app version (background download)
-const PING_BGUC_ADDON_SAME_APP_VER           = 27;
-// No incompatible add-ons found during incompatible check (background download)
-const PING_BGUC_CHECK_NO_INCOMPAT            = 28;
-// Incompatible add-ons found and all of them have updates (background download)
-const PING_BGUC_ADDON_UPDATES_FOR_INCOMPAT   = 29;
-// Incompatible add-ons found (update notification)
-const PING_BGUC_ADDON_HAVE_INCOMPAT          = 30;
-
-// Health report field names
-const UpdaterHealthReportFields = {
-  CHECK_START: "updateCheckStart",
-  CHECK_SUCCESS: "updateCheckSuccess",
-  CHECK_FAILED: "updateCheckFailed",
-  COMPLETE_START: "completeUpdateStart",
-  PARTIAL_START: "partialUpdateStart",
-  COMPLETE_SUCCESS: "completeUpdateSuccess",
-  PARTIAL_SUCCESS: "partialUpdateSuccess",
-  FAILED: "updateFailed"
-};
-
 var gLocale = null;
 var gUpdateMutexHandle = null;
 
 #ifdef MOZ_WIDGET_GONK
 var gSDCardMountLock = null;
 
 XPCOMUtils.defineLazyGetter(this, "gExtStorage", function aus_gExtStorage() {
     return Services.env.get("EXTERNAL_STORAGE");
@@ -565,45 +505,33 @@ function getPerInstallationMutexName(aGl
   return (aGlobal ? "Global\\" : "") + "MozillaUpdateMutex-" + hasher.finish(true);
 }
 #endif // XP_WIN
 
 /**
  * Whether or not the current instance has the update mutex. The update mutex
  * gives protection against 2 applications from the same installation updating:
  * 1) Running multiple profiles from the same installation path
- * 2) Running a Metro and Desktop application at the same time from the same
- *    path
- * 3) 2 applications running in 2 different user sessions from the same path
+ * 2) Two applications running in 2 different user sessions from the same path
  *
  * @return true if this instance holds the update mutex
  */
 function hasUpdateMutex() {
 #ifdef XP_WIN
   if (!gUpdateMutexHandle) {
     gUpdateMutexHandle = createMutex(getPerInstallationMutexName(true), false);
   }
 
   return !!gUpdateMutexHandle;
 #else
   return true;
 #endif // XP_WIN
 }
 
 XPCOMUtils.defineLazyGetter(this, "gCanApplyUpdates", function aus_gCanApplyUpdates() {
-  function submitHasPermissionsTelemetryPing(val) {
-    try {
-      let h = Services.telemetry.getHistogramById("UPDATER_HAS_PERMISSIONS");
-      h.add(+val);
-    } catch(e) {
-      // Don't allow any exception to be propagated.
-      Components.utils.reportError(e);
-    }
-  }
-
   let useService = false;
   if (shouldUseService() && isServiceInstalled()) {
     // No need to perform directory write checks, the maintenance service will
     // be able to write to all directories.
     LOG("gCanApplyUpdates - bypass the write checks because we'll use the service");
     useService = true;
   }
 
@@ -626,25 +554,25 @@ XPCOMUtils.defineLazyGetter(this, "gCanA
       var sysInfo = Cc["@mozilla.org/system-info;1"].
                     getService(Ci.nsIPropertyBag2);
 
       // Example windowsVersion:  Windows XP == 5.1
       var windowsVersion = sysInfo.getProperty("version");
       LOG("gCanApplyUpdates - windowsVersion = " + windowsVersion);
 
     /**
-  #    For Vista, updates can be performed to a location requiring admin
-  #    privileges by requesting elevation via the UAC prompt when launching
-  #    updater.exe if the appDir is under the Program Files directory
-  #    (e.g. C:\Program Files\) and UAC is turned on and  we can elevate
-  #    (e.g. user has a split token).
-  #
-  #    Note: this does note attempt to handle the case where UAC is turned on
-  #    and the installation directory is in a restricted location that
-  #    requires admin privileges to update other than Program Files.
+     * For Vista, updates can be performed to a location requiring admin
+     * privileges by requesting elevation via the UAC prompt when launching
+     * updater.exe if the appDir is under the Program Files directory
+     * (e.g. C:\Program Files\) and UAC is turned on and  we can elevate
+     * (e.g. user has a split token).
+     *
+     * Note: this does note attempt to handle the case where UAC is turned on
+     * and the installation directory is in a restricted location that
+     * requires admin privileges to update other than Program Files.
      */
       var userCanElevate = false;
 
       if (parseFloat(windowsVersion) >= 6) {
         try {
           var fileLocator = Cc["@mozilla.org/file/directory_service;1"].
                             getService(Ci.nsIProperties);
           // KEY_UPDROOT will fail and throw an exception if
@@ -659,57 +587,55 @@ XPCOMUtils.defineLazyGetter(this, "gCanA
           // When the installation directory is not under Program Files,
           // fall through to checking if write access to the
           // installation directory is available.
           LOG("gCanApplyUpdates - on Vista, appDir is not under Program Files");
         }
       }
 
       /**
-#      On Windows, we no longer store the update under the app dir.
-#
-#      If we are on Windows (including Vista, if we can't elevate) we need to
-#      to check that we can create and remove files from the actual app
-#      directory (like C:\Program Files\Mozilla Firefox).  If we can't
-#      (because this user is not an adminstrator, for example) canUpdate()
-#      should return false.
-#
-#      For Vista, we perform this check to enable updating the  application
-#      when the user has write access to the installation directory under the
-#      following scenarios:
-#      1) the installation directory is not under Program Files
-#         (e.g. C:\Program Files)
-#      2) UAC is turned off
-#      3) UAC is turned on and the user is not an admin
-#         (e.g. the user does not have a split token)
-#      4) UAC is turned on and the user is already elevated, so they can't be
-#         elevated again
+       * On Windows, we no longer store the update under the app dir.
+       *
+       * If we are on Windows (including Vista, if we can't elevate) we need to
+       * to check that we can create and remove files from the actual app
+       * directory (like C:\Program Files\Mozilla Firefox).  If we can't
+       * (because this user is not an adminstrator, for example) canUpdate()
+       * should return false.
+       *
+       * For Vista, we perform this check to enable updating the  application
+       * when the user has write access to the installation directory under the
+       * following scenarios:
+       * 1) the installation directory is not under Program Files
+       *    (e.g. C:\Program Files)
+       * 2) UAC is turned off
+       * 3) UAC is turned on and the user is not an admin
+       *    (e.g. the user does not have a split token)
+       * 4) UAC is turned on and the user is already elevated, so they can't be
+       *    elevated again
        */
       if (!userCanElevate) {
         // if we're unable to create the test file this will throw an exception.
         var appDirTestFile = getAppBaseDir();
         appDirTestFile.append(FILE_PERMS_TEST);
         LOG("gCanApplyUpdates - testing write access " + appDirTestFile.path);
         if (appDirTestFile.exists())
           appDirTestFile.remove(false)
         appDirTestFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
         appDirTestFile.remove(false);
       }
 #endif //XP_WIN
     }
     catch (e) {
        LOG("gCanApplyUpdates - unable to apply updates. Exception: " + e);
       // No write privileges to install directory
-      submitHasPermissionsTelemetryPing(false);
       return false;
     }
   } // if (!useService)
 
   LOG("gCanApplyUpdates - able to apply updates");
-  submitHasPermissionsTelemetryPing(true);
   return true;
 });
 
 /**
  * Whether or not the application can stage an update.
  *
  * @return true if updates can be staged.
  */
@@ -772,48 +698,27 @@ function getCanStageUpdates() {
 
     LOG("canStageUpdatesSession - able to stage updates");
     return true;
   });
 
   return canStageUpdatesSession;
 }
 
-XPCOMUtils.defineLazyGetter(this, "gMetroUpdatesEnabled", function aus_gMetroUpdatesEnabled() {
-#ifdef XP_WIN
-#ifdef MOZ_METRO
-  if (Services.metro && Services.metro.immersive) {
-    let metroUpdate = getPref("getBoolPref", PREF_APP_UPDATE_METRO_ENABLED, true);
-    if (!metroUpdate) {
-      LOG("gMetroUpdatesEnabled - unable to automatically check for metro " +
-          "updates, disabled by pref");
-      return false;
-    }
-  }
-#endif
-#endif
-
-  return true;
-});
-
 XPCOMUtils.defineLazyGetter(this, "gCanCheckForUpdates", function aus_gCanCheckForUpdates() {
   // If the administrator has disabled app update and locked the preference so
   // users can't check for updates. This preference check is ok in this lazy
   // getter since locked prefs don't change until the application is restarted.
   var enabled = getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true);
   if (!enabled && Services.prefs.prefIsLocked(PREF_APP_UPDATE_ENABLED)) {
     LOG("gCanCheckForUpdates - unable to automatically check for updates, " +
         "the preference is disabled and admistratively locked.");
     return false;
   }
 
-  if (!gMetroUpdatesEnabled) {
-    return false;
-  }
-
   // If we don't know the binary platform we're updating, we can't update.
   if (!gABI) {
     LOG("gCanCheckForUpdates - unable to check for updates, unknown ABI");
     return false;
   }
 
   // If we don't know the OS version we're updating, we can't update.
   if (!gOSVersion) {
@@ -960,47 +865,16 @@ function getStatusTextFromCode(code, def
     reason = gUpdateBundle.GetStringFromName("check_error-" + defaultCode);
     LOG("getStatusTextFromCode - transfer error: " + reason +
         ", default code: " + defaultCode);
   }
   return reason;
 }
 
 /**
- * Record count in the health report.
- * @param field
- *        The field name to record
- * @param status
- *        Status code for errors, 0 otherwise
- */
-function recordInHealthReport(field, status) {
-#ifdef MOZ_SERVICES_HEALTHREPORT
-  try {
-    LOG("recordInHealthReport - " + field + " - " + status);
-
-    let reporter = Cc["@mozilla.org/datareporting/service;1"]
-                      .getService().wrappedJSObject.healthReporter;
-
-    if (reporter) {
-      reporter.onInit().then(function recordUpdateInHealthReport() {
-        try {
-          reporter.getProvider("org.mozilla.update").recordUpdate(field, status);
-        } catch (ex) {
-          Cu.reportError(ex);
-        }
-      });
-    }
-  // If getting the heath reporter service fails, don't fail updating.
-  } catch (ex) {
-    LOG("recordInHealthReport - could not initialize health reporter");
-  }
-#endif
-}
-
-/**
  * Get the Active Updates directory
  * @return The active updates directory, as a nsIFile object
  */
 function getUpdatesDir() {
   // Right now, we only support downloading one patch at a time, so we always
   // use the same target directory.
   return getUpdateDirCreate([DIR_UPDATES, "0"]);
 }
@@ -1481,47 +1355,39 @@ function handleUpdateFailure(update, err
     Cc["@mozilla.org/updates/update-prompt;1"].
       createInstance(Ci.nsIUpdatePrompt).
       showUpdateError(update);
     writeStatusFile(getUpdatesDir(), STATE_FAILED + ": " + errorCode);
     cleanupActiveUpdate();
     return true;
   }
 
-  if (update.errorCode == WRITE_ERROR ||
-      update.errorCode == WRITE_ERROR_ACCESS_DENIED ||
-      update.errorCode == WRITE_ERROR_SHARING_VIOLATION_SIGNALED ||
-      update.errorCode == WRITE_ERROR_SHARING_VIOLATION_NOPROCESSFORPID ||
-      update.errorCode == WRITE_ERROR_SHARING_VIOLATION_NOPID ||
-      update.errorCode == WRITE_ERROR_CALLBACK_APP ||
+  // Replace with Array.prototype.includes when it has stabilized.
+  if (WRITE_ERRORS.indexOf(update.errorCode) != -1 ||
       update.errorCode == FILESYSTEM_MOUNT_READWRITE_ERROR) {
     Cc["@mozilla.org/updates/update-prompt;1"].
       createInstance(Ci.nsIUpdatePrompt).
       showUpdateError(update);
     writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
     return true;
   }
 
   if (update.errorCode == ELEVATION_CANCELED) {
     writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
+    let cancelations = getPref("getIntPref", PREF_APP_UPDATE_CANCELATIONS, 0);
+    cancelations++;
+    Services.prefs.setIntPref(PREF_APP_UPDATE_CANCELATIONS, cancelations);
     return true;
   }
-
-  if (update.errorCode == SERVICE_UPDATER_COULD_NOT_BE_STARTED ||
-      update.errorCode == SERVICE_NOT_ENOUGH_COMMAND_LINE_ARGS ||
-      update.errorCode == SERVICE_UPDATER_SIGN_ERROR ||
-      update.errorCode == SERVICE_UPDATER_COMPARE_ERROR ||
-      update.errorCode == SERVICE_UPDATER_IDENTITY_ERROR ||
-      update.errorCode == SERVICE_STILL_APPLYING_ON_SUCCESS ||
-      update.errorCode == SERVICE_STILL_APPLYING_ON_FAILURE ||
-      update.errorCode == SERVICE_UPDATER_NOT_FIXED_DRIVE ||
-      update.errorCode == SERVICE_COULD_NOT_LOCK_UPDATER ||
-      update.errorCode == SERVICE_COULD_NOT_COPY_UPDATER ||
-      update.errorCode == SERVICE_INSTALLDIR_ERROR) {
-
+  if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SERVICE_ERRORS)) {
+    Services.prefs.clearUserPref(PREF_APP_UPDATE_SERVICE_ERRORS);
+  }
+
+  // Replace with Array.prototype.includes when it has stabilized.
+  if (SERVICE_ERRORS.indexOf(update.errorCode) != -1) {
     var failCount = getPref("getIntPref",
                             PREF_APP_UPDATE_SERVICE_ERRORS, 0);
     var maxFail = getPref("getIntPref",
                           PREF_APP_UPDATE_SERVICE_MAX_ERRORS,
                           DEFAULT_SERVICE_MAX_ERRORS);
 
     // As a safety, when the service reaches maximum failures, it will
     // disable itself and fallback to using the normal update mechanism
@@ -1531,32 +1397,18 @@ function handleUpdateFailure(update, err
       Services.prefs.clearUserPref(PREF_APP_UPDATE_SERVICE_ERRORS);
     } else {
       failCount++;
       Services.prefs.setIntPref(PREF_APP_UPDATE_SERVICE_ERRORS,
                                 failCount);
     }
 
     writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
-    try {
-      Services.telemetry.getHistogramById("UPDATER_SERVICE_ERROR_CODE").
-        add(update.errorCode);
-    }
-    catch (e) {
-      Cu.reportError(e);
-    }
     return true;
   }
-
-  try {
-    Services.telemetry.getHistogramById("UPDATER_SERVICE_ERROR_CODE").add(0);
-  }
-  catch (e) {
-    Cu.reportError(e);
-  }
   return false;
 }
 
 /**
  * Fall back to downloading a complete update in case an update has failed.
  *
  * @param update the update object that has failed to apply.
  * @param postStaging true if we have just attempted to stage an update.
@@ -1581,16 +1433,81 @@ function handleFallbackToCompleteUpdate(
   else {
     LOG("handleFallbackToCompleteUpdate - install of complete or " +
         "only one patch offered failed.");
   }
   update.QueryInterface(Ci.nsIWritablePropertyBag);
   update.setProperty("patchingFailed", oldType);
 }
 
+function pingStateAndStatusCodes(aUpdate, aStartup, aStatus) {
+  let patchType = AUSTLMY.PATCH_UNKNOWN;
+  if (aUpdate && aUpdate.selectedPatch && aUpdate.selectedPatch.type) {
+    if (aUpdate.selectedPatch.type == "complete") {
+      patchType = AUSTLMY.PATCH_COMPLETE;
+    } else if (aUpdate.selectedPatch.type == "partial") {
+      patchType = AUSTLMY.PATCH_PARTIAL;
+    }
+  }
+
+  let suffix = patchType + "_" + (aStartup ? AUSTLMY.STARTUP : AUSTLMY.STAGE);
+  let stateCode = 0;
+  let parts = aStatus.split(":");
+  if (parts.length > 0) {
+    switch (parts[0]) {
+      case STATE_NONE:
+        stateCode = 2;
+        break;
+      case STATE_DOWNLOADING:
+        stateCode = 3;
+        break;
+      case STATE_PENDING:
+        stateCode = 4;
+        parts[0] = STATE_FAILED;
+        parts.push(STAGE_FAIL_FALLBACK);
+        break;
+      case STATE_PENDING_SVC:
+        stateCode = 5;
+        break;
+      case STATE_APPLYING:
+        stateCode = 6;
+        break;
+      case STATE_APPLIED:
+        stateCode = 7;
+        break;
+      case STATE_APPLIED_OS:
+        stateCode = 8;
+        break;
+      case STATE_APPLIED_SVC:
+        stateCode = 9;
+        break;
+      case STATE_SUCCEEDED:
+        stateCode = 10;
+        break;
+      case STATE_DOWNLOAD_FAILED:
+        stateCode = 11;
+        break;
+      case STATE_FAILED:
+        stateCode = 12;
+        break;
+      default:
+        stateCode = 1;
+    }
+
+    if (parts.length > 1) {
+      let statusErrorCode = INVALID_UPDATER_STATE_CODE;
+      if (parts[0] == STATE_FAILED) {
+        statusErrorCode = parseInt(parts[1]) || INVALID_UPDATER_STATUS_CODE;
+      }
+      AUSTLMY.pingStatusErrorCode(suffix, statusErrorCode);
+    }
+  }
+  AUSTLMY.pingStateCode(suffix, stateCode);
+}
+
 /**
  * Update Patch
  * @param   patch
  *          A <patch> element to initialize this object with
  * @throws if patch has a size of 0
  * @constructor
  */
 function UpdatePatch(patch) {
@@ -2161,53 +2078,44 @@ UpdateService.prototype = {
 
   /**
    * Perform post-processing on updates lingering in the updates directory
    * from a previous application session - either report install failures (and
    * optionally attempt to fetch a different version if appropriate) or
    * notify the user of install success.
    */
   _postUpdateProcessing: function AUS__postUpdateProcessing() {
-    // canCheckForUpdates will return false when metro-only updates are disabled
-    // from within metro.  In that case we still want _postUpdateProcessing to
-    // run.  gMetroUpdatesEnabled returns true on non Windows 8 platforms.
-    // We want _postUpdateProcessing to run so that it will update the history
-    // XML. Without updating the history XML, the about flyout will continue to
-    // have the "Restart to Apply Update" button (history xml indicates update
-    // is applied).
-    // TODO: I think this whole if-block should be removed since updates can
-    // always be applied via the about dialog, we should be running post update
-    // in those cases.
-    if (!this.canCheckForUpdates && gMetroUpdatesEnabled) {
+    if (!this.canCheckForUpdates) {
       LOG("UpdateService:_postUpdateProcessing - unable to check for " +
           "updates... returning early");
       return;
     }
 
     if (!this.canApplyUpdates) {
       LOG("UpdateService:_postUpdateProcessing - unable to apply " +
           "updates... returning early");
       // If the update is present in the update directly somehow,
       // it would prevent us from notifying the user of futher updates.
       cleanupActiveUpdate();
       return;
     }
 
+    var um = Cc["@mozilla.org/updates/update-manager;1"].
+             getService(Ci.nsIUpdateManager);
+    var update = um.activeUpdate;
     var status = readStatusFile(getUpdatesDir());
-    // STATE_NONE status means that the update.status file is present but a
-    // background download error occurred.
+    pingStateAndStatusCodes(update, true, status);
+    // STATE_NONE status typically means that the update.status file is present
+    // but a background download error occurred.
     if (status == STATE_NONE) {
       LOG("UpdateService:_postUpdateProcessing - no status, no update");
       cleanupActiveUpdate();
       return;
     }
 
-    var um = Cc["@mozilla.org/updates/update-manager;1"].
-             getService(Ci.nsIUpdateManager);
-
 #ifdef MOZ_WIDGET_GONK
     // This code is called very early in the boot process, before we've even
     // had a chance to setup the UI so we can give feedback to the user.
     //
     // Since the download may be occuring over a link which has associated
     // cost, we want to require user-consent before resuming the download.
     // Also, applying an already downloaded update now is undesireable,
     // since the phone will look dead while the update is being applied.
@@ -2215,18 +2123,16 @@ UpdateService.prototype = {
     // the UI is initialized so it is possible to give feedback to and get
     // consent to update from the user.
     if (isInterruptedUpdate(status)) {
       LOG("UpdateService:_postUpdateProcessing - interrupted update detected - wait for user consent");
       return;
     }
 #endif
 
-    var update = um.activeUpdate;
-
     if (status == STATE_DOWNLOADING) {
       LOG("UpdateService:_postUpdateProcessing - patch found in downloading " +
           "state");
       if (update && update.state != STATE_SUCCEEDED) {
         // Resume download
         var status = this.downloadUpdate(update, true);
         if (status == STATE_NONE)
           cleanupActiveUpdate();
@@ -2300,17 +2206,16 @@ UpdateService.prototype = {
       }
       update = new Update(null);
     }
 
     var prompter = Cc["@mozilla.org/updates/update-prompt;1"].
                    createInstance(Ci.nsIUpdatePrompt);
 
     update.state = status;
-    this._sendStatusCodeTelemetryPing(status);
 
     if (status == STATE_SUCCEEDED) {
       update.statusText = gUpdateBundle.GetStringFromName("installSuccess");
 
       // Update the patch's metadata.
       um.activeUpdate = update;
       Services.prefs.setBoolPref(PREF_APP_UPDATE_POSTUPDATE, true);
       prompter.showUpdateInstalled();
@@ -2342,177 +2247,16 @@ UpdateService.prototype = {
     }
 
     // Now trash the MozUpdater directory created when replacing an install with
     // a staged update.
     cleanUpMozUpdaterDirs();
   },
 
   /**
-   * Submit a telemetry ping with the boolean value of a pref for a histogram
-   *
-   * @param  pref
-   *         The preference to report
-   * @param  histogram
-   *         The histogram ID to report to
-   */
-  _sendBoolPrefTelemetryPing: function AUS__boolTelemetryPing(pref, histogram) {
-    try {
-      // The getPref is already wrapped in a try/catch but we never
-      // want telemetry pings breaking app update so we just put it
-      // inside the try to be safe.
-      let val = getPref("getBoolPref", pref, false);
-      Services.telemetry.getHistogramById(histogram).add(+val);
-    } catch(e) {
-      // Don't allow any exception to be propagated.
-      Cu.reportError(e);
-    }
-  },
-
-#ifdef XP_WIN
-  /**
-   * Submit a telemetry ping with a boolean value which indicates if the service
-   * is installed.
-   * Also submits a telemetry ping with a boolean value which indicates if the
-   * service was at some point installed, but is now uninstalled.
-   */
-  _sendServiceInstalledTelemetryPing: function AUS__svcInstallTelemetryPing() {
-    let installed = isServiceInstalled(); // Is the service installed?
-    let attempted = 0;
-    try {
-      let wrk = Cc["@mozilla.org/windows-registry-key;1"].
-                createInstance(Ci.nsIWindowsRegKey);
-      wrk.open(wrk.ROOT_KEY_LOCAL_MACHINE,
-               "SOFTWARE\\Mozilla\\MaintenanceService",
-               wrk.ACCESS_READ | wrk.WOW64_64);
-      // Was the service at some point installed, but is now uninstalled?
-      attempted = wrk.readIntValue("Attempted");
-      wrk.close();
-    } catch(e) {
-    }
-    try {
-      let h = Services.telemetry.getHistogramById("UPDATER_SERVICE_INSTALLED");
-      h.add(Number(installed));
-    } catch(e) {
-      // Don't allow any exception to be propagated.
-      Cu.reportError(e);
-    }
-    try {
-      let h = Services.telemetry.getHistogramById("UPDATER_SERVICE_MANUALLY_UNINSTALLED");
-      h.add(!installed && attempted ? 1 : 0);
-    } catch(e) {
-      // Don't allow any exception to be propagated.
-      Cu.reportError(e);
-    }
-  },
-#endif
-
-  /**
-   * Submit a telemetry ping with the int value of a pref for a histogram
-   *
-   * @param  pref
-   *         The preference to report
-   * @param histogram
-   *         The histogram ID to report to
-   */
-  _sendIntPrefTelemetryPing: function AUS__intTelemetryPing(pref, histogram) {
-    try {
-      // The getPref is already wrapped in a try/catch but we never
-      // want telemetry pings breaking app update so we just put it
-      // inside the try to be safe.
-      let val = getPref("getIntPref", pref, 0);
-      Services.telemetry.getHistogramById(histogram).add(val);
-    } catch(e) {
-      // Don't allow any exception to be propagated.
-      Cu.reportError(e);
-    }
-  },
-
-
-  /**
-   * Submit the results of applying the update via telemetry.
-   *
-   * @param  status
-   *         The status of the update as read from the update.status file
-   */
-  _sendStatusCodeTelemetryPing: function AUS__statusTelemetryPing(status) {
-    try {
-      let parts = status.split(":");
-      if ((parts.length == 1 && status != STATE_SUCCEEDED) ||
-          (parts.length > 1  && parts[0] != STATE_FAILED)) {
-        // Should also report STATE_DOWNLOAD_FAILED
-        return;
-      }
-      let result = 0; // 0 means success
-      if (parts.length > 1) {
-        result = parseInt(parts[1]) || INVALID_UPDATER_STATUS_CODE;
-      }
-      Services.telemetry.getHistogramById("UPDATER_STATUS_CODES").add(result);
-    } catch(e) {
-      // Don't allow any exception to be propagated.
-      Cu.reportError(e);
-    }
-  },
-
-  /**
-   * Submit the interval in days since the last notification for this background
-   * update check.
-   */
-  _sendLastNotifyIntervalPing: function AUS__notifyIntervalPing() {
-    if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_LASTUPDATETIME)) {
-      let idSuffix = this._isNotify ? "NOTIFY" : "EXTERNAL";
-      let lastUpdateTimeSeconds = getPref("getIntPref",
-                                          PREF_APP_UPDATE_LASTUPDATETIME, 0);
-      if (lastUpdateTimeSeconds) {
-        let currentTimeSeconds = Math.round(Date.now() / 1000);
-        if (lastUpdateTimeSeconds > currentTimeSeconds) {
-          try {
-            Services.telemetry.
-              getHistogramById("UPDATER_INVALID_LASTUPDATETIME_" + idSuffix).
-              add(1);
-          } catch(e) {
-            Cu.reportError(e);
-          }
-        }
-        else {
-          let intervalDays = (currentTimeSeconds - lastUpdateTimeSeconds) /
-                             (60 * 60 * 24);
-          try {
-            Services.telemetry.
-              getHistogramById("UPDATER_INVALID_LASTUPDATETIME_" + idSuffix).
-              add(0);
-            Services.telemetry.
-              getHistogramById("UPDATER_LAST_NOTIFY_INTERVAL_DAYS_" + idSuffix).
-              add(intervalDays);
-          } catch(e) {
-            Cu.reportError(e);
-          }
-        }
-      }
-    }
-  },
-
-  /**
-   * Submit the result for the background update check.
-   *
-   * @param  code
-   *         An integer value as defined by the PING_BGUC_* constants.
-   */
-  _backgroundUpdateCheckCodePing: function AUS__backgroundUpdateCheckCodePing(code) {
-    try {
-      let idSuffix = this._isNotify ? "NOTIFY" : "EXTERNAL";
-      Services.telemetry.
-        getHistogramById("UPDATER_BACKGROUND_CHECK_CODE_" + idSuffix).add(code);
-    }
-    catch (e) {
-      Cu.reportError(e);
-    }
-  },
-
-  /**
    * Register an observer when the network comes online, so we can short-circuit
    * the app.update.interval when there isn't connectivity
    */
   _registerOnlineObserver: function AUS__registerOnlineObserver() {
     if (this._registeredOnlineObserver) {
       LOG("UpdateService:_registerOnlineObserver - observer already registered");
       return;
     }
@@ -2550,66 +2294,68 @@ UpdateService.prototype = {
     LOG("UpdateService:onError - error during background update. error code: " +
         update.errorCode + ", status text: " + update.statusText);
 
     var maxErrors;
     var errCount;
     if (update.errorCode == NETWORK_ERROR_OFFLINE) {
       // Register an online observer to try again
       this._registerOnlineObserver();
-      this._backgroundUpdateCheckCodePing(PING_BGUC_OFFLINE);
+      if (this._pingSuffix) {
+        AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_OFFLINE);
+      }
       return;
     }
 
     if (update.errorCode == CERT_ATTR_CHECK_FAILED_NO_UPDATE ||
         update.errorCode == CERT_ATTR_CHECK_FAILED_HAS_UPDATE) {
       errCount = getPref("getIntPref", PREF_APP_UPDATE_CERT_ERRORS, 0);
       errCount++;
       Services.prefs.setIntPref(PREF_APP_UPDATE_CERT_ERRORS, errCount);
       maxErrors = getPref("getIntPref", PREF_APP_UPDATE_CERT_MAXERRORS, 5);
-    }
-    else {
+    } else {
       update.errorCode = BACKGROUNDCHECK_MULTIPLE_FAILURES;
       errCount = getPref("getIntPref", PREF_APP_UPDATE_BACKGROUNDERRORS, 0);
       errCount++;
       Services.prefs.setIntPref(PREF_APP_UPDATE_BACKGROUNDERRORS, errCount);
       maxErrors = getPref("getIntPref", PREF_APP_UPDATE_BACKGROUNDMAXERRORS,
                           10);
     }
 
-    var pingCode;
+    let checkCode;
     if (errCount >= maxErrors) {
       var prompter = Cc["@mozilla.org/updates/update-prompt;1"].
                      createInstance(Ci.nsIUpdatePrompt);
       prompter.showUpdateError(update);
 
       switch (update.errorCode) {
         case CERT_ATTR_CHECK_FAILED_NO_UPDATE:
-          pingCode = PING_BGUC_CERT_ATTR_NO_UPDATE_NOTIFY;
+          checkCode = AUSTLMY.CHK_CERT_ATTR_NO_UPDATE_PROMPT;
           break;
         case CERT_ATTR_CHECK_FAILED_HAS_UPDATE:
-          pingCode = PING_BGUC_CERT_ATTR_WITH_UPDATE_NOTIFY;
+          checkCode = AUSTLMY.CHK_CERT_ATTR_WITH_UPDATE_PROMPT;
           break;
         default:
-          pingCode = PING_BGUC_GENERAL_ERROR_NOTIFY;
+          checkCode = AUSTLMY.CHK_GENERAL_ERROR_PROMPT;
+          AUSTLMY.pingCheckExError(this._pingSuffix, update.errorCode);
+      }
+    } else {
+      switch (update.errorCode) {
+        case CERT_ATTR_CHECK_FAILED_NO_UPDATE:
+          checkCode = AUSTLMY.CHK_CERT_ATTR_NO_UPDATE_SILENT;
+          break;
+        case CERT_ATTR_CHECK_FAILED_HAS_UPDATE:
+          checkCode = AUSTLMY.CHK_CERT_ATTR_WITH_UPDATE_SILENT;
+          break;
+        default:
+          checkCode = AUSTLMY.CHK_GENERAL_ERROR_SILENT;
+          AUSTLMY.pingCheckExError(this._pingSuffix, update.errorCode);
       }
     }
-    else {
-      switch (update.errorCode) {
-        case CERT_ATTR_CHECK_FAILED_NO_UPDATE:
-          pingCode = PING_BGUC_CERT_ATTR_NO_UPDATE_SILENT;
-          break;
-        case CERT_ATTR_CHECK_FAILED_HAS_UPDATE:
-          pingCode = PING_BGUC_CERT_ATTR_WITH_UPDATE_SILENT;
-          break;
-        default:
-          pingCode = PING_BGUC_GENERAL_ERROR_SILENT;
-      }
-    }
-    this._backgroundUpdateCheckCodePing(pingCode);
+    AUSTLMY.pingCheckCode(this._pingSuffix, checkCode);
   },
 
   /**
    * Called when a connection should be resumed
    */
   _attemptResume: function AUS_attemptResume() {
     LOG("UpdateService:_attemptResume")
     // If a download is in progress, then resume it.
@@ -2633,152 +2379,207 @@ UpdateService.prototype = {
   },
 
   /**
    * Notified when a timer fires
    * @param   timer
    *          The timer that fired
    */
   notify: function AUS_notify(timer) {
-    // The telemetry below is specific to background notification.
-    this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_ENABLED,
-                                    "UPDATER_UPDATES_ENABLED");
-    this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_METRO_ENABLED,
-                                    "UPDATER_UPDATES_METRO_ENABLED");
-    this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_AUTO,
-                                    "UPDATER_UPDATES_AUTOMATIC");
-    this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_STAGING_ENABLED,
-                                    "UPDATER_STAGE_ENABLED");
-
-#ifdef XP_WIN
-    this._sendBoolPrefTelemetryPing(PREF_APP_UPDATE_SERVICE_ENABLED,
-                                    "UPDATER_SERVICE_ENABLED");
-    this._sendIntPrefTelemetryPing(PREF_APP_UPDATE_SERVICE_ERRORS,
-                                   "UPDATER_SERVICE_ERRORS");
-    this._sendServiceInstalledTelemetryPing();
-#endif
-
     this._checkForBackgroundUpdates(true);
   },
 
   /**
    * See nsIUpdateService.idl
    */
   checkForBackgroundUpdates: function AUS_checkForBackgroundUpdates() {
     this._checkForBackgroundUpdates(false);
   },
 
+  // The suffix used for background update check telemetry histogram ID's.
+  get _pingSuffix() {
+    return this._isNotify ? AUSTLMY.NOTIFY : AUSTLMY.EXTERNAL;
+  },
+
   /**
    * Checks for updates in the background.
    * @param   isNotify
    *          Whether or not a background update check was initiated by the
    *          application update timer notification.
    */
   _checkForBackgroundUpdates: function AUS__checkForBackgroundUpdates(isNotify) {
     this._isNotify = isNotify;
-    // From this point on, the telemetry reported differentiates between a call
-    // to notify and a call to checkForBackgroundUpdates so they are reported
-    // separately.
-    this._sendLastNotifyIntervalPing();
+
+    // Histogram IDs:
+    // UPDATE_CANNOT_APPLY_EXTERNAL
+    // UPDATE_CANNOT_APPLY_NOTIFY
+    AUSTLMY.pingGeneric("UPDATE_CANNOT_APPLY_" + this._pingSuffix,
+                        gCanApplyUpdates);
+    // Histogram IDs:
+    // UPDATE_CANNOT_STAGE_EXTERNAL
+    // UPDATE_CANNOT_STAGE_NOTIFY
+    AUSTLMY.pingGeneric("UPDATE_CANNOT_STAGE_" + this._pingSuffix,
+                        getCanStageUpdates(), true);
+    // Histogram IDs:
+    // UPDATE_INVALID_LASTUPDATETIME_EXTERNAL
+    // UPDATE_INVALID_LASTUPDATETIME_NOTIFY
+    // UPDATE_LAST_NOTIFY_INTERVAL_DAYS_EXTERNAL
+    // UPDATE_LAST_NOTIFY_INTERVAL_DAYS_NOTIFY
+    AUSTLMY.pingLastUpdateTime(this._pingSuffix);
+    // Histogram IDs:
+    // UPDATE_NOT_PREF_UPDATE_ENABLED_EXTERNAL
+    // UPDATE_NOT_PREF_UPDATE_ENABLED_NOTIFY
+    AUSTLMY.pingBoolPref("UPDATE_NOT_PREF_UPDATE_ENABLED_" + this._pingSuffix,
+                         PREF_APP_UPDATE_ENABLED, true, true);
+    // Histogram IDs:
+    // UPDATE_NOT_PREF_UPDATE_AUTO_EXTERNAL
+    // UPDATE_NOT_PREF_UPDATE_AUTO_NOTIFY
+    AUSTLMY.pingBoolPref("UPDATE_NOT_PREF_UPDATE_AUTO_" + this._pingSuffix,
+                         PREF_APP_UPDATE_AUTO, true, true);
+    // Histogram IDs:
+    // UPDATE_NOT_PREF_UPDATE_STAGING_ENABLED_EXTERNAL
+    // UPDATE_NOT_PREF_UPDATE_STAGING_ENABLED_NOTIFY
+    AUSTLMY.pingBoolPref("UPDATE_NOT_PREF_UPDATE_STAGING_ENABLED_" +
+                         this._pingSuffix,
+                         PREF_APP_UPDATE_STAGING_ENABLED, true, true);
+#ifdef XP_WIN
+    // Histogram IDs:
+    // UPDATE_PREF_UPDATE_CANCELATIONS_EXTERNAL
+    // UPDATE_PREF_UPDATE_CANCELATIONS_NOTIFY
+    AUSTLMY.pingIntPref("UPDATE_PREF_UPDATE_CANCELATIONS_" + this._pingSuffix,
+                        PREF_APP_UPDATE_CANCELATIONS, 0, 0);
+#ifdef MOZ_MAINTENANCE_SERVICE
+    // Histogram IDs:
+    // UPDATE_NOT_PREF_UPDATE_SERVICE_ENABLED_EXTERNAL
+    // UPDATE_NOT_PREF_UPDATE_SERVICE_ENABLED_NOTIFY
+    AUSTLMY.pingBoolPref("UPDATE_NOT_PREF_UPDATE_SERVICE_ENABLED_" +
+                         this._pingSuffix,
+                         PREF_APP_UPDATE_SERVICE_ENABLED, true);
+    // Histogram IDs:
+    // UPDATE_PREF_SERVICE_ERRORS_EXTERNAL
+    // UPDATE_PREF_SERVICE_ERRORS_NOTIFY
+    AUSTLMY.pingIntPref("UPDATE_PREF_SERVICE_ERRORS_" + this._pingSuffix,
+                        PREF_APP_UPDATE_SERVICE_ERRORS, 0, 0);
+    // Histogram IDs:
+    // UPDATE_SERVICE_INSTALLED_EXTERNAL
+    // UPDATE_SERVICE_INSTALLED_NOTIFY
+    // UPDATE_SERVICE_MANUALLY_UNINSTALLED_EXTERNAL
+    // UPDATE_SERVICE_MANUALLY_UNINSTALLED_NOTIFY
+    AUSTLMY.pingServiceInstallStatus(this._pingSuffix, isServiceInstalled());
+#endif // MOZ_MAINTENANCE_SERVICE
+#endif // XP_WIN
+    let prefType = Services.prefs.getPrefType(PREF_APP_UPDATE_URL_OVERRIDE);
+    let overridePrefHasValue = prefType != Ci.nsIPrefBranch.PREF_INVALID;
+    // Histogram IDs:
+    // UPDATE_HAS_PREF_URL_OVERRIDE_EXTERNAL
+    // UPDATE_HAS_PREF_URL_OVERRIDE_NOTIFY
+    AUSTLMY.pingGeneric("UPDATE_HAS_PREF_URL_OVERRIDE_" + this._pingSuffix,
+                        overridePrefHasValue, false);
 
     // If a download is in progress or the patch has been staged do nothing.
     if (this.isDownloading) {
-      this._backgroundUpdateCheckCodePing(PING_BGUC_IS_DOWNLOADING);
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_IS_DOWNLOADING);
       return;
     }
 
     if (this._downloader && this._downloader.patchIsStaged) {
-      this._backgroundUpdateCheckCodePing(PING_BGUC_IS_STAGED);
+      let readState = readStatusFile(getUpdatesDir());
+      if (readState == STATE_PENDING || readState == STATE_PENDING_SVC) {
+        AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_IS_DOWNLOADED);
+      } else {
+        AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_IS_STAGED);
+      }
       return;
     }
 
-    // The following checks will return early without notification in the call
-    // to checkForUpdates below. To simplify the background update check ping
-    // their values are checked here.
+    let validUpdateURL = true;
     try {
-      if (!this.backgroundChecker.getUpdateURL(false)) {
-        let prefs = Services.prefs;
-        if (!prefs.prefHasUserValue(PREF_APP_UPDATE_URL_OVERRIDE)) {
-          if (!prefs.prefHasUserValue(PREF_APP_UPDATE_URL)) {
-            this._backgroundUpdateCheckCodePing(PING_BGUC_INVALID_DEFAULT_URL);
-          }
-          else {
-            this._backgroundUpdateCheckCodePing(PING_BGUC_INVALID_CUSTOM_URL);
-          }
-        }
-        else {
-          this._backgroundUpdateCheckCodePing(PING_BGUC_INVALID_OVERRIDE_URL);
+      this.backgroundChecker.getUpdateURL(false);
+    } catch (e) {
+      validUpdateURL = false;
+    }
+    // The following checks are done here so they can be differentiated from
+    // foreground checks.
+    if (!gOSVersion) {
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_NO_OS_VERSION);
+    } else if (!gABI) {
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_NO_OS_ABI);
+    } else if (!validUpdateURL) {
+      if (overridePrefHasValue) {
+        if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_URL_OVERRIDE)) {
+          AUSTLMY.pingCheckCode(this._pingSuffix,
+                                AUSTLMY.CHK_INVALID_USER_OVERRIDE_URL);
+        } else {
+          AUSTLMY.pingCheckCode(this._pingSuffix,
+                                AUSTLMY.CHK_INVALID_DEFAULT_OVERRIDE_URL);
         }
-      }
-      else if (!gMetroUpdatesEnabled) {
-        this._backgroundUpdateCheckCodePing(PING_BGUC_METRO_DISABLED);
-      }
-      else if (!getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true)) {
-        this._backgroundUpdateCheckCodePing(PING_BGUC_PREF_DISABLED);
+      } else {
+        AUSTLMY.pingCheckCode(this._pingSuffix,
+                              AUSTLMY.CHK_INVALID_DEFAULT_URL);
       }
-      else if (!(gCanCheckForUpdates && hasUpdateMutex())) {
-        this._backgroundUpdateCheckCodePing(PING_BGUC_UNABLE_TO_CHECK);
-      }
-      else if (!this.backgroundChecker._enabled) {
-        this._backgroundUpdateCheckCodePing(PING_BGUC_DISABLED_FOR_SESSION);
-      }
-    }
-    catch (e) {
-      Cu.reportError(e);
+    } else if (!getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true)) {
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_PREF_DISABLED);
+    } else if (!hasUpdateMutex()) {
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_NO_MUTEX);
+    } else if (!gCanCheckForUpdates) {
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_UNABLE_TO_CHECK);
+    } else if (!this.backgroundChecker._enabled) {
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_DISABLED_FOR_SESSION);
     }
 
     this.backgroundChecker.checkForUpdates(this, false);
   },
 
   /**
    * Determine the update from the specified updates that should be offered.
    * If both valid major and minor updates are available the minor update will
    * be offered.
    * @param   updates
    *          An array of available nsIUpdate items
    * @return  The nsIUpdate to offer.
    */
   selectUpdate: function AUS_selectUpdate(updates) {
     if (updates.length == 0) {
-      this._backgroundUpdateCheckCodePing(PING_BGUC_NO_UPDATE_FOUND);
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_NO_UPDATE_FOUND);
       return null;
     }
 
     // The ping for unsupported is sent after the call to showPrompt.
-    if (updates.length == 1 && updates[0].unsupported)
+    if (updates.length == 1 && updates[0].unsupported) {
       return updates[0];
+    }
 
     // Choose the newest of the available minor and major updates.
     var majorUpdate = null;
     var minorUpdate = null;
     var vc = Services.vc;
-    var lastPingCode = PING_BGUC_NO_COMPAT_UPDATE_FOUND;
+    let lastCheckCode = AUSTLMY.CHK_NO_COMPAT_UPDATE_FOUND;
 
     updates.forEach(function(aUpdate) {
       // Ignore updates for older versions of the application and updates for
       // the same version of the application with the same build ID.
       if (vc.compare(aUpdate.appVersion, Services.appinfo.version) < 0 ||
           vc.compare(aUpdate.appVersion, Services.appinfo.version) == 0 &&
           aUpdate.buildID == Services.appinfo.appBuildID) {
         LOG("UpdateService:selectUpdate - skipping update because the " +
             "update's application version is less than the current " +
             "application version");
-        lastPingCode = PING_BGUC_UPDATE_PREVIOUS_VERSION;
+        lastCheckCode = AUSTLMY.CHK_UPDATE_PREVIOUS_VERSION;
         return;
       }
 
       // Skip the update if the user responded with "never" to this update's
       // application version and the update specifies showNeverForVersion
       // (see bug 350636).
       let neverPrefName = PREF_APP_UPDATE_NEVER_BRANCH + aUpdate.appVersion;
       if (aUpdate.showNeverForVersion &&
           getPref("getBoolPref", neverPrefName, false)) {
         LOG("UpdateService:selectUpdate - skipping update because the " +
             "preference " + neverPrefName + " is true");
-        lastPingCode = PING_BGUC_UPDATE_NEVER_PREF;
+        lastCheckCode = AUSTLMY.CHK_UPDATE_NEVER_PREF;
         return;
       }
 
       switch (aUpdate.type) {
         case "major":
           if (!majorUpdate)
             majorUpdate = aUpdate;
           else if (vc.compare(majorUpdate.appVersion, aUpdate.appVersion) <= 0)
@@ -2788,24 +2589,25 @@ UpdateService.prototype = {
           if (!minorUpdate)
             minorUpdate = aUpdate;
           else if (vc.compare(minorUpdate.appVersion, aUpdate.appVersion) <= 0)
             minorUpdate = aUpdate;
           break;
         default:
           LOG("UpdateService:selectUpdate - skipping unknown update type: " +
               aUpdate.type);
-          lastPingCode = PING_BGUC_UPDATE_INVALID_TYPE;
+          lastCheckCode = AUSTLMY.CHK_UPDATE_INVALID_TYPE;
           break;
       }
     });
 
     var update = minorUpdate || majorUpdate;
-    if (!update)
-      this._backgroundUpdateCheckCodePing(lastPingCode);
+    if (!update) {
+      AUSTLMY.pingCheckCode(this._pingSuffix, lastCheckCode);
+    }
 
     return update;
   },
 
   /**
    * Reference to the currently selected update for when add-on compatibility
    * is checked.
    */
@@ -2823,55 +2625,50 @@ UpdateService.prototype = {
     var um = Cc["@mozilla.org/updates/update-manager;1"].
              getService(Ci.nsIUpdateManager);
     if (um.activeUpdate) {
 #ifdef MOZ_WIDGET_GONK
       // For gonk, the user isn't necessarily aware of the update, so we need
       // to show the prompt to make sure.
       this._showPrompt(um.activeUpdate);
 #endif
-      this._backgroundUpdateCheckCodePing(PING_BGUC_HAS_ACTIVEUPDATE);
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_HAS_ACTIVEUPDATE);
       return;
     }
 
     var updateEnabled = getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true);
     if (!updateEnabled) {
-      this._backgroundUpdateCheckCodePing(PING_BGUC_PREF_DISABLED);
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_PREF_DISABLED);
       LOG("UpdateService:_selectAndInstallUpdate - not prompting because " +
           "update is disabled");
       return;
     }
 
-    if (!gMetroUpdatesEnabled) {
-      this._backgroundUpdateCheckCodePing(PING_BGUC_METRO_DISABLED);
-      return;
-    }
-
     var update = this.selectUpdate(updates, updates.length);
     if (!update) {
       return;
     }
 
     if (update.unsupported) {
       LOG("UpdateService:_selectAndInstallUpdate - update not supported for " +
           "this system");
       if (!getPref("getBoolPref", PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED, false)) {
         LOG("UpdateService:_selectAndInstallUpdate - notifying that the " +
             "update is not supported for this system");
         this._showPrompt(update);
       }
-      this._backgroundUpdateCheckCodePing(PING_BGUC_UNSUPPORTED);
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_UNSUPPORTED);
       return;
     }
 
-    if (!(gCanApplyUpdates && hasUpdateMutex())) {
+    if (!gCanApplyUpdates) {
       LOG("UpdateService:_selectAndInstallUpdate - the user is unable to " +
           "apply updates... prompting");
       this._showPrompt(update);
-      this._backgroundUpdateCheckCodePing(PING_BGUC_UNABLE_TO_APPLY);
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_UNABLE_TO_APPLY);
       return;
     }
 
     /**
 #      From this point on there are two possible outcomes:
 #      1. download and install the update automatically
 #      2. notify the user about the availability of an update
 #
@@ -2894,58 +2691,54 @@ UpdateService.prototype = {
 #      Major         all    N/A                    Notify
 #      Minor         0      N/A                    Auto Install
 #      Minor         1      Yes                    Notify
 #      Minor         1      No                     Auto Install
      */
     if (update.showPrompt) {
       LOG("UpdateService:_selectAndInstallUpdate - prompting because the " +
           "update snippet specified showPrompt");
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_SHOWPROMPT_SNIPPET);
       this._showPrompt(update);
-      if (!Services.metro || !Services.metro.immersive) {
-        this._backgroundUpdateCheckCodePing(PING_BGUC_SHOWPROMPT_SNIPPET);
-        return;
-      }
+      return;
     }
 
     if (!getPref("getBoolPref", PREF_APP_UPDATE_AUTO, true)) {
       LOG("UpdateService:_selectAndInstallUpdate - prompting because silent " +
           "install is disabled");
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_SHOWPROMPT_PREF);
       this._showPrompt(update);
-      if (!Services.metro || !Services.metro.immersive) {
-        this._backgroundUpdateCheckCodePing(PING_BGUC_SHOWPROMPT_PREF);
-        return;
-      }
     }
 
     if (getPref("getIntPref", PREF_APP_UPDATE_MODE, 1) == 0) {
       // Do not prompt regardless of add-on incompatibilities
       LOG("UpdateService:_selectAndInstallUpdate - add-on compatibility " +
           "check disabled by preference, just download the update");
       var status = this.downloadUpdate(update, true);
       if (status == STATE_NONE)
         cleanupActiveUpdate();
-      this._backgroundUpdateCheckCodePing(PING_BGUC_ADDON_PREF_DISABLED);
+      AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_ADDON_PREF_DISABLED);
       return;
     }
 
     // Only check add-on compatibility when the version changes.
     if (update.appVersion &&
         Services.vc.compare(update.appVersion, Services.appinfo.version) != 0) {
       this._update = update;
       this._checkAddonCompatibility();
     }
     else {
       LOG("UpdateService:_selectAndInstallUpdate - add-on compatibility " +
           "check not performed due to the update version being the same as " +
           "the current application version, just download the update");
-      var status = this.downloadUpdate(update, true);
-      if (status == STATE_NONE)
+      let status = this.downloadUpdate(update, true);
+      if (status == STATE_NONE) {
         cleanupActiveUpdate();
-      this._backgroundUpdateCheckCodePing(PING_BGUC_ADDON_SAME_APP_VER);
+      }
+      AUSTLMY.pingCheckCode(this._pingSuffix,AUSTLMY.CHK_ADDON_SAME_APP_VER);
     }
   },
 
   _showPrompt: function AUS__showPrompt(update) {
     var prompter = Cc["@mozilla.org/updates/update-prompt;1"].
                    createInstance(Ci.nsIUpdatePrompt);
     prompter.showUpdateAvailable(update);
   },
@@ -2961,18 +2754,19 @@ UpdateService.prototype = {
     AddonManager.getAllAddons(function(addons) {
       self._incompatibleAddons = [];
       addons.forEach(function(addon) {
         // Protect against code that overrides the add-ons manager and doesn't
         // implement the isCompatibleWith or the findUpdates method.
         if (!("isCompatibleWith" in addon) || !("findUpdates" in addon)) {
           let errMsg = "Add-on doesn't implement either the isCompatibleWith " +
                        "or the findUpdates method!";
-          if (addon.id)
+          if (addon.id) {
             errMsg += " Add-on ID: " + addon.id;
+          }
           Cu.reportError(errMsg);
           return;
         }
 
         // If an add-on isn't appDisabled and isn't userDisabled then it is
         // either active now or the user expects it to be active after the
         // restart. If that is the case and the add-on is not installed by the
         // application and is not compatible with the new application version
@@ -2983,20 +2777,20 @@ UpdateService.prototype = {
         // (see bug 566787). The hotfix add-on is also ignored as it shouldn't
         // block the user from upgrading.
         try {
           if (addon.type != "plugin" && addon.id != hotfixID &&
               !addon.appDisabled && !addon.userDisabled &&
               addon.scope != AddonManager.SCOPE_APPLICATION &&
               addon.isCompatible &&
               !addon.isCompatibleWith(self._update.appVersion,
-                                      self._update.platformVersion))
+                                      self._update.platformVersion)) {
             self._incompatibleAddons.push(addon);
-        }
-        catch (e) {
+          }
+        } catch (e) {
           Cu.reportError(e);
         }
       });
 
       if (self._incompatibleAddons.length > 0) {
       /**
 #        PREF_APP_UPDATE_INCOMPATIBLE_MODE
 #        Controls the mode in which we check for updates as follows.
@@ -3028,17 +2822,17 @@ UpdateService.prototype = {
       }
       else {
         LOG("UpdateService:_checkAddonCompatibility - no incompatible " +
             "add-ons found, just download the update");
         var status = self.downloadUpdate(self._update, true);
         if (status == STATE_NONE)
           cleanupActiveUpdate();
         self._update = null;
-        self._backgroundUpdateCheckCodePing(PING_BGUC_CHECK_NO_INCOMPAT);
+        AUSTLMY.pingCheckCode(self._pingSuffix, AUSTLMY.CHK_ADDON_NO_INCOMPAT);
       }
     });
   },
 
   // AddonUpdateListener
   onCompatibilityUpdateAvailable: function(addon) {
     // Remove the add-on from the list of add-ons that will become incompatible
     // with the new version of the application.
@@ -3068,30 +2862,35 @@ UpdateService.prototype = {
     // Compatibility or new version updates mean the same thing here.
     this.onCompatibilityUpdateAvailable(addon);
   },
 
   onUpdateFinished: function(addon) {
     if (--this._updateCheckCount > 0)
       return;
 
-    if (this._incompatibleAddons.length > 0 ||
-        !(gCanApplyUpdates && hasUpdateMutex())) {
+    if (this._incompatibleAddons.length > 0 || !gCanApplyUpdates) {
       LOG("UpdateService:onUpdateEnded - prompting because there are " +
           "incompatible add-ons");
+      if (this._incompatibleAddons.length > 0) {
+        AUSTLMY.pingCheckCode(this._pingSuffix,
+                              AUSTLMY.CHK_ADDON_HAVE_INCOMPAT);
+      } else {
+        AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_UNABLE_TO_APPLY);
+      }
       this._showPrompt(this._update);
-      this._backgroundUpdateCheckCodePing(PING_BGUC_ADDON_HAVE_INCOMPAT);
     }
     else {
       LOG("UpdateService:_selectAndInstallUpdate - updates for all " +
           "incompatible add-ons found, just download the update");
       var status = this.downloadUpdate(this._update, true);
       if (status == STATE_NONE)
         cleanupActiveUpdate();
-      this._backgroundUpdateCheckCodePing(PING_BGUC_ADDON_UPDATES_FOR_INCOMPAT);
+      AUSTLMY.pingCheckCode(this._pingSuffix,
+                            AUSTLMY.CHK_ADDON_UPDATES_FOR_INCOMPAT);
     }
     this._update = null;
   },
 
   /**
    * The Checker used for background update checks.
    */
   _backgroundChecker: null,
@@ -3249,39 +3048,45 @@ UpdateService.prototype = {
     }
 
     aUpdate.QueryInterface(Ci.nsIWritablePropertyBag);
     let osApplyToDir = aUpdate.getProperty("osApplyToDir");
 
     if (!osApplyToDir) {
       LOG("UpdateService:applyOsUpdate - Error: osApplyToDir is not defined" +
           "in the nsIUpdate!");
+      pingStateAndStatusCodes(aUpdate, false,
+                              STATE_FAILED + ": " + FOTA_FILE_OPERATION_ERROR);
       handleUpdateFailure(aUpdate, FOTA_FILE_OPERATION_ERROR);
       return;
     }
 
     let updateFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
     updateFile.initWithPath(osApplyToDir + "/update.zip");
     if (!updateFile.exists()) {
       LOG("UpdateService:applyOsUpdate - Error: OS update is not found at " +
           updateFile.path);
+      pingStateAndStatusCodes(aUpdate, false,
+                              STATE_FAILED + ": " + FOTA_FILE_OPERATION_ERROR);
       handleUpdateFailure(aUpdate, FOTA_FILE_OPERATION_ERROR);
       return;
     }
 
     writeStatusFile(getUpdatesDir(), aUpdate.state = STATE_APPLIED_OS);
     LOG("UpdateService:applyOsUpdate - Rebooting into recovery to apply " +
         "FOTA update: " + updateFile.path);
     try {
       let recoveryService = Cc["@mozilla.org/recovery-service;1"]
                             .getService(Ci.nsIRecoveryService);
       recoveryService.installFotaUpdate(updateFile.path);
     } catch (e) {
       LOG("UpdateService:applyOsUpdate - Error: Couldn't reboot into recovery" +
           " to apply FOTA update " + updateFile.path);
+      pingStateAndStatusCodes(aUpdate, false,
+                              STATE_FAILED + ": " + FOTA_RECOVERY_ERROR);
       writeStatusFile(getUpdatesDir(), aUpdate.state = STATE_APPLIED);
       handleUpdateFailure(aUpdate, FOTA_RECOVERY_ERROR);
     }
   },
 
   classID: UPDATESERVICE_CID,
   classInfo: XPCOMUtils.generateCI({classID: UPDATESERVICE_CID,
                                     contractID: UPDATESERVICE_CONTRACTID,
@@ -3567,21 +3372,23 @@ UpdateManager.prototype = {
    */
   refreshUpdateStatus: function UM_refreshUpdateStatus() {
     var update = this._activeUpdate;
     if (!update) {
       return;
     }
     var updateSucceeded = true;
     var status = readStatusFile(getUpdatesDir());
-    var ary = status.split(":");
-    update.state = ary[0];
-    if (update.state == STATE_FAILED && ary[1]) {
+    pingStateAndStatusCodes(update, false, status);
+    var parts = status.split(":");
+    update.state = parts[0];
+
+    if (update.state == STATE_FAILED && parts[1]) {
       updateSucceeded = false;
-      if (!handleUpdateFailure(update, ary[1])) {
+      if (!handleUpdateFailure(update, parts[1])) {
         handleFallbackToCompleteUpdate(update, true);
       }
     }
     if (update.state == STATE_APPLIED && shouldUseService()) {
       writeStatusFile(getUpdatesDir(), update.state = STATE_APPLIED_SVC);
     }
     var um = Cc["@mozilla.org/updates/update-manager;1"].
              getService(Ci.nsIUpdateManager);
@@ -3716,18 +3523,16 @@ Checker.prototype = {
       throw Cr.NS_ERROR_NULL_POINTER;
 
     Services.obs.notifyObservers(null, "update-check-start", null);
 
     var url = this.getUpdateURL(force);
     if (!url || (!this.enabled && !force))
       return;
 
-    recordInHealthReport(UpdaterHealthReportFields.CHECK_START, 0);
-
     this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
                     createInstance(Ci.nsISupports);
     // This is here to let unit test code override XHR
     if (this._request.wrappedJSObject) {
       this._request = this._request.wrappedJSObject;
     }
     this._request.open("GET", url, true);
     var allowNonBuiltIn = !getPref("getBoolPref",
@@ -3841,18 +3646,16 @@ Checker.prototype = {
       gCertUtils.checkCert(this._request.channel, allowNonBuiltIn, certs);
 
       if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_ERRORS))
         Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_ERRORS);
 
       if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS))
         Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDERRORS);
 
-      recordInHealthReport(UpdaterHealthReportFields.CHECK_SUCCESS, 0);
-
       // Tell the callback about the updates
       this._callback.onCheckComplete(event.target, updates, updates.length);
     }
     catch (e) {
       LOG("Checker:onLoad - there was a problem checking for updates. " +
           "Exception: " + e);
       var request = event.target;
       var status = this._getChannelStatus(request);
@@ -3864,18 +3667,16 @@ Checker.prototype = {
       if (this._isHttpStatusCode(status)) {
         update.errorCode = HTTP_ERROR_OFFSET + status;
       }
       if (e.result && e.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
         update.errorCode = updates[0] ? CERT_ATTR_CHECK_FAILED_HAS_UPDATE
                                       : CERT_ATTR_CHECK_FAILED_NO_UPDATE;
       }
 
-      recordInHealthReport(UpdaterHealthReportFields.CHECK_FAILED, update.errorCode);
-
       this._callback.onError(request, update);
     }
 
     this._callback = null;
     this._request = null;
   },
 
   /**
@@ -3897,32 +3698,25 @@ Checker.prototype = {
 
     if (status == Cr.NS_ERROR_OFFLINE) {
       // We use a separate constant here because nsIUpdate.errorCode is signed
       update.errorCode = NETWORK_ERROR_OFFLINE;
     } else if (this._isHttpStatusCode(status)) {
       update.errorCode = HTTP_ERROR_OFFSET + status;
     }
 
-    recordInHealthReport(UpdaterHealthReportFields.CHECK_FAILED, update.errorCode);
-
     this._callback.onError(request, update);
-
     this._request = null;
   },
 
   /**
    * Whether or not we are allowed to do update checking.
    */
   _enabled: true,
   get enabled() {
-    if (!gMetroUpdatesEnabled) {
-      return false;
-    }
-
     return getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true) &&
            gCanCheckForUpdates && hasUpdateMutex() && this._enabled;
   },
 
   /**
    * See nsIUpdateService.idl
    */
   stopChecking: function UC_stopChecking(duration) {
@@ -4012,24 +3806,28 @@ Downloader.prototype = {
 
   /**
    * Verify the downloaded file.  We assume that the download is complete at
    * this point.
    */
   _verifyDownload: function Downloader__verifyDownload() {
     LOG("Downloader:_verifyDownload called");
     if (!this._request) {
+      AUSTLMY.pingDownloadCode(this.isCompleteUpdate,
+                               AUSTLMY.DWNLD_ERR_VERIFY_NO_REQUEST);
       return false;
     }
 
     let destination = this._request.destination;
 
     // Ensure that the file size matches the expected file size.
     if (destination.fileSize != this._patch.size) {
       LOG("Downloader:_verifyDownload downloaded size != expected size.");
+      AUSTLMY.pingDownloadCode(this.isCompleteUpdate,
+                               AUSTLMY.DWNLD_ERR_VERIFY_PATCH_SIZE_NOT_EQUAL);
       return false;
     }
 
     LOG("Downloader:_verifyDownload downloaded size == expected size.");
     let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].
                      createInstance(Ci.nsIFileInputStream);
     fileStream.init(destination, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
 
@@ -4057,16 +3855,18 @@ Downloader.prototype = {
     fileStream.close();
 
     if (digest == this._patch.hashValue.toLowerCase()) {
       LOG("Downloader:_verifyDownload hashes match.");
       return true;
     }
 
     LOG("Downloader:_verifyDownload hashes do not match. ");
+    AUSTLMY.pingDownloadCode(this.isCompleteUpdate,
+                             AUSTLMY.DWNLD_ERR_VERIFY_NO_HASH_MATCH);
     return false;
   },
 
   /**
    * Select the patch to use given the current state of updateDir and the given
    * set of update patches.
    * @param   update
    *          A nsIUpdate object to select a patch from
@@ -4200,36 +4000,35 @@ Downloader.prototype = {
 
   /**
    * Download and stage the given update.
    * @param   update
    *          A nsIUpdate object to download a patch for. Cannot be null.
    */
   downloadUpdate: function Downloader_downloadUpdate(update) {
     LOG("UpdateService:_downloadUpdate");
-    if (!update)
+    if (!update) {
+      AUSTLMY.pingDownloadCode(undefined, AUSTLMY.DWNLD_ERR_NO_UPDATE);
       throw Cr.NS_ERROR_NULL_POINTER;
+    }
 
     var updateDir = getUpdatesDir();
 
     this._update = update;
 
     // This function may return null, which indicates that there are no patches
     // to download.
     this._patch = this._selectPatch(update, updateDir);
     if (!this._patch) {
       LOG("Downloader:downloadUpdate - no patch to download");
+      AUSTLMY.pingDownloadCode(undefined, AUSTLMY.DWNLD_ERR_NO_UPDATE_PATCH);
       return readStatusFile(updateDir);
     }
     this.isCompleteUpdate = this._patch.type == "complete";
 
-    recordInHealthReport(
-      this.isCompleteUpdate ? UpdaterHealthReportFields.COMPLETE_START :
-                              UpdaterHealthReportFields.PARTIAL_START, 0);
-
     var patchFile = null;
 
 #ifdef MOZ_WIDGET_GONK
     let status = readStatusFile(updateDir);
     if (isInterruptedUpdate(status)) {
       LOG("Downloader:downloadUpdate - interruptted update");
       // The update was interrupted. Try to locate the existing patch file.
       // For an interrupted download, this allows a resume rather than a
@@ -4281,16 +4080,18 @@ Downloader.prototype = {
       }
     }
 #endif
     if (!patchFile) {
       // Find a place to put the patchfile that we're going to download.
       patchFile = this._getUpdateArchiveFile();
     }
     if (!patchFile) {
+      AUSTLMY.pingDownloadCode(this.isCompleteUpdate,
+                               AUSTLMY.DWNLD_ERR_NO_PATCH_FILE);
       return STATE_NONE;
     }
 
 #ifdef MOZ_WIDGET_GONK
     if (patchFile.path.indexOf(updateDir.path) != 0) {
       // The patchFile is in a directory which is different from the
       // updateDir, create a link file.
       writeLinkFile(updateDir, patchFile);
@@ -4398,26 +4199,30 @@ Downloader.prototype = {
     LOG("Downloader:onProgress - progress: " + progress + "/" + maxProgress);
 
     if (progress > this._patch.size) {
       LOG("Downloader:onProgress - progress: " + progress +
           " is higher than patch size: " + this._patch.size);
       // It's important that we use a different code than
       // NS_ERROR_CORRUPTED_CONTENT so that tests can verify the difference
       // between a hash error and a wrong download error.
+      AUSTLMY.pingDownloadCode(this.isCompleteUpdate,
+                               AUSTLMY.DWNLD_ERR_PATCH_SIZE_LARGER);
       this.cancel(Cr.NS_ERROR_UNEXPECTED);
       return;
     }
 
     if (maxProgress != this._patch.size) {
       LOG("Downloader:onProgress - maxProgress: " + maxProgress +
           " is not equal to expectd patch size: " + this._patch.size);
       // It's important that we use a different code than
       // NS_ERROR_CORRUPTED_CONTENT so that tests can verify the difference
       // between a hash error and a wrong download error.
+      AUSTLMY.pingDownloadCode(this.isCompleteUpdate,
+                               AUSTLMY.DWNLD_ERR_PATCH_SIZE_NOT_EQUAL);
       this.cancel(Cr.NS_ERROR_UNEXPECTED);
       return;
     }
 
     var listeners = this._listeners.concat();
     var listenerCount = listeners.length;
     for (var i = 0; i < listenerCount; ++i) {
       var listener = listeners[i];
@@ -4475,25 +4280,22 @@ Downloader.prototype = {
     var retryTimeout = getPref("getIntPref", PREF_APP_UPDATE_RETRY_TIMEOUT,
                                DEFAULT_UPDATE_RETRY_TIMEOUT);
     var maxFail = getPref("getIntPref", PREF_APP_UPDATE_SOCKET_ERRORS,
                           DEFAULT_SOCKET_MAX_ERRORS);
     LOG("Downloader:onStopRequest - status: " + status + ", " +
         "current fail: " + this.updateService._consecutiveSocketErrors + ", " +
         "max fail: " + maxFail + ", " + "retryTimeout: " + retryTimeout);
     if (Components.isSuccessCode(status)) {
-      recordInHealthReport(
-        this.isCompleteUpdate ? UpdaterHealthReportFields.COMPLETE_SUCCESS :
-                                UpdaterHealthReportFields.PARTIAL_SUCCESS, 0);
-
       if (this._verifyDownload()) {
         state = shouldUseService() ? STATE_PENDING_SVC : STATE_PENDING;
         if (this.background) {
           shouldShowPrompt = !getCanStageUpdates();
         }
+        AUSTLMY.pingDownloadCode(this.isCompleteUpdate, AUSTLMY.DWNLD_SUCCESS);
 
         // Tell the updater.exe we're ready to apply.
         writeStatusFile(getUpdatesDir(), state);
         writeVersionFile(getUpdatesDir(), this._update.appVersion);
         this._update.installDate = (new Date()).getTime();
         this._update.statusText = gUpdateBundle.GetStringFromName("installPending");
       }
       else {
@@ -4508,41 +4310,56 @@ Downloader.prototype = {
 
         if (this._update.isCompleteUpdate || this._update.patchCount != 2)
           deleteActiveUpdate = true;
 
         // Destroy the updates directory, since we're done with it.
         cleanUpUpdatesDir();
       }
     } else {
-      recordInHealthReport(UpdaterHealthReportFields.FAILED, status);
-
       if (status == Cr.NS_ERROR_OFFLINE) {
         // Register an online observer to try again.
         // The online observer will continue the incremental download by
         // calling downloadUpdate on the active update which continues
         // downloading the file from where it was.
         LOG("Downloader:onStopRequest - offline, register online observer: true");
+        AUSTLMY.pingDownloadCode(this.isCompleteUpdate,
+                                 AUSTLMY.DWNLD_RETRY_OFFLINE);
         shouldRegisterOnlineObserver = true;
         deleteActiveUpdate = false;
       // Each of NS_ERROR_NET_TIMEOUT, ERROR_CONNECTION_REFUSED, and
       // NS_ERROR_NET_RESET can be returned when disconnecting the internet while
       // a download of a MAR is in progress.  There may be others but I have not
       // encountered them during testing.
       } else if ((status == Cr.NS_ERROR_NET_TIMEOUT ||
                   status == Cr.NS_ERROR_CONNECTION_REFUSED ||
                   status == Cr.NS_ERROR_NET_RESET) &&
                  this.updateService._consecutiveSocketErrors < maxFail) {
         LOG("Downloader:onStopRequest - socket error, shouldRetrySoon: true");
+        let dwnldCode = AUSTLMY.DWNLD_RETRY_CONNECTION_REFUSED;
+        if (status == Cr.NS_ERROR_NET_TIMEOUT) {
+          dwnldCode = AUSTLMY.DWNLD_RETRY_NET_TIMEOUT;
+        } else if (status == Cr.NS_ERROR_NET_RESET) {
+          dwnldCode = AUSTLMY.DWNLD_RETRY_NET_RESET;
+        }
+        AUSTLMY.pingDownloadCode(this.isCompleteUpdate, dwnldCode);
         shouldRetrySoon = true;
         deleteActiveUpdate = false;
       } else if (status != Cr.NS_BINDING_ABORTED &&
                  status != Cr.NS_ERROR_ABORT &&
                  status != Cr.NS_ERROR_DOCUMENT_NOT_CACHED) {
         LOG("Downloader:onStopRequest - non-verification failure");
+        let dwnldCode = AUSTLMY.DWNLD_ERR_DOCUMENT_NOT_CACHED;
+        if (status == Cr.NS_BINDING_ABORTED) {
+          dwnldCode = AUSTLMY.DWNLD_ERR_BINDING_ABORTED;
+        } else if (status == Cr.NS_ERROR_ABORT) {
+          dwnldCode = AUSTLMY.DWNLD_ERR_ABORT;
+        }
+        AUSTLMY.pingDownloadCode(this.isCompleteUpdate, dwnldCode);
+
         // Some sort of other failure, log this in the |statusText| property
         state = STATE_DOWNLOAD_FAILED;
 
         // XXXben - if |request| (The Incremental Download) provided a means
         // for accessing the http channel we could do more here.
 
         this._update.statusText = getStatusTextFromCode(status,
                                                         Cr.NS_BINDING_FAILED);
@@ -4564,18 +4381,19 @@ Downloader.prototype = {
     this._patch.state = state;
     var um = Cc["@mozilla.org/updates/update-manager;1"].
              getService(Ci.nsIUpdateManager);
     if (deleteActiveUpdate) {
       this._update.installDate = (new Date()).getTime();
       um.activeUpdate = null;
     }
     else {
-      if (um.activeUpdate)
+      if (um.activeUpdate) {
         um.activeUpdate.state = state;
+      }
     }
     um.saveUpdates();
 
     // Only notify listeners about the stopped state if we
     // aren't handling an internal retry.
     if (!shouldRetrySoon && !shouldRegisterOnlineObserver) {
       var listeners = this._listeners.concat();
       var listenerCount = listeners.length;
@@ -4794,24 +4612,20 @@ UpdatePrompt.prototype = {
   /**
    * See nsIUpdateService.idl
    */
   showUpdateError: function UP_showUpdateError(update) {
     if (getPref("getBoolPref", PREF_APP_UPDATE_SILENT, false) ||
         this._getAltUpdateWindow())
       return;
 
-    // In some cases, we want to just show a simple alert dialog:
+    // In some cases, we want to just show a simple alert dialog.
+    // Replace with Array.prototype.includes when it has stabilized.
     if (update.state == STATE_FAILED &&
-        (update.errorCode == WRITE_ERROR ||
-         update.errorCode == WRITE_ERROR_ACCESS_DENIED ||
-         update.errorCode == WRITE_ERROR_SHARING_VIOLATION_SIGNALED ||
-         update.errorCode == WRITE_ERROR_SHARING_VIOLATION_NOPROCESSFORPID ||
-         update.errorCode == WRITE_ERROR_SHARING_VIOLATION_NOPID ||
-         update.errorCode == WRITE_ERROR_CALLBACK_APP ||
+        (WRITE_ERRORS.indexOf(update.errorCode) != -1 ||
          update.errorCode == FILESYSTEM_MOUNT_READWRITE_ERROR ||
          update.errorCode == FOTA_GENERAL_ERROR ||
          update.errorCode == FOTA_FILE_OPERATION_ERROR ||
          update.errorCode == FOTA_RECOVERY_ERROR ||
          update.errorCode == FOTA_UNKNOWN_ERROR)) {
       var title = gUpdateBundle.GetStringFromName("updaterIOErrorTitle");
       var text = gUpdateBundle.formatStringFromName("updaterIOErrorMsg",
                                                     [Services.appinfo.name,
--- a/toolkit/mozapps/update/nsUpdateServiceStub.js
+++ b/toolkit/mozapps/update/nsUpdateServiceStub.js
@@ -1,17 +1,17 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
+Cu.import("resource://gre/modules/FileUtils.jsm", this);
 
 const DIR_UPDATES         = "updates";
 const FILE_UPDATE_STATUS  = "update.status";
 
 const KEY_UPDROOT         = "UpdRootD";
 
 /**
  * Gets the specified directory at the specified hierarchy under the update root
--- a/toolkit/mozapps/update/nsUpdateTimerManager.js
+++ b/toolkit/mozapps/update/nsUpdateTimerManager.js
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", this);
+Components.utils.import("resource://gre/modules/Services.jsm", this);
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 const PREF_APP_UPDATE_LASTUPDATETIME_FMT  = "app.update.lastUpdateTime.%ID%";
 const PREF_APP_UPDATE_TIMERMINIMUMDELAY   = "app.update.timerMinimumDelay";
 const PREF_APP_UPDATE_TIMERFIRSTINTERVAL  = "app.update.timerFirstInterval";
 const PREF_APP_UPDATE_LOG                 = "app.update.log";
--- a/toolkit/mozapps/update/tests/chrome/chrome.ini
+++ b/toolkit/mozapps/update/tests/chrome/chrome.ini
@@ -62,16 +62,18 @@ reason = Bug 918029 - timeout caused by 
 [test_0097_restartNotification_stagedServiceBackground.xul]
 [test_0101_background_restartNotification.xul]
 [test_0102_background_restartNotification_staging.xul]
 skip-if = os == 'linux'
 reason = Bug 918029 - timeout caused by copying too many files.
 [test_0103_background_restartNotification_stagingService.xul]
 skip-if = os != 'win'
 reason = only Windows has the maintenance service.
+[test_0104_background_restartNotification_NoIncompatAddons.xul]
+[test_0105_background_restartNotification_VersionCompatAddons.xul]
 [test_0111_neverButton_basic.xul]
 [test_0112_neverButton_billboard.xul]
 [test_0113_showNeverForVersionRemovedWithPref.xul]
 [test_0121_check_requireBuiltinCert.xul]
 [test_0122_check_allowNonBuiltinCert_validCertAttrs.xul]
 [test_0123_check_allowNonBuiltinCert_noCertAttrsCheck.xul]
 [test_0131_check_invalidCertAttrs_noUpdate.xul]
 [test_0132_check_invalidCertAttrs_hasUpdate.xul]
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/tests/chrome/test_0104_background_restartNotification_NoIncompatAddons.xul
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!--
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+-->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window title="Update Wizard pages: background finish with a background download"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        onload="runTestDefault();">
+<script type="application/javascript"
+        src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+<script type="application/javascript"
+        src="utils.js"/>
+
+<script type="application/javascript">
+<![CDATA[
+
+const TESTS = [ {
+  pageid: PAGEID_FINISHED_BKGRD,
+  buttonClick: "extra1"
+} ];
+
+gDisableNoUpdateAddon = true;
+gDisableUpdateCompatibilityAddon = true;
+gDisableUpdateVersionAddon = true;
+
+function runTest() {
+  debugDump("entering");
+
+  Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
+
+  let url = URL_HTTP_UPDATE_XML + "?showDetails=1" +
+            getVersionParams(getNewerAppVersion(), getNewerPlatformVersion());
+  setUpdateURLOverride(url);
+
+  gAUS.notify(null);
+}
+
+]]>
+</script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test"></pre>
+</body>
+</window>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/tests/chrome/test_0105_background_restartNotification_VersionCompatAddons.xul
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<!--
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+-->
+
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window title="Update Wizard pages: background finish with a background download"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        onload="runTestDefault();">
+<script type="application/javascript"
+        src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+<script type="application/javascript"
+        src="utils.js"/>
+
+<script type="application/javascript">
+<![CDATA[
+
+const TESTS = [ {
+  pageid: PAGEID_FINISHED_BKGRD,
+  buttonClick: "extra1"
+} ];
+
+gDisableNoUpdateAddon = true;
+gDisableUpdateCompatibilityAddon = true;
+
+function runTest() {
+  debugDump("entering");
+
+  Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 1);
+
+  let url = URL_HTTP_UPDATE_XML + "?showDetails=1" +
+            getVersionParams(getNewerAppVersion(), getNewerPlatformVersion());
+  setUpdateURLOverride(url);
+
+  gAUS.notify(null);
+}
+
+]]>
+</script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test"></pre>
+</body>
+</window>
--- a/toolkit/mozapps/update/tests/chrome/utils.js
+++ b/toolkit/mozapps/update/tests/chrome/utils.js
@@ -97,35 +97,41 @@
  *   the add-on is compatible with the current toolkit version and does not have
  *   an update to make it compatible with the update's toolkit version. Tests
  *   that need to have all add-ons compatible for the application update can
  *   disable this add-on by setting the gDisableNoUpdateAddon variable to true.
  *
  * updatecompatibility
  *   the add-on is compatible with the current toolkit version and has a
  *   compatibility update to make it compatible with the update's toolkit
- *   version.
+ *   version. Tests that need to have add-ons compatible for the application
+ *   update without updating the add-on's compatibility information can disable
+ *   this add-on by setting the gDisableUpdateCompatibilityAddon variable to
+ *   true.
  *
  * updateversion
  *   the add-on is compatible with the current toolkit version and has a version
- *   update to make it compatible with the update's toolkit version.
+ *   update to make it compatible with the update's toolkit version. Tests that
+ *   need to have add-ons compatible for the application update without updating
+ *   the add-on's to a new version that is compatible can disable this add-on by
+ *   setting the gDisableUpdateVersionAddon variable to true.
  *
  * userdisabled
  *   disabled by the user and compatible with the current toolkit version but
  *   not the update's toolkit version. This add-on will be disabled after its
  *   install completes.
  */
 
 'use strict';
 
 const { classes: Cc, interfaces: Ci, manager: Cm, results: Cr,
         utils: Cu } = Components;
 
-Cu.import("resource://gre/modules/AddonManager.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/AddonManager.jsm", this);
+Cu.import("resource://gre/modules/Services.jsm", this);
 
 const IS_MACOSX = ("nsILocalFileMac" in Ci);
 
 // The tests have to use the pageid instead of the pageIndex due to the
 // app update wizard's access method being random.
 const PAGEID_DUMMY            = "dummy";                 // Done
 const PAGEID_CHECKING         = "checking";              // Done
 const PAGEID_PLUGIN_UPDATES   = "pluginupdatesfound";
@@ -146,16 +152,18 @@ const PAGEID_FINISHED_BKGRD   = "finishe
 const PAGEID_INSTALLED        = "installed";             // Done
 
 const UPDATE_WINDOW_NAME = "Update:Wizard";
 
 const URL_HOST = "http://example.com";
 const URL_PATH_UPDATE_XML = "/chrome/toolkit/mozapps/update/tests/chrome/update.sjs";
 const REL_PATH_DATA = "chrome/toolkit/mozapps/update/tests/data";
 
+// These two URLs must not contain parameters since tests add their own
+// test specific parameters.
 const URL_HTTP_UPDATE_XML = URL_HOST + URL_PATH_UPDATE_XML;
 const URL_HTTPS_UPDATE_XML = "https://example.com" + URL_PATH_UPDATE_XML;
 
 const URI_UPDATE_PROMPT_DIALOG  = "chrome://mozapps/content/update/updates.xul";
 
 const ADDON_ID_SUFFIX = "@appupdatetest.mozilla.org";
 const ADDON_PREP_DIR = "appupdateprep";
 
@@ -197,16 +205,18 @@ var gAppUpdateURLDefault;         // app
 var gAppUpdateURL;                // app.update.url.override
 var gExtUpdateURL;                // extensions.update.url
 
 var gTestCounter = -1;
 var gWin;
 var gDocElem;
 var gPrefToCheck;
 var gDisableNoUpdateAddon = false;
+var gDisableUpdateCompatibilityAddon = false;
+var gDisableUpdateVersionAddon = false;
 
 // Set to true to log additional information for debugging. To log additional
 // information for an individual test set DEBUG_AUS_TEST to true in the test's
 // onload function.
 var DEBUG_AUS_TEST = false;
 
 const DATA_URI_SPEC = "chrome://mochitests/content/chrome/toolkit/mozapps/update/tests/data/";
 Services.scriptloader.loadSubScript(DATA_URI_SPEC + "shared.js", this);
@@ -1120,31 +1130,37 @@ function setupAddons(aCallback) {
   debugDump("entering");
 
   // Sets the appropriate userDisabled value for the noupdate test add-ons based
   // on the value of gDisableNoUpdateAddon and calls the callback specified in
   // setupAddons aCallback parameter.
   function setNoUpdateAddonsDisabledState() {
     AddonManager.getAllAddons(function(aAddons) {
       aAddons.forEach(function(aAddon) {
-        if (aAddon.name.indexOf("appdisabled") == 0) {
+        if (aAddon.name.startsWith("appdisabled")) {
           if (!aAddon.userDisabled) {
             aAddon.userDisabled = true;
           }
         }
 
-        if (aAddon.name.indexOf("noupdate") == 0) {
-          if (gDisableNoUpdateAddon) {
-            if (!aAddon.userDisabled) {
-              aAddon.userDisabled = true;
-            }
-          } else {
-            if (aAddon.userDisabled) {
-              aAddon.userDisabled = false;
-            }
+        if (aAddon.name.startsWith("noupdate")) {
+          if (aAddon.userDisabled != gDisableNoUpdateAddon) {
+            aAddon.userDisabled = gDisableNoUpdateAddon;
+          }
+        }
+
+        if (aAddon.name.startsWith("updatecompatibility")) {
+          if (aAddon.userDisabled != gDisableUpdateCompatibilityAddon) {
+            aAddon.userDisabled = gDisableUpdateCompatibilityAddon;
+          }
+        }
+
+        if (aAddon.name.startsWith("updateversion")) {
+          if (aAddon.userDisabled != gDisableUpdateVersionAddon) {
+            aAddon.userDisabled = gDisableUpdateVersionAddon;
           }
         }
       });
       // Start the timout timer before the update window is displayed so it can
       // clean up tests that don't successfully display the update window.
       setupTimer(gTestTimeout);
       aCallback();
     });
--- a/toolkit/mozapps/update/tests/data/partial_log_failure
+++ b/toolkit/mozapps/update/tests/data/partial_log_failure
@@ -177,10 +177,10 @@ backup_restore: backup file doesn't exis
 FINISH REMOVEFILE 4/4text1
 backup_restore: backup file doesn't exist: 4/4text1.moz-backup
 FINISH REMOVEFILE 4/4text0
 backup_restore: backup file doesn't exist: 4/4text0.moz-backup
 FINISH REMOVEFILE 3/3text1
 backup_restore: backup file doesn't exist: 3/3text1.moz-backup
 FINISH REMOVEFILE 3/3text0
 backup_restore: backup file doesn't exist: 3/3text0.moz-backup
-failed: 42
+failed: 2
 calling QuitProgressUI
--- a/toolkit/mozapps/update/tests/data/partial_log_failure_mac
+++ b/toolkit/mozapps/update/tests/data/partial_log_failure_mac
@@ -177,10 +177,10 @@ backup_restore: backup file doesn't exis
 FINISH REMOVEFILE Contents/Resources/4/4text1
 backup_restore: backup file doesn't exist: Contents/Resources/4/4text1.moz-backup
 FINISH REMOVEFILE Contents/Resources/4/4text0
 backup_restore: backup file doesn't exist: Contents/Resources/4/4text0.moz-backup
 FINISH REMOVEFILE Contents/Resources/3/3text1
 backup_restore: backup file doesn't exist: Contents/Resources/3/3text1.moz-backup
 FINISH REMOVEFILE Contents/Resources/3/3text0
 backup_restore: backup file doesn't exist: Contents/Resources/3/3text0.moz-backup
-failed: 42
+failed: 2
 calling QuitProgressUI
--- a/toolkit/mozapps/update/tests/data/sharedUpdateXML.js
+++ b/toolkit/mozapps/update/tests/data/sharedUpdateXML.js
@@ -30,21 +30,22 @@ const STATE_PENDING         = "pending";
 const STATE_PENDING_SVC     = "pending-service";
 const STATE_APPLYING        = "applying";
 const STATE_APPLIED         = "applied";
 const STATE_APPLIED_SVC     = "applied-service";
 const STATE_SUCCEEDED       = "succeeded";
 const STATE_DOWNLOAD_FAILED = "download-failed";
 const STATE_FAILED          = "failed";
 
-const STATE_FAILED_READ_ERROR                      = STATE_FAILED + ": 6";
-const STATE_FAILED_WRITE_ERROR                     = STATE_FAILED + ": 7";
-const STATE_FAILED_CHANNEL_MISMATCH_ERROR          = STATE_FAILED + ": 22";
-const STATE_FAILED_VERSION_DOWNGRADE_ERROR         = STATE_FAILED + ": 23";
-const STATE_FAILED_UNEXPECTED_FILE_OPERATION_ERROR = STATE_FAILED + ": 42";
+const STATE_FAILED_LOADSOURCE_ERROR_WRONG_SIZE = STATE_FAILED + ": 2";
+const STATE_FAILED_READ_ERROR                  = STATE_FAILED + ": 6";
+const STATE_FAILED_WRITE_ERROR                 = STATE_FAILED + ": 7";
+const STATE_FAILED_CHANNEL_MISMATCH_ERROR      = STATE_FAILED + ": 22";
+const STATE_FAILED_VERSION_DOWNGRADE_ERROR     = STATE_FAILED + ": 23";
+const STATE_FAILED_WRITE_ERROR_FILE_COPY       = STATE_FAILED + ": 61";
 
 /**
  * Constructs a string representing a remote update xml file.
  *
  * @param  aUpdates
  *         The string representing the update elements.
  * @return The string representing a remote update xml file.
  */
--- a/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
+++ b/toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
@@ -4,17 +4,18 @@
 
 'use strict';
 
 const { classes: Cc, interfaces: Ci, manager: Cm, results: Cr,
         utils: Cu } = Components;
 
 load("../data/xpcshellConstantsPP.js");
 
-Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Services.jsm", this);
+Cu.import("resource://gre/modules/ctypes.jsm", this);
 
 const DIR_MACOS = IS_MACOSX ? "Contents/MacOS/" : "";
 const DIR_RESOURCES = IS_MACOSX ? "Contents/Resources/" : "";
 const TEST_FILE_SUFFIX =  IS_MACOSX ? "_mac" : "";
 const FILE_COMPLETE_MAR = "complete" + TEST_FILE_SUFFIX + ".mar";
 const FILE_PARTIAL_MAR = "partial" + TEST_FILE_SUFFIX + ".mar";
 const LOG_COMPLETE_SUCCESS = "complete_log_success" + TEST_FILE_SUFFIX;
 const LOG_PARTIAL_SUCCESS  = "partial_log_success" + TEST_FILE_SUFFIX;
@@ -1191,17 +1192,16 @@ function getTestDirFile(aRelPath) {
   return do_get_file(relpath, false);
 }
 
 function getSpecialFolderDir(aCSIDL) {
   if (!IS_WIN) {
     do_throw("Windows only function called by a different platform!");
   }
 
-  Cu.import("resource://gre/modules/ctypes.jsm");
   let lib = ctypes.open("shell32");
   let SHGetSpecialFolderPath = lib.declare("SHGetSpecialFolderPathW",
                                            ctypes.winapi_abi,
                                            ctypes.bool, /* bool(return) */
                                            ctypes.int32_t, /* HWND hwndOwner */
                                            ctypes.char16_t.ptr, /* LPTSTR lpszPath */
                                            ctypes.int32_t, /* int csidl */
                                            ctypes.bool /* BOOL fCreate */);
@@ -1526,18 +1526,23 @@ function runUpdate(aExpectedExitValue, a
                   process.exitValue + ", Expected: " +  aExpectedExitValue);
     }
     if (status != aExpectedStatus) {
       logTestInfo("update status is not the expected status! Got: " + status +
                   ", Expected: " +  aExpectedStatus);
     }
     let updateLog = getUpdatesPatchDir();
     updateLog.append(FILE_UPDATE_LOG);
-    logTestInfo("contents of " + updateLog.path + ":\n" +
-                readFileBytes(updateLog).replace(/\r\n/g, "\n"));
+    // xpcshell tests won't display the entire contents so log each line.
+    let contents = readFileBytes(updateLog).replace(/\r\n/g, "\n");
+    let aryLogContents = contents.split("\n");
+    logTestInfo("contents of " + updateLog.path + ":");
+    aryLogContents.forEach(function RU_LC_FE(aLine) {
+      logTestInfo(aLine);
+    });
   }
   debugDump("testing updater binary process exitValue against expected " +
             "exit value");
   do_check_eq(process.exitValue, aExpectedExitValue);
   debugDump("testing update status against expected status");
   do_check_eq(status, aExpectedStatus);
 
   if (aCallback !== null) {
@@ -2070,17 +2075,17 @@ function runUpdateUsingService(aInitialS
   // We will rely on watching the update.status file and waiting for the service
   // to stop to know the service command is done.
   process.run(true, args, args.length);
 
   resetEnvironment();
 
   function timerCallback(aTimer) {
     // Wait for the expected status
-    let status = readStatusState();
+    let status = readStatusFile();
     // status will probably always be equal to STATE_APPLYING but there is a
     // race condition where it would be possible on slower machines where status
     // could be equal to STATE_PENDING_SVC.
     if (status == STATE_APPLYING ||
         status == STATE_PENDING_SVC) {
       debugDump("still waiting to see the " + aExpectedStatus +
                 " status, got " + status + " for now...");
       return;
@@ -2093,18 +2098,23 @@ function runUpdateUsingService(aInitialS
     aTimer = null;
 
     if (status != aExpectedStatus) {
       logTestInfo("update status is not the expected status! Got: " + status +
                   ", Expected: " +  aExpectedStatus);
       logTestInfo("update.status contents: " + readStatusFile());
       let updateLog = getUpdatesPatchDir();
       updateLog.append(FILE_UPDATE_LOG);
-      logTestInfo("contents of " + updateLog.path + ":\n" +
-                  readFileBytes(updateLog).replace(/\r\n/g, "\n"));
+      // xpcshell tests won't display the entire contents so log each line.
+      let contents = readFileBytes(updateLog).replace(/\r\n/g, "\n");
+      let aryLogContents = contents.split("\n");
+      logTestInfo("contents of " + updateLog.path + ":");
+      aryLogContents.forEach(function RUUS_TC_LC_FE(aLine) {
+        logTestInfo(aLine);
+      });
     }
     debugDump("testing update status against expected status");
     do_check_eq(status, aExpectedStatus);
 
     if (aCheckSvcLog) {
       checkServiceLogs(svcOriginalLog);
     }
 
@@ -2465,17 +2475,32 @@ function checkUpdateLogContents(aCompare
 
   // Don't write the contents of the file to the log to reduce log spam
   // unless there is a failure.
   if (compareLogContents == updateLogContents) {
     debugDump("log contents are correct");
     do_check_true(true);
   } else {
     logTestInfo("log contents are not correct");
-    do_check_eq(compareLogContents, updateLogContents);
+    let aryLog = updateLogContents.split("\n");
+    let aryCompare = compareLogContents.split("\n");
+    // Pushing an empty string to both arrays makes it so either array's length
+    // can be used in the for loop below without going out of bounds.
+    aryLog.push("");
+    aryCompare.push("");
+    // xpcshell tests won't display the entire contents so log the incorrect
+    // line.
+    for (let i = 0; i < aryLog.length; ++i) {
+      if (aryCompare[i] != aryLog[i]) {
+        logTestInfo("the first incorrect line in the log is: " + aryLog[i]);
+        do_check_eq(aryCompare[i], aryLog[i]);
+      }
+    }
+    // This should never happen!
+    do_throw("Unable to find incorrect log contents!");
   }
 }
 
 /**
  * Helper function to check if the update log contains a string.
  *
  * @param   aCheckString
  *          The string to check if the update log contains.
@@ -2484,17 +2509,16 @@ function checkUpdateLogContains(aCheckSt
   let updateLog = getUpdatesPatchDir();
   updateLog.append(FILE_UPDATE_LOG);
   let updateLogContents = readFileBytes(updateLog);
   if (updateLogContents.indexOf(aCheckString) != -1) {
     debugDump("log file does contain: " + aCheckString);
     do_check_true(true);
   } else {
     logTestInfo("log file does not contain: " + aCheckString);
-    logTestInfo("log file contents:\n" + updateLogContents);
     do_check_true(false);
   }
 }
 
 /**
  * Helper function for updater binary tests for verifying the state of files and
  * directories after a successful update.
  *
@@ -3015,17 +3039,17 @@ xhr.prototype = {
   _onload: null,
   set onload(aValue) { gXHR._onload = makeHandler(aValue); },
   get onload() { return gXHR._onload; },
   addEventListener: function(aEvent, aValue, aCapturing) {
     eval("gXHR._on" + aEvent + " = aValue");
   },
   flags: Ci.nsIClassInfo.SINGLETON,
   implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
-  getHelperForLanguage: function(aLanguage) null,
+  getScriptableHelper: function() null,
   getInterfaces: function(aCount) {
     let interfaces = [Ci.nsISupports];
     aCount.value = interfaces.length;
     return interfaces;
   },
   classDescription: "XMLHttpRequest",
   contractID: "@mozilla.org/xmlextras/xmlhttprequest;1",
   classID: Components.ID("{c9b37f43-4278-4304-a5e0-600991ab08cb}"),
@@ -3073,17 +3097,17 @@ function UpdatePrompt() {
                      Array.prototype.slice.call(arguments));
     }
   });
 }
 
 UpdatePrompt.prototype = {
   flags: Ci.nsIClassInfo.SINGLETON,
   implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
-  getHelperForLanguage: function(aLanguage) null,
+  getScriptableHelper: function() null,
   getInterfaces: function(aCount) {
     let interfaces = [Ci.nsISupports, Ci.nsIUpdatePrompt];
     aCount.value = interfaces.length;
     return interfaces;
   },
   classDescription: "UpdatePrompt",
   contractID: "@mozilla.org/updates/update-prompt;1",
   classID: Components.ID("{8c350a15-9b90-4622-93a1-4d320308664b}"),
deleted file mode 100644
--- a/toolkit/mozapps/update/tests/unit_aus_update/updateHealthReport.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-Cu.import("resource://gre/modules/Metrics.jsm");
-Cu.import("resource://gre/modules/UpdaterHealthProvider.jsm");
-
-// Create a profile
-let gProfile = do_get_profile();
-
-function run_test() {
-  run_next_test();
-}
-
-add_test(function test_constructor() {
-  let provider = new UpdateProvider();
-  run_next_test();
-});
-
-add_task(function test_init() {
-  let storage = yield Metrics.Storage("init");
-  let provider = new UpdateProvider();
-  yield provider.init(storage);
-  yield provider.shutdown();
-
-  yield storage.close();
-});
-
-add_task(function test_collect() {
-  let storage = yield Metrics.Storage("collect");
-  let provider = new UpdateProvider();
-  yield provider.init(storage);
-
-  let now = new Date();
-
-  let m = provider.getMeasurement("update", 1);
-
-  let fieldcount = 0;
-  for (let field of ["updateCheckStart",
-                     "updateCheckSuccess",
-                     "completeUpdateStart",
-                     "partialUpdateStart",
-                     "completeUpdateSuccess",
-                     "partialUpdateSuccess"]) {
-    fieldcount++; // One new day per iteration
-
-    yield provider.recordUpdate(field, 0);
-
-    let data = yield m.getValues();
-    do_check_eq(data.days.size, 1);
-
-    let day = data.days.getDay(now);
-    do_check_eq(day.size, fieldcount);
-    do_check_eq(day.get(field + "Count"), 1);
-
-    yield provider.recordUpdate(field, 0);
-
-    data = yield m.getValues();
-    day = data.days.getDay(now);
-    do_check_eq(day.size, fieldcount);
-    do_check_eq(day.get(field + "Count"), 2);
-  }
-
-  for (let field of ["updateCheckFailed", "updateFailed"]) {
-    fieldcount += 2; // Two fields added per iteration
-
-    yield provider.recordUpdate(field, 500);
-
-    let data = yield m.getValues();
-    let day = data.days.getDay(now);
-    do_check_eq(day.size, fieldcount);
-
-    do_check_eq(day.get(field + "Statuses"), 500);
-
-    yield provider.recordUpdate(field, 800);
-
-    data = yield m.getValues();
-    day = data.days.getDay(now);
-    do_check_eq(day.size, fieldcount);
-    do_check_eq(day.get(field + "Statuses")[0], 500);
-    do_check_eq(day.get(field + "Statuses")[1], 800);
-  }
-
-  yield provider.shutdown();
-  yield storage.close();
-});
-
--- a/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini
+++ b/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini
@@ -32,10 +32,8 @@ skip-if = toolkit != 'gonk'
 skip-if = toolkit == 'gonk'
 reason = custom nsIUpdatePrompt
 [uiOnlyAllowOneWindow.js]
 skip-if = toolkit == 'gonk'
 reason = custom nsIUpdatePrompt
 [uiUnsupportedAlreadyNotified.js]
 skip-if = toolkit == 'gonk'
 reason = custom nsIUpdatePrompt
-[updateHealthReport.js]
-skip-if = ! healthreport
--- a/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyDirLockedStageFailure_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyDirLockedStageFailure_win.js
@@ -84,10 +84,11 @@ function finishTest() {
   if (IS_WIN || IS_MACOSX) {
     // Check that the post update process was not launched.
     do_check_false(getPostUpdateFile(".running").exists());
   }
 
   do_check_eq(readStatusState(), STATE_PENDING);
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   unlockDirectory(getAppBaseDir());
+  standardInit();
   waitForFilesInUse();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseFallbackStageFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseFallbackStageFailureComplete_win.js
@@ -35,10 +35,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageFailureComplete_win.js
@@ -36,10 +36,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageSuccessComplete_unix.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageSuccessComplete_unix.js
@@ -108,16 +108,17 @@ function finishCheckUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   if (IS_UNIX) {
     checkSymlink();
   }
   checkUpdateLogContents(LOG_COMPLETE_SUCCESS);
+  standardInit();
   checkCallbackAppLog();
 }
 
 function runHelperProcess(args) {
   let helperBin = getTestDirFile(FILE_HELPER_BIN);
   let process = Cc["@mozilla.org/process/util;1"].
                 createInstance(Ci.nsIProcess);
   process.init(helperBin);
--- a/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseSuccessComplete.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseSuccessComplete.js
@@ -48,10 +48,11 @@ function checkUpdate() {
     let now = Date.now();
     let applyToDir = getApplyDirFile();
     let timeDiff = Math.abs(applyToDir.lastModifiedTime - now);
     do_check_true(timeDiff < MAC_MAX_TIME_DIFFERENCE);
   }
 
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
   checkUpdateLogContents(LOG_COMPLETE_SUCCESS);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessComplete_win.js
@@ -18,10 +18,11 @@ function run_test() {
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   runUpdate(0, STATE_SUCCEEDED);
 }
 
 function checkUpdateApplied() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessPartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessPartial_win.js
@@ -18,10 +18,11 @@ function run_test() {
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   runUpdate(0, STATE_SUCCEEDED);
 }
 
 function checkUpdateApplied() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessComplete_win.js
@@ -12,10 +12,11 @@ function run_test() {
 
   gCallbackBinFile = "exe0.exe";
 
   runUpdate(0, STATE_SUCCEEDED);
 }
 
 function checkUpdateApplied() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessPartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessPartial_win.js
@@ -12,10 +12,11 @@ function run_test() {
 
   gCallbackBinFile = "exe0.exe";
 
   runUpdate(0, STATE_SUCCEEDED);
 }
 
 function checkUpdateApplied() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFailurePartial.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFailurePartial.js
@@ -21,17 +21,17 @@ function run_test() {
   if (IS_MACOSX) {
     let now = Date.now();
     let yesterday = now - (1000 * 60 * 60 * 24);
     let applyToDir = getApplyDirFile();
     applyToDir.lastModifiedTime = yesterday;
   }
 
   // Note that on platforms where we use execv, we cannot trust the return code.
-  runUpdate((USE_EXECV ? 0 : 1), STATE_FAILED_UNEXPECTED_FILE_OPERATION_ERROR);
+  runUpdate((USE_EXECV ? 0 : 1), STATE_FAILED_LOADSOURCE_ERROR_WRONG_SIZE);
 }
 
 /**
  * Checks if the update has finished and if it has finished performs checks for
  * the test.
  */
 function checkUpdateApplied() {
   if (IS_WIN || IS_MACOSX) {
@@ -45,10 +45,11 @@ function checkUpdateApplied() {
     let now = Date.now();
     let applyToDir = getApplyDirFile();
     let timeDiff = Math.abs(applyToDir.lastModifiedTime - now);
     do_check_true(timeDiff < MAC_MAX_TIME_DIFFERENCE);
   }
 
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContents(LOG_PARTIAL_FAILURE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseFallbackStageFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseFallbackStageFailureComplete_win.js
@@ -36,10 +36,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseFallbackStageFailurePartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseFallbackStageFailurePartial_win.js
@@ -36,10 +36,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailureComplete_win.js
@@ -37,10 +37,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailurePartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailurePartial_win.js
@@ -37,10 +37,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessComplete_win.js
@@ -1,18 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /* File in use complete MAR file patch apply success test */
 
 function run_test() {
-  // Set to true due to bug 1123503
-  DEBUG_AUS_TEST = true;
-
   setupTestCommon();
   gTestFiles = gTestFilesCompleteSuccess;
   gTestDirs = gTestDirsCompleteSuccess;
   setupUpdaterTest(FILE_COMPLETE_MAR);
 
   // Launch an existing file so it is in use during the update.
   let fileInUseBin = getApplyDirFile(gTestFiles[13].relPathDir +
                                      gTestFiles[13].fileName);
@@ -32,10 +29,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
   checkUpdateLogContains(ERR_BACKUP_DISCARD);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessPartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessPartial_win.js
@@ -29,10 +29,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
   checkUpdateLogContains(ERR_BACKUP_DISCARD);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailureComplete_win.js
@@ -39,10 +39,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailurePartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailurePartial_win.js
@@ -39,10 +39,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_UNABLE_OPEN_DEST);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFallbackStageFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFallbackStageFailureComplete_win.js
@@ -30,25 +30,26 @@ function run_test() {
                         createInstance(Ci.nsIProcess);
   lockFileProcess.init(helperBin);
   lockFileProcess.run(false, args, args.length);
 
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdate(1, STATE_FAILED_WRITE_ERROR, null);
+  runUpdate(1, STATE_FAILED_WRITE_ERROR_FILE_COPY, null);
 
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   runUpdate(1, STATE_PENDING);
 }
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFallbackStageFailurePartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFallbackStageFailurePartial_win.js
@@ -30,25 +30,26 @@ function run_test() {
                         createInstance(Ci.nsIProcess);
   lockFileProcess.init(helperBin);
   lockFileProcess.run(false, args, args.length);
 
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdate(1, STATE_FAILED_WRITE_ERROR, null);
+  runUpdate(1, STATE_FAILED_WRITE_ERROR_FILE_COPY, null);
 
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   runUpdate(1, STATE_PENDING);
 }
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailureComplete_win.js
@@ -30,26 +30,27 @@ function run_test() {
                         createInstance(Ci.nsIProcess);
   lockFileProcess.init(helperBin);
   lockFileProcess.run(false, args, args.length);
 
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdate(1, STATE_FAILED_WRITE_ERROR, null);
+  runUpdate(1, STATE_FAILED_WRITE_ERROR_FILE_COPY, null);
 
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   gDisableReplaceFallback = true;
   runUpdate(1, STATE_FAILED_WRITE_ERROR);
 }
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailurePartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailurePartial_win.js
@@ -30,26 +30,27 @@ function run_test() {
                         createInstance(Ci.nsIProcess);
   lockFileProcess.init(helperBin);
   lockFileProcess.run(false, args, args.length);
 
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdate(1, STATE_FAILED_WRITE_ERROR, null);
+  runUpdate(1, STATE_FAILED_WRITE_ERROR_FILE_COPY, null);
 
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   gDisableReplaceFallback = true;
   runUpdate(1, STATE_FAILED_WRITE_ERROR);
 }
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseFallbackStageFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseFallbackStageFailureComplete_win.js
@@ -47,10 +47,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseFallbackStageFailurePartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseFallbackStageFailurePartial_win.js
@@ -45,10 +45,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailureComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailureComplete_win.js
@@ -48,10 +48,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailurePartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailurePartial_win.js
@@ -46,10 +46,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessComplete_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessComplete_win.js
@@ -39,10 +39,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
   checkUpdateLogContains(ERR_BACKUP_DISCARD);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessPartial_win.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessPartial_win.js
@@ -37,10 +37,11 @@ function doUpdate() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
   checkUpdateLogContains(ERR_BACKUP_DISCARD);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marStageFailurePartial.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marStageFailurePartial.js
@@ -21,25 +21,26 @@ function run_test() {
   // the precomplete file in the root of the bundle is renamed, etc. (bug 600098).
   if (IS_MACOSX) {
     let now = Date.now();
     let yesterday = now - (1000 * 60 * 60 * 24);
     let applyToDir = getApplyDirFile();
     applyToDir.lastModifiedTime = yesterday;
   }
 
-  runUpdate(1, STATE_FAILED_UNEXPECTED_FILE_OPERATION_ERROR);
+  runUpdate(1, STATE_FAILED_LOADSOURCE_ERROR_WRONG_SIZE);
 }
 
 /**
  * Checks if the update has finished and if it has finished performs checks for
  * the test.
  */
 function checkUpdateApplied() {
   if (IS_WIN || IS_MACOSX) {
     // Check that the post update process was not launched.
     do_check_false(getPostUpdateFile(".running").exists());
   }
 
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContents(LOG_PARTIAL_FAILURE);
+  standardInit();
   waitForFilesInUse();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessComplete.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessComplete.js
@@ -113,16 +113,17 @@ function finishCheckUpdateApplied() {
     checkUpdateLogContains("removing old distribution directory");
   }
 
   if (IS_UNIX && !IS_MACOSX) {
     checkSymlink();
   }
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
   checkUpdateLogContents(LOG_COMPLETE_SUCCESS);
+  standardInit();
   checkCallbackAppLog();
 }
 
 function runHelperProcess(args) {
   let helperBin = getTestDirFile(FILE_HELPER_BIN);
   let process = Cc["@mozilla.org/process/util;1"].
                 createInstance(Ci.nsIProcess);
   process.init(helperBin);
--- a/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessPartial.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessPartial.js
@@ -106,10 +106,11 @@ function finishCheckUpdateApplied() {
     debugDump("testing that files aren't added with an add-if instruction " +
               "when the file's destination directory doesn't exist");
     debugDump("testing " + distributionDir.path + " shouldn't exist");
     do_check_false(distributionDir.exists());
   }
 
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
   checkUpdateLogContents(LOG_PARTIAL_SUCCESS, true);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marSuccessComplete.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marSuccessComplete.js
@@ -86,10 +86,11 @@ function finishCheckUpdateApplied() {
     debugDump("testing that files aren't added with an add-if instruction " +
               "when the file's destination directory doesn't exist");
     debugDump("testing " + distributionDir.path + " shouldn't exist");
     do_check_false(distributionDir.exists());
   }
 
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
   checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartial.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartial.js
@@ -76,10 +76,11 @@ function finishCheckUpdateApplied() {
     debugDump("testing " + distributionDir.path + " shouldn't exist");
     do_check_false(distributionDir.exists());
 
     checkUpdateLogContains("removing old distribution directory");
   }
 
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
   checkUpdateLogContents(LOG_PARTIAL_SUCCESS);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marVersionDowngrade.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marVersionDowngrade.js
@@ -32,10 +32,11 @@ function run_test() {
  */
 function checkUpdateApplied() {
   if (IS_WIN || IS_MACOSX) {
     // Check that the post update process was not launched.
     do_check_false(getPostUpdateFile(".running").exists());
   }
 
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   doTestFinish();
 }
--- a/toolkit/mozapps/update/tests/unit_base_updater/marWrongChannel.js
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marWrongChannel.js
@@ -32,10 +32,11 @@ function run_test() {
  */
 function checkUpdateApplied() {
   if (IS_WIN || IS_MACOSX) {
     // Check that the post update process was not launched.
     do_check_false(getPostUpdateFile(".running").exists());
   }
 
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   doTestFinish();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marAppApplyDirLockedStageFailureSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marAppApplyDirLockedStageFailureSvc_win.js
@@ -90,10 +90,11 @@ function finishTest() {
     debugDump("checking that the post update process running file doesn't " +
               "exist. Path: " + running.path);
     do_check_false(running.exists());
   }
 
   do_check_eq(readStatusState(), STATE_PENDING);
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   unlockDirectory(getAppBaseDir());
+  standardInit();
   waitForFilesInUse();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marAppInUseFallbackStageFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marAppInUseFallbackStageFailureCompleteSvc_win.js
@@ -45,10 +45,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marAppInUseStageFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marAppInUseStageFailureCompleteSvc_win.js
@@ -46,10 +46,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marAppInUseSuccessCompleteSvc.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marAppInUseSuccessCompleteSvc.js
@@ -56,10 +56,11 @@ function checkUpdate() {
     let now = Date.now();
     let applyToDir = getApplyDirFile();
     let timeDiff = Math.abs(applyToDir.lastModifiedTime - now);
     do_check_true(timeDiff < MAC_MAX_TIME_DIFFERENCE);
   }
 
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
   checkUpdateLogContents(LOG_COMPLETE_SUCCESS);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppStageSuccessCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppStageSuccessCompleteSvc_win.js
@@ -1,18 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /* Replace app binary complete MAR file staged patch apply success test */
 
 function run_test() {
-  // Set to true due to bug 1037599
-  DEBUG_AUS_TEST = true;
-
   if (!shouldRunServiceTest()) {
     return;
   }
 
   gStageUpdate = true;
   setupTestCommon();
   gTestFiles = gTestFilesCompleteSuccess;
   gTestDirs = gTestDirsCompleteSuccess;
@@ -31,10 +28,11 @@ function checkUpdateFinished() {
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   runUpdate(0, STATE_SUCCEEDED);
 }
 
 function checkUpdateApplied() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppStageSuccessPartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppStageSuccessPartialSvc_win.js
@@ -28,10 +28,11 @@ function checkUpdateFinished() {
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   runUpdate(0, STATE_SUCCEEDED);
 }
 
 function checkUpdateApplied() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppSuccessCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppSuccessCompleteSvc_win.js
@@ -20,10 +20,11 @@ function run_test() {
 }
 
 function setupAppFilesFinished() {
   runUpdateUsingService(STATE_PENDING_SVC, STATE_SUCCEEDED);
 }
 
 function checkUpdateFinished() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppSuccessPartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marCallbackAppSuccessPartialSvc_win.js
@@ -20,10 +20,11 @@ function run_test() {
 }
 
 function setupAppFilesFinished() {
   runUpdateUsingService(STATE_PENDING_SVC, STATE_SUCCEEDED);
 }
 
 function checkUpdateFinished() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, false);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFailurePartialSvc.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFailurePartialSvc.js
@@ -28,17 +28,18 @@ function run_test() {
     let applyToDir = getApplyDirFile();
     applyToDir.lastModifiedTime = yesterday;
   }
 
   setupAppFilesAsync();
 }
 
 function setupAppFilesFinished() {
-  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED);
+  runUpdateUsingService(STATE_PENDING_SVC,
+                        STATE_FAILED_LOADSOURCE_ERROR_WRONG_SIZE);
 }
 
 /**
  * Checks if the update has finished and if it has finished performs checks for
  * the test.
  */
 function checkUpdateFinished() {
   if (IS_MACOSX) {
@@ -54,10 +55,11 @@ function checkUpdateFinished() {
     let running = getPostUpdateFile(".running");
     debugDump("checking that the post update process running file doesn't " +
               "exist. Path: " + running.path);
     do_check_false(running.exists());
   }
 
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContents(LOG_PARTIAL_FAILURE);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseFallbackStageFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseFallbackStageFailureCompleteSvc_win.js
@@ -46,10 +46,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseFallbackStageFailurePartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseFallbackStageFailurePartialSvc_win.js
@@ -46,10 +46,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseStageFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseStageFailureCompleteSvc_win.js
@@ -47,10 +47,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseStageFailurePartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseStageFailurePartialSvc_win.js
@@ -47,10 +47,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseSuccessCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseSuccessCompleteSvc_win.js
@@ -37,10 +37,11 @@ function doUpdate() {
 
 function checkUpdateFinished() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
   checkUpdateLogContains(ERR_BACKUP_DISCARD);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseSuccessPartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileInUseSuccessPartialSvc_win.js
@@ -37,10 +37,11 @@ function doUpdate() {
 
 function checkUpdateFinished() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
   checkUpdateLogContains(ERR_BACKUP_DISCARD);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFailureCompleteSvc_win.js
@@ -37,20 +37,21 @@ function run_test() {
   setupAppFilesAsync();
 }
 
 function setupAppFilesFinished() {
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED);
+  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED_WRITE_ERROR);
 }
 
 function checkUpdateFinished() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFailurePartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFailurePartialSvc_win.js
@@ -37,20 +37,21 @@ function run_test() {
   setupAppFilesAsync();
 }
 
 function setupAppFilesFinished() {
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED);
+  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED_READ_ERROR);
 }
 
 function checkUpdateFinished() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_UNABLE_OPEN_DEST);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFallbackStageFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFallbackStageFailureCompleteSvc_win.js
@@ -38,27 +38,28 @@ function run_test() {
   setupAppFilesAsync();
 }
 
 function setupAppFilesFinished() {
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED);
+  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED_WRITE_ERROR_FILE_COPY);
 }
 
 function checkUpdateFinished() {
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   runUpdate(1, STATE_PENDING);
 }
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFallbackStageFailurePartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedFallbackStageFailurePartialSvc_win.js
@@ -38,27 +38,28 @@ function run_test() {
   setupAppFilesAsync();
 }
 
 function setupAppFilesFinished() {
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED);
+  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED_WRITE_ERROR_FILE_COPY);
 }
 
 function checkUpdateFinished() {
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   runUpdate(1, STATE_PENDING);
 }
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedStageFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedStageFailureCompleteSvc_win.js
@@ -38,17 +38,17 @@ function run_test() {
   setupAppFilesAsync();
 }
 
 function setupAppFilesFinished() {
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED);
+  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED_WRITE_ERROR_FILE_COPY);
 }
 
 function checkUpdateFinished() {
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   gDisableReplaceFallback = true;
   runUpdate(1, STATE_FAILED_WRITE_ERROR);
@@ -56,10 +56,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedStageFailurePartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marFileLockedStageFailurePartialSvc_win.js
@@ -38,17 +38,17 @@ function run_test() {
   setupAppFilesAsync();
 }
 
 function setupAppFilesFinished() {
   do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
 }
 
 function doUpdate() {
-  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED);
+  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED_WRITE_ERROR_FILE_COPY);
 }
 
 function checkUpdateFinished() {
   // Switch the application to the staged application that was updated.
   gStageUpdate = false;
   gSwitchApp = true;
   gDisableReplaceFallback = true;
   runUpdate(1, STATE_FAILED_WRITE_ERROR);
@@ -56,10 +56,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseFallbackStageFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseFallbackStageFailureCompleteSvc_win.js
@@ -1,19 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /* File in use inside removed dir complete MAR file staged patch apply failure
    fallback test */
 
 function run_test() {
-  // Set to true due to bug 1123503
-  DEBUG_AUS_TEST = true;
-
   if (!shouldRunServiceTest()) {
     return;
   }
 
   gStageUpdate = true;
   setupTestCommon();
   gTestFiles = gTestFilesCompleteSuccess;
   gTestDirs = gTestDirsCompleteSuccess;
@@ -60,10 +57,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseFallbackStageFailurePartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseFallbackStageFailurePartialSvc_win.js
@@ -1,19 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /* File in use inside removed dir partial MAR file staged patch apply failure
    fallback test */
 
 function run_test() {
-  // Set to true due to bug 1112284
-  DEBUG_AUS_TEST = true;
-
   if (!shouldRunServiceTest()) {
     return;
   }
 
   gStageUpdate = true;
   setupTestCommon();
   gTestFiles = gTestFilesPartialSuccess;
   gTestDirs = gTestDirsPartialSuccess;
@@ -58,10 +55,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, false, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseStageFailureCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseStageFailureCompleteSvc_win.js
@@ -1,19 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /* File in use inside removed dir complete MAR file staged patch apply failure
    test */
 
 function run_test() {
-  // Set to true due to bug 1123503
-  DEBUG_AUS_TEST = true;
-
   if (!shouldRunServiceTest()) {
     return;
   }
 
   gStageUpdate = true;
   setupTestCommon();
   gTestFiles = gTestFilesCompleteSuccess;
   gTestDirs = gTestDirsCompleteSuccess;
@@ -61,10 +58,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseStageFailurePartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseStageFailurePartialSvc_win.js
@@ -1,19 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 /* File in use inside removed dir partial MAR file staged patch apply failure
    test */
 
 function run_test() {
-  // Set to true due to bug 1112284
-  DEBUG_AUS_TEST = true;
-
   if (!shouldRunServiceTest()) {
     return;
   }
 
   gStageUpdate = true;
   setupTestCommon();
   gTestFiles = gTestFilesPartialSuccess;
   gTestDirs = gTestDirsPartialSuccess;
@@ -59,10 +56,11 @@ function checkUpdateFinished() {
 
 function checkUpdateApplied() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContains(ERR_RENAME_FILE);
+  standardInit();
   checkCallbackAppLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseSuccessCompleteSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseSuccessCompleteSvc_win.js
@@ -47,10 +47,11 @@ function doUpdate() {
 
 function checkUpdateFinished() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
   checkUpdateLogContains(ERR_BACKUP_DISCARD);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseSuccessPartialSvc_win.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marRMRFDirFileInUseSuccessPartialSvc_win.js
@@ -45,10 +45,11 @@ function doUpdate() {
 
 function checkUpdateFinished() {
   setupHelperFinish();
 }
 
 function checkUpdate() {
   checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
   checkUpdateLogContains(ERR_BACKUP_DISCARD);
+  standardInit();
   checkCallbackServiceLog();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marStageFailurePartialSvc.js
+++ b/toolkit/mozapps/update/tests/unit_service_updater/marStageFailurePartialSvc.js
@@ -1,19 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 /* General Partial MAR File Staged Patch Apply Failure Test */
 
 function run_test() {
-  // Set to true due to bug 1109219
-  DEBUG_AUS_TEST = true;
-
   if (!shouldRunServiceTest()) {
     return;
   }
 
   gStageUpdate = true;
   setupTestCommon();
   gTestFiles = gTestFilesPartialSuccess;
   gTestFiles[11].originalFile = "partial.png";
@@ -32,27 +29,29 @@ function run_test() {
     let applyToDir = getApplyDirFile();
     applyToDir.lastModifiedTime = yesterday;
   }
 
   setupAppFilesAsync();
 }
 
 function setupAppFilesFinished() {
-  runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED);
+  runUpdateUsingService(STATE_PENDING_SVC,
+                        STATE_FAILED_LOADSOURCE_ERROR_WRONG_SIZE);
 }
 
 /**
  * Checks if the update has finished and if it has finished performs checks for
  * the test.
  */
 function checkUpdateFinished() {
   if (IS_WIN || IS_MACOSX) {
     let running = getPostUpdateFile(".running");
     debugDump("checking that the post update process running file doesn't " +
               "exist. Path: " + running.path);
     do_check_false(running.exists());
   }
 
   checkFilesAfterUpdateFailure(getApplyDirFile, true, false);
   checkUpdateLogContents(LOG_PARTIAL_FAILURE);
+  standardInit();
   waitForFilesInUse();
 }
--- a/toolkit/mozapps/update/tests/unit_service_updater/marStageSuccessCompleteSvc.js