Merge m-c to a CLOSED TREE m-i
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 23 Aug 2016 22:57:10 -0700
changeset 341694 d015148149e85fe4b3769f3edf7108b89fe57520
parent 341693 d7bf236adf776c24982d1b5c7553df9a78761ef6 (current diff)
parent 341660 bd7645928990649c84609d3f531e803c2d41f269 (diff)
child 341696 bfbb874b4641d775af2db1c69f3b1ec696aaf177
push id5
push userfmarier@mozilla.com
push dateFri, 26 Aug 2016 00:45:46 +0000
milestone51.0a1
Merge m-c to a CLOSED TREE m-i
image/imgIContainer.idl
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -261,16 +261,27 @@ toolbar[customizing] > .overflow-button 
 }
 
 #titlebar-secondary-buttonbox:-moz-locale-dir(rtl),
 #titlebar-buttonbox-container:-moz-locale-dir(ltr),
 .titlebar-placeholder[type="caption-buttons"]:-moz-locale-dir(ltr),
 .titlebar-placeholder[type="fullscreen-button"]:-moz-locale-dir(rtl) {
   -moz-box-ordinal-group: 0;
 }
+
+/* In private windows, the #titlebar-content is higher because of the
+ * private browsing indicator. With the margin-top the titlebar buttons
+ * align to the top correctly in that case, but only if we don't stretch
+ * the box they're in because the container is too high, so we override
+ * the default alignment value (stretch).
+ */
+#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-buttonbox-container {
+  -moz-box-align: start;
+}
+
 %else
 /* On non-OSX, these should be start-aligned */
 #titlebar-buttonbox-container {
   -moz-box-align: start;
 }
 %endif
 
 %if !defined(MOZ_WIDGET_GTK)
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -710,22 +710,22 @@ nsDefaultCommandLineHandler.prototype = 
 
   /* nsICommandLineHandler */
   handle : function dch_handle(cmdLine) {
     // The -url flag is inserted by the operating system when the default
     // application handler is used. We check for default browser to remove
     // instances where users explicitly decide to "open with" the browser.
     // Note that users who launch firefox manually with the -url flag will
     // get erroneously counted.
-    if (cmdLine.findFlag("url", false) &&
-        ShellService.isDefaultBrowser(false, false)) {
-      try {
+    try {
+      if (cmdLine.findFlag("url", false) &&
+          ShellService.isDefaultBrowser(false, false)) {
         Services.telemetry.getHistogramById("FX_STARTUP_EXTERNAL_CONTENT_HANDLER").add();
-      } catch (e) {}
-    }
+      }
+    } catch (e) {}
 
     var urilist = [];
 
     if (AppConstants.platform == "win") {
       // If we don't have a profile selected yet (e.g. the Profile Manager is
       // displayed) we will crash if we open an url and then select a profile. To
       // prevent this handle all url command line flags and set the command line's
       // preventDefault to true to prevent the display of the ui. The initial
--- a/browser/components/shell/ShellService.jsm
+++ b/browser/components/shell/ShellService.jsm
@@ -96,12 +96,18 @@ let ShellServiceInternal = {
 XPCOMUtils.defineLazyServiceGetter(ShellServiceInternal, "shellService",
   "@mozilla.org/browser/shell-service;1", Ci.nsIShellService);
 
 /**
  * The external API exported by this module.
  */
 this.ShellService = new Proxy(ShellServiceInternal, {
   get(target, name) {
-    return name in target ? target[name] :
-                            target.shellService[name];
+    if (name in target) {
+      return target[name];
+    }
+    if (target.shellService) {
+      return target.shellService[name];
+    }
+    Services.console.logStringMessage(`${name} not found in ShellService: ${target.shellService}`);
+    return undefined;
   }
 });
--- a/browser/themes/osx/devedition.css
+++ b/browser/themes/osx/devedition.css
@@ -27,26 +27,16 @@
 }
 
 /* Resize things so that the native titlebar is in line with the tabs */
 #main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-buttonbox-container,
 #main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-secondary-buttonbox > #titlebar-fullscreen-button {
   margin-top: 6px;
 }
 
-/* In private windows, the #titlebar-content is higher because of the
- * private browsing indicator. With the margin-top the titlebar buttons
- * align to the top correctly in that case, but only if we don't stretch
- * the box they're in because the container is too high, so we override
- * the default alignment value (stretch).
- */
-#main-window[tabsintitlebar] > #titlebar > #titlebar-content > #titlebar-buttonbox-container {
-  -moz-box-align: start;
-}
-
 /* Square back and forward buttons.  Need !important on these because there
    are a lot of more specific selectors sprinkled around elsewhere for changing
    background / shadows for different states */
 #back-button,
 #forward-button {
   height: 24px !important;
   box-shadow: none !important;
   border: 1px solid var(--chrome-nav-bar-controls-border-color) !important;
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_BasePrincipal_h
 #define mozilla_BasePrincipal_h
 
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsJSPrincipals.h"
 
+#include "mozilla/Attributes.h"
 #include "mozilla/dom/ChromeUtilsBinding.h"
 
 class nsIContentSecurityPolicy;
 class nsIObjectOutputStream;
 class nsIObjectInputStream;
 class nsIURI;
 
 class nsExpandedPrincipal;
@@ -40,21 +41,21 @@ public:
   {
     return !(*this == aOther);
   }
 
   // Serializes/Deserializes non-default values into the suffix format, i.e.
   // |!key1=value1&key2=value2|. If there are no non-default attributes, this
   // returns an empty string.
   void CreateSuffix(nsACString& aStr) const;
-  bool PopulateFromSuffix(const nsACString& aStr);
+  MOZ_MUST_USE bool PopulateFromSuffix(const nsACString& aStr);
 
   // Populates the attributes from a string like
   // |uri!key1=value1&key2=value2| and returns the uri without the suffix.
-  bool PopulateFromOrigin(const nsACString& aOrigin,
+  MOZ_MUST_USE bool PopulateFromOrigin(const nsACString& aOrigin,
                           nsACString& aOriginNoSuffix);
 
   // Helper function to match mIsPrivateBrowsing to existing private browsing
   // flags. Once all other flags are removed, this can be removed too.
   void SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing);
 
 protected:
   OriginAttributes() {}
--- a/caps/nsJSPrincipals.cpp
+++ b/caps/nsJSPrincipals.cpp
@@ -134,17 +134,19 @@ ReadSuffixAndSpec(JSStructuredCloneReade
     }
 
     nsAutoCString suffix;
     suffix.SetLength(suffixLength);
     if (!JS_ReadBytes(aReader, suffix.BeginWriting(), suffixLength)) {
         return false;
     }
 
-    aAttrs.PopulateFromSuffix(suffix);
+    if (!aAttrs.PopulateFromSuffix(suffix)) {
+        return false;
+    }
 
     aSpec.SetLength(specLength);
     if (!JS_ReadBytes(aReader, aSpec.BeginWriting(), specLength)) {
         return false;
     }
 
     return true;
 }
--- a/caps/tests/gtest/TestOriginAttributes.cpp
+++ b/caps/tests/gtest/TestOriginAttributes.cpp
@@ -8,17 +8,18 @@ using mozilla::PrincipalOriginAttributes
 
 static void
 TestSuffix(const PrincipalOriginAttributes& attrs)
 {
   nsAutoCString suffix;
   attrs.CreateSuffix(suffix);
 
   PrincipalOriginAttributes attrsFromSuffix;
-  attrsFromSuffix.PopulateFromSuffix(suffix);
+  bool success = attrsFromSuffix.PopulateFromSuffix(suffix);
+  EXPECT_TRUE(success);
 
   EXPECT_EQ(attrs, attrsFromSuffix);
 }
 
 TEST(PrincipalOriginAttributes, Suffix_default)
 {
   PrincipalOriginAttributes attrs;
   TestSuffix(attrs);
--- a/devtools/client/shared/shim/Services.js
+++ b/devtools/client/shared/shim/Services.js
@@ -421,19 +421,23 @@ PrefBranch.prototype = {
       thePref._storageUpdated(type, userValue, hasUserValue, defaultValue);
     }
   },
 
   /**
    * Helper function to initialize the root PrefBranch.
    */
   _initializeRoot: function () {
-    if (localStorage.length === 0) {
-      // FIXME - this is where we'll load devtools.js to install the
-      // default prefs.
+    if (localStorage.length === 0 && Services._defaultPrefsEnabled) {
+      /* eslint-disable no-eval */
+      let devtools = require("raw!prefs!devtools/client/preferences/devtools");
+      eval(devtools);
+      let all = require("raw!prefs!modules/libpref/init/all");
+      eval(all);
+      /* eslint-enable no-eval */
     }
 
     // Read the prefs from local storage and create the local
     // representations.
     for (let i = 0; i < localStorage.length; ++i) {
       let keyName = localStorage.key(i);
       if (keyName.startsWith(PREFIX)) {
         let {userValue, hasUserValue, defaultValue} =
@@ -444,22 +448,35 @@ PrefBranch.prototype = {
     }
 
     this._onStorageChange = this._onStorageChange.bind(this);
     window.addEventListener("storage", this._onStorageChange);
   },
 };
 
 const Services = {
+  _prefs: null,
+
+  // For use by tests.  If set to false before Services.prefs is used,
+  // this will disable the reading of the default prefs.
+  _defaultPrefsEnabled: true,
+
   /**
    * An implementation of nsIPrefService that is based on local
    * storage.  Only the subset of nsIPrefService that is actually used
-   * by devtools is implemented here.
+   * by devtools is implemented here.  This is lazily instantiated so
+   * that the tests have a chance to disable the loading of default
+   * prefs.
    */
-  prefs: new PrefBranch(null, "", ""),
+  get prefs() {
+    if (!this._prefs) {
+      this._prefs = new PrefBranch(null, "", "");
+    }
+    return this._prefs;
+  },
 
   /**
    * An implementation of Services.appinfo that holds just the
    * properties needed by devtools.
    */
   appinfo: {
     get OS() {
       const os = window.navigator.userAgent;
@@ -577,12 +594,10 @@ const Services = {
  * @param {Any} value the default value of the preference
  */
 function pref(name, value) {
   let thePref = Services.prefs._findOrCreatePref(name, value, true, value);
   thePref._setDefault(value);
 }
 
 module.exports = Services;
-// This is exported to silence eslint and, at some point, perhaps to
-// provide it when loading devtools.js in order to install the default
-// preferences.
+// This is exported to silence eslint.
 exports.pref = pref;
--- a/devtools/client/shared/shim/test/test_service_prefs.html
+++ b/devtools/client/shared/shim/test/test_service_prefs.html
@@ -47,16 +47,19 @@ localStorage.setItem("Services.prefs:dev
   <script type="application/javascript;version=1.8"
 	  src="resource://devtools/client/shared/shim/Services.js"></script>
 </head>
 <body>
 <script type="application/javascript;version=1.8">
 "use strict";
 
 function do_tests() {
+  // We can't load the defaults in this context.
+  Services._defaultPrefsEnabled = false;
+
   is(Services.prefs.getBoolPref("devtools.branch1.somebool"), false,
     "bool pref value");
   Services.prefs.setBoolPref("devtools.branch1.somebool", true);
   is(Services.prefs.getBoolPref("devtools.branch1.somebool"), true,
     "bool pref value after setting");
 
   let threw;
 
--- a/docshell/base/SerializedLoadContext.h
+++ b/docshell/base/SerializedLoadContext.h
@@ -82,17 +82,15 @@ struct ParamTraits<SerializedLoadContext
     if (!ReadParam(aMsg, aIter, &aResult->mIsNotNull) ||
         !ReadParam(aMsg, aIter, &aResult->mIsContent) ||
         !ReadParam(aMsg, aIter, &aResult->mIsPrivateBitValid) ||
         !ReadParam(aMsg, aIter, &aResult->mUsePrivateBrowsing) ||
         !ReadParam(aMsg, aIter, &aResult->mUseRemoteTabs) ||
         !ReadParam(aMsg, aIter, &suffix)) {
       return false;
     }
-    aResult->mOriginAttributes.PopulateFromSuffix(suffix);
-
-    return true;
+    return aResult->mOriginAttributes.PopulateFromSuffix(suffix);
   }
 };
 
 } // namespace IPC
 
 #endif // SerializedLoadContext_h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2431,17 +2431,18 @@ ContentChild::RecvAddPermission(const IP
     static_cast<nsPermissionManager*>(permissionManagerIface.get());
   MOZ_ASSERT(permissionManager,
          "We have no permissionManager in the Content process !");
 
   // note we do not need to force mUserContextId to the default here because
   // the permission manager does that internally.
   nsAutoCString originNoSuffix;
   PrincipalOriginAttributes attrs;
-  attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
+  bool success = attrs.PopulateFromOrigin(permission.origin, originNoSuffix);
+  NS_ENSURE_TRUE(success, false);
 
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
   NS_ENSURE_SUCCESS(rv, true);
 
   nsCOMPtr<nsIPrincipal> principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs);
 
   // child processes don't care about modification time.
--- a/dom/ipc/TabContext.cpp
+++ b/dom/ipc/TabContext.cpp
@@ -364,17 +364,20 @@ MaybeInvalidTabContext::MaybeInvalidTabC
       isMozBrowserElement = ipcContext.isMozBrowserElement();
       isPrerendered = ipcContext.isPrerendered();
       containingAppId = ipcContext.frameOwnerAppId();
       signedPkgOriginNoSuffix = ipcContext.signedPkgOriginNoSuffix();
       presentationURL = ipcContext.presentationURL();
       showAccelerators = ipcContext.showAccelerators();
       showFocusRings = ipcContext.showFocusRings();
       originSuffix = ipcContext.originSuffix();
-      originAttributes.PopulateFromSuffix(originSuffix);
+      if (!originAttributes.PopulateFromSuffix(originSuffix)) {
+        mInvalidReason = "Populate originAttributes from originSuffix failed.";
+        return;
+      }
       break;
     }
     case IPCTabContext::TUnsafeIPCTabContext: {
       // XXXcatalinb: This used *only* by ServiceWorkerClients::OpenWindow.
       // It is meant as a temporary solution until service workers can
       // provide a TabChild equivalent. Don't allow this on b2g since
       // it might be used to escalate privileges.
 #ifdef MOZ_B2G
--- a/dom/storage/DOMStorageDBThread.cpp
+++ b/dom/storage/DOMStorageDBThread.cpp
@@ -50,17 +50,18 @@ nsCString
 Scheme0Scope(DOMStorageCacheBridge* aCache)
 {
   nsCString result;
 
   nsCString suffix = aCache->OriginSuffix();
 
   PrincipalOriginAttributes oa;
   if (!suffix.IsEmpty()) {
-    oa.PopulateFromSuffix(suffix);
+    DebugOnly<bool> success = oa.PopulateFromSuffix(suffix);
+    MOZ_ASSERT(success);
   }
 
   if (oa.mAppId != nsIScriptSecurityManager::NO_APP_ID || oa.mInIsolatedMozBrowser) {
     result.AppendInt(oa.mAppId);
     result.Append(':');
     result.Append(oa.mInIsolatedMozBrowser ? 't' : 'f');
     result.Append(':');
   }
@@ -758,17 +759,18 @@ OriginAttrsPatternMatchSQLFunction::OnFu
 {
   nsresult rv;
 
   nsAutoCString suffix;
   rv = aFunctionArguments->GetUTF8String(0, suffix);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PrincipalOriginAttributes oa;
-  oa.PopulateFromSuffix(suffix);
+  bool success = oa.PopulateFromSuffix(suffix);
+  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
   bool result = mPattern.Matches(oa);
 
   RefPtr<nsVariant> outVar(new nsVariant());
   rv = outVar->SetAsBool(result);
   NS_ENSURE_SUCCESS(rv, rv);
 
   outVar.forget(aResult);
   return NS_OK;
--- a/gfx/2d/ScaledFontBase.cpp
+++ b/gfx/2d/ScaledFontBase.cpp
@@ -230,16 +230,17 @@ ScaledFontBase::GetGlyphDesignMetrics(co
         else if (cairo_scaled_font_get_type(mScaledFont) == CAIRO_FONT_TYPE_DWRITE) {
           if (aGlyphMetrics[i].mWidth > 0 && aGlyphMetrics[i].mHeight > 0) {
             aGlyphMetrics[i].mWidth -= 2.0f;
             aGlyphMetrics[i].mXBearing += 1.0f;
           }
         }
 #endif
       }
+      cairo_font_options_destroy(options);
     }
 
   }
 #endif
 
   // Don't know how to get the glyph metrics...
   MOZ_CRASH("The specific backend type is not supported for GetGlyphDesignMetrics.");
 }
--- a/image/DynamicImage.cpp
+++ b/image/DynamicImage.cpp
@@ -190,18 +190,20 @@ DynamicImage::GetFrameAtSize(const IntSi
 
   auto result = Draw(context, aSize, ImageRegion::Create(aSize),
                      aWhichFrame, SamplingFilter::POINT, Nothing(), aFlags);
 
   return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
 }
 
 NS_IMETHODIMP_(bool)
-DynamicImage::WillDrawOpaqueNow()
+DynamicImage::IsOpaque()
 {
+  // XXX(seth): For performance reasons it'd be better to return true here, but
+  // I'm not sure how we can guarantee it for an arbitrary gfxDrawable.
   return false;
 }
 
 NS_IMETHODIMP_(bool)
 DynamicImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
 {
   return false;
 }
--- a/image/ImageWrapper.cpp
+++ b/image/ImageWrapper.cpp
@@ -180,19 +180,19 @@ NS_IMETHODIMP_(already_AddRefed<SourceSu
 ImageWrapper::GetFrameAtSize(const IntSize& aSize,
                              uint32_t aWhichFrame,
                              uint32_t aFlags)
 {
   return mInnerImage->GetFrameAtSize(aSize, aWhichFrame, aFlags);
 }
 
 NS_IMETHODIMP_(bool)
-ImageWrapper::WillDrawOpaqueNow()
+ImageWrapper::IsOpaque()
 {
-  return mInnerImage->WillDrawOpaqueNow();
+  return mInnerImage->IsOpaque();
 }
 
 NS_IMETHODIMP_(bool)
 ImageWrapper::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
 {
   return mInnerImage->IsImageContainerAvailable(aManager, aFlags);
 }
 
--- a/image/OrientedImage.cpp
+++ b/image/OrientedImage.cpp
@@ -84,17 +84,17 @@ OrientedImage::GetFrame(uint32_t aWhichF
   IntSize size;
   rv = InnerImage()->GetWidth(&size.width);
   NS_ENSURE_SUCCESS(rv, nullptr);
   rv = InnerImage()->GetHeight(&size.height);
   NS_ENSURE_SUCCESS(rv, nullptr);
 
   // Determine an appropriate format for the surface.
   gfx::SurfaceFormat surfaceFormat;
-  if (InnerImage()->WillDrawOpaqueNow()) {
+  if (InnerImage()->IsOpaque()) {
     surfaceFormat = gfx::SurfaceFormat::B8G8R8X8;
   } else {
     surfaceFormat = gfx::SurfaceFormat::B8G8R8A8;
   }
 
   // Create a surface to draw into.
   RefPtr<DrawTarget> target =
     gfxPlatform::GetPlatform()->
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -372,17 +372,17 @@ RasterImage::LookupFrame(const IntSize& 
   if (aFlags & (FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST) &&
     result.Surface()->IsAborted()) {
     return DrawableSurface();
   }
 
   return Move(result.Surface());
 }
 
-bool
+NS_IMETHODIMP_(bool)
 RasterImage::IsOpaque()
 {
   if (mError) {
     return false;
   }
 
   Progress progress = mProgressTracker->GetProgress();
 
@@ -390,49 +390,16 @@ RasterImage::IsOpaque()
   if (!(progress & FLAG_DECODE_COMPLETE)) {
     return false;
   }
 
   // Other, we're opaque if FLAG_HAS_TRANSPARENCY is not set.
   return !(progress & FLAG_HAS_TRANSPARENCY);
 }
 
-NS_IMETHODIMP_(bool)
-RasterImage::WillDrawOpaqueNow()
-{
-  if (!IsOpaque()) {
-    return false;
-  }
-
-  if (mAnimationState) {
-    // We never discard frames of animated images.
-    return true;
-  }
-
-  // If we are not locked our decoded data could get discard at any time (ie
-  // between the call to this function and when we are asked to draw), so we
-  // have to return false if we are unlocked.
-  if (IsUnlocked()) {
-    return false;
-  }
-
-  LookupResult result =
-    SurfaceCache::LookupBestMatch(ImageKey(this),
-                                  RasterSurfaceKey(mSize,
-                                                   DefaultSurfaceFlags(),
-                                                   PlaybackType::eStatic));
-  MatchType matchType = result.Type();
-  if (matchType == MatchType::NOT_FOUND || matchType == MatchType::PENDING ||
-      !result.Surface()->IsFinished()) {
-    return false;
-  }
-
-  return true;
-}
-
 void
 RasterImage::OnSurfaceDiscarded()
 {
   MOZ_ASSERT(mProgressTracker);
 
   NS_DispatchToMainThread(NewRunnableMethod(mProgressTracker, &ProgressTracker::OnDiscard));
 }
 
--- a/image/RasterImage.h
+++ b/image/RasterImage.h
@@ -479,18 +479,16 @@ private: // data
     explicit HandleErrorWorker(RasterImage* aImage);
 
     RefPtr<RasterImage> mImage;
   };
 
   // Helpers
   bool CanDiscard();
 
-  bool IsOpaque();
-
 protected:
   explicit RasterImage(ImageURL* aURI = nullptr);
 
   bool ShouldAnimate() override;
 
   friend class ImageFactory;
 };
 
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -673,17 +673,17 @@ VectorImage::GetFirstFrameDelay()
   }
 
   // We don't really have a frame delay, so just pretend that we constantly
   // need updates.
   return 0;
 }
 
 NS_IMETHODIMP_(bool)
-VectorImage::WillDrawOpaqueNow()
+VectorImage::IsOpaque()
 {
   return false; // In general, SVG content is not opaque.
 }
 
 //******************************************************************************
 NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
 VectorImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags)
 {
--- a/image/VectorImage.h
+++ b/image/VectorImage.h
@@ -44,17 +44,17 @@ public:
                                         nsIInputStream* aInStr,
                                         uint64_t aSourceOffset,
                                         uint32_t aCount) override;
   virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
                                        nsISupports* aContext,
                                        nsresult aResult,
                                        bool aLastPart) override;
 
-  virtual void OnSurfaceDiscarded() override;
+  void OnSurfaceDiscarded() override;
 
   /**
    * Callback for SVGRootRenderingObserver.
    *
    * This just sets a dirty flag that we check in VectorImage::RequestRefresh,
    * which is called under the ticks of the refresh driver of any observing
    * documents that we may have. Only then (after all animations in this image
    * have been updated) do we send out "frame changed" notifications,
--- a/image/imgIContainer.idl
+++ b/image/imgIContainer.idl
@@ -259,22 +259,19 @@ interface imgIContainer : nsISupports
    * @param aWhichFrame Frame specifier of the FRAME_* variety.
    * @param aFlags Flags of the FLAG_* variety
    */
   [noscript, notxpcom] TempRefSourceSurface getFrameAtSize([const] in nsIntSize aSize,
                                                            in uint32_t aWhichFrame,
                                                            in uint32_t aFlags);
 
   /**
-   * Returns true if this image will draw opaquely right now if asked to draw
-   * with FLAG_HIGH_QUALITY_SCALING and otherwise default flags. If this image
-   * (when decoded) is opaque but no decoded frames are available then
-   * willDrawOpaqueNow will return false.
+   * Whether this image is opaque (i.e., needs a background painted behind it).
    */
-  [noscript, notxpcom] boolean willDrawOpaqueNow();
+  [notxpcom] boolean isOpaque();
 
   /**
    * @return true if getImageContainer() is expected to return a valid
    *         ImageContainer when passed the given @Manager and @Flags
    *         parameters.
    */
   [noscript, notxpcom] boolean isImageContainerAvailable(in LayerManager aManager,
                                                          in uint32_t aFlags);
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1629,17 +1629,17 @@ nsDisplayImage::GetLayerState(nsDisplayL
 }
 
 
 /* virtual */ nsRegion
 nsDisplayImage::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                 bool* aSnap)
 {
   *aSnap = false;
-  if (mImage && mImage->WillDrawOpaqueNow()) {
+  if (mImage && mImage->IsOpaque()) {
     const nsRect frameContentBox = GetBounds(aSnap);
     return GetDestRect().Intersect(frameContentBox);
   }
   return nsRegion();
 }
 
 already_AddRefed<Layer>
 nsDisplayImage::BuildLayer(nsDisplayListBuilder* aBuilder,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2213,17 +2213,17 @@ nsStyleImage::IsOpaque() const
 
   MOZ_ASSERT(mType == eStyleImageType_Image, "unexpected image type");
 
   nsCOMPtr<imgIContainer> imageContainer;
   mImage->GetImage(getter_AddRefs(imageContainer));
   MOZ_ASSERT(imageContainer, "IsComplete() said image container is ready");
 
   // Check if the crop region of the image is opaque.
-  if (imageContainer->WillDrawOpaqueNow()) {
+  if (imageContainer->IsOpaque()) {
     if (!mCropRect) {
       return true;
     }
 
     // Must make sure if mCropRect contains at least a pixel.
     // XXX Is this optimization worth it? Maybe I should just return false.
     nsIntRect actualCropRect;
     bool rv = ComputeActualCropRect(actualCropRect);
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java
@@ -101,24 +101,26 @@ public class VideoCaptureAndroid impleme
     mCaptureRotation = GetRotateAmount();
   }
 
   @Override
   public synchronized void onPause() {
     if (camera != null) {
       mResumeCapture = true;
       stopCapture();
+      GeckoAppShell.notifyObservers("VideoCapture:Paused", null);
     }
   }
 
   @Override
   public synchronized void onResume() {
     if (mResumeCapture) {
       startCapture(mCaptureWidth, mCaptureHeight, mCaptureMinFPS, mCaptureMaxFPS);
       mResumeCapture = false;
+      GeckoAppShell.notifyObservers("VideoCapture:Resumed", null);
     }
   }
 
   @Override
   public void onOrientationChanged() {
     mCaptureRotation = GetRotateAmount();
   }
 
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -467,35 +467,36 @@ pref("dom.ipc.plugins.enabled", false);
 // the default so that we can migrate a user-set pref. See bug 885357.
 pref("plugins.click_to_play", true);
 // The default value for nsIPluginTag.enabledState (STATE_CLICKTOPLAY = 1)
 pref("plugin.default.state", 1);
 
 // product URLs
 // The breakpad report server to link to in about:crashes
 pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/");
+
 pref("app.support.baseURL", "https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/");
+pref("app.supportURL", "https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/mobile-help");
+pref("app.faqURL", "https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/faq");
 
 // URL for feedback page
 // This should be kept in sync with the "feedback_link" string defined in strings.xml.in
 pref("app.feedbackURL", "https://input.mozilla.org/feedback/android/%VERSION%/%CHANNEL%/?utm_source=feedback-prompt");
 
 pref("app.privacyURL", "https://www.mozilla.org/privacy/firefox/");
 pref("app.creditsURL", "https://www.mozilla.org/credits/");
 pref("app.channelURL", "https://www.mozilla.org/%LOCALE%/firefox/channel/");
 #if MOZ_UPDATE_CHANNEL == aurora
 pref("app.releaseNotesURL", "https://www.mozilla.com/%LOCALE%/mobile/%VERSION%/auroranotes/");
 #elif MOZ_UPDATE_CHANNEL == beta
 pref("app.releaseNotesURL", "https://www.mozilla.com/%LOCALE%/mobile/%VERSION%beta/releasenotes/");
 #else
 pref("app.releaseNotesURL", "https://www.mozilla.com/%LOCALE%/mobile/%VERSION%/releasenotes/");
 #endif
 
-pref("app.faqURL", "https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/faq");
-
 // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
 pref("security.alternate_certificate_error_page", "certerror");
 
 pref("security.warn_viewing_mixed", false); // Warning is disabled.  See Bug 616712.
 
 // Block insecure active content on https pages
 pref("security.mixed_content.block_active_content", true);
 
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -80,18 +80,18 @@
   <string name="crash_email">&crash_email;</string>
   <string name="crash_closing_alert">&crash_closing_alert;</string>
   <string name="sending_crash_report">&sending_crash_report;</string>
   <string name="crash_close_label">&crash_close_label;</string>
   <string name="crash_restart_label">&crash_restart_label;</string>
 
   <string name="url_bar_default_text">&url_bar_default_text2;</string>
 
-  <!-- https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/ -->
-  <string name="help_link">https://support.mozilla.org/1/mobile/&formatS1;/&formatS2;/&formatS3;/</string>
+  <!-- https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/mobile-help -->
+  <string name="help_link">https://support.mozilla.org/1/mobile/&formatS1;/&formatS2;/&formatS3;/mobile-help</string>
   <string name="help_menu">&help_menu;</string>
 
   <string name="quit">&quit;</string>
   <string name="bookmark">&bookmark;</string>
   <string name="bookmark_remove">&bookmark_remove;</string>
   <string name="bookmark_added">&bookmark_added;</string>
   <string name="bookmark_already_added">&bookmark_already_added;</string>
   <string name="bookmark_removed">&bookmark_removed;</string>
--- a/mobile/android/chrome/content/WebrtcUI.js
+++ b/mobile/android/chrome/content/WebrtcUI.js
@@ -41,16 +41,23 @@ var WebrtcUI = {
       this.handlePCRequest(aSubject, aTopic, aData);
     } else if (aTopic === "recording-device-events") {
       switch (aData) {
         case "shutdown":
         case "starting":
           this.notify();
           break;
       }
+    } else if (aTopic === "VideoCapture:Paused") {
+      if (this._notificationId) {
+        Notifications.cancel(this._notificationId);
+        this._notificationId = null;
+      }
+    } else if (aTopic === "VideoCapture:Resumed") {
+      this.notify();
     }
   },
 
   notify: function() {
     let windows = MediaManagerService.activeMediaCaptureWindows;
     let count = windows.Count();
     let msg = {};
     if (count == 0) {
--- a/mobile/android/chrome/content/about.js
+++ b/mobile/android/chrome/content/about.js
@@ -40,17 +40,17 @@ function init() {
   }
 
   // get URLs from prefs
   try {
     let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
 
     let links = [
       {id: "releaseNotesURL", pref: "app.releaseNotesURL"},
-      {id: "supportURL",      pref: "app.support.baseURL"},
+      {id: "supportURL",      pref: "app.supportURL"},
       {id: "faqURL",          pref: "app.faqURL"},
       {id: "privacyURL",      pref: "app.privacyURL"},
       {id: "creditsURL",      pref: "app.creditsURL"},
     ];
 
     links.forEach(function(link) {
       let url = formatter.formatURLPref(link.pref);
       let element = document.getElementById(link.id);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -161,17 +161,19 @@ lazilyLoadedObserverScripts.push(
 ["ActionBarHandler", ["TextSelection:Get", "TextSelection:Action", "TextSelection:End"],
   "chrome://browser/content/ActionBarHandler.js"]
 );
 
 if (AppConstants.MOZ_WEBRTC) {
   lazilyLoadedObserverScripts.push(
     ["WebrtcUI", ["getUserMedia:request",
                   "PeerConnection:request",
-                  "recording-device-events"], "chrome://browser/content/WebrtcUI.js"])
+                  "recording-device-events",
+                  "VideoCapture:Paused",
+                  "VideoCapture:Resumed"], "chrome://browser/content/WebrtcUI.js"])
 }
 
 lazilyLoadedObserverScripts.forEach(function (aScript) {
   let [name, notifications, script] = aScript;
   XPCOMUtils.defineLazyGetter(window, name, function() {
     let sandbox = {};
     Services.scriptloader.loadSubScript(script, sandbox);
     return sandbox[name];
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -2,16 +2,17 @@
 /* vim: set sw=2 ts=8 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Likely.h"
+#include "mozilla/unused.h"
 
 #include "mozilla/net/CookieServiceChild.h"
 #include "mozilla/net/NeckoCommon.h"
 
 #include "nsCookieService.h"
 #include "nsContentUtils.h"
 #include "nsIServiceManager.h"
 
@@ -486,17 +487,18 @@ public:
       if (!row)
         break;
 
       CookieDomainTuple *tuple = mDBState->hostArray.AppendElement();
       row->GetUTF8String(IDX_BASE_DOMAIN, tuple->key.mBaseDomain);
 
       nsAutoCString suffix;
       row->GetUTF8String(IDX_ORIGIN_ATTRIBUTES, suffix);
-      tuple->key.mOriginAttributes.PopulateFromSuffix(suffix);
+      DebugOnly<bool> success = tuple->key.mOriginAttributes.PopulateFromSuffix(suffix);
+      MOZ_ASSERT(success);
 
       tuple->cookie =
         gCookieService->GetCookieFromRow(row, tuple->key.mOriginAttributes);
     }
 
     return NS_OK;
   }
   NS_IMETHOD HandleCompletion(uint16_t aReason) override
@@ -859,17 +861,18 @@ SetAppIdFromOriginAttributesSQLFunction:
   mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult)
 {
   nsresult rv;
   nsAutoCString suffix;
   NeckoOriginAttributes attrs;
 
   rv = aFunctionArguments->GetUTF8String(0, suffix);
   NS_ENSURE_SUCCESS(rv, rv);
-  attrs.PopulateFromSuffix(suffix);
+  bool success = attrs.PopulateFromSuffix(suffix);
+  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
 
   RefPtr<nsVariant> outVar(new nsVariant());
   rv = outVar->SetAsInt32(attrs.mAppId);
   NS_ENSURE_SUCCESS(rv, rv);
 
   outVar.forget(aResult);
   return NS_OK;
 }
@@ -891,17 +894,18 @@ SetInBrowserFromOriginAttributesSQLFunct
   mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult)
 {
   nsresult rv;
   nsAutoCString suffix;
   NeckoOriginAttributes attrs;
 
   rv = aFunctionArguments->GetUTF8String(0, suffix);
   NS_ENSURE_SUCCESS(rv, rv);
-  attrs.PopulateFromSuffix(suffix);
+  bool success = attrs.PopulateFromSuffix(suffix);
+  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
 
   RefPtr<nsVariant> outVar(new nsVariant());
   rv = outVar->SetAsInt32(attrs.mInIsolatedMozBrowser);
   NS_ENSURE_SUCCESS(rv, rv);
 
   outVar.forget(aResult);
   return NS_OK;
 }
@@ -2793,17 +2797,19 @@ nsCookieService::EnsureReadComplete()
       break;
 
     // Make sure we haven't already read the data.
     stmt->GetUTF8String(IDX_BASE_DOMAIN, baseDomain);
 
     nsAutoCString suffix;
     NeckoOriginAttributes attrs;
     stmt->GetUTF8String(IDX_ORIGIN_ATTRIBUTES, suffix);
-    attrs.PopulateFromSuffix(suffix);
+    // If PopulateFromSuffix failed we just ignore the OA attributes
+    // that we don't support
+    Unused << attrs.PopulateFromSuffix(suffix);
 
     nsCookieKey key(baseDomain, attrs);
     if (mDefaultDBState->readSet.GetEntry(key))
       continue;
 
     CookieDomainTuple* tuple = array.AppendElement();
     tuple->key = key;
     tuple->cookie = GetCookieFromRow(stmt, attrs);
--- a/netwerk/protocol/http/PackagedAppVerifier.cpp
+++ b/netwerk/protocol/http/PackagedAppVerifier.cpp
@@ -77,17 +77,18 @@ NS_IMETHODIMP PackagedAppVerifier::Init(
   mListener = aListener;
   mState = STATE_UNKNOWN;
   mSignature = aSignature;
   mIsPackageSigned = false;
   mPackageCacheEntry = aPackageCacheEntry;
   mIsFirstResource = true;
   mManifest = EmptyCString();
 
-  NeckoOriginAttributes().PopulateFromOrigin(aPackageOrigin, mPackageOrigin);
+  bool success = NeckoOriginAttributes().PopulateFromOrigin(aPackageOrigin, mPackageOrigin);
+  NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
   mBypassVerification = (mPackageOrigin ==
       Preferences::GetCString("network.http.signed-packages.trusted-origin"));
 
   LOG(("mBypassVerification = %d\n", mBypassVerification));
   LOG(("mPackageOrigin = %s\n", mPackageOrigin.get()));
 
   nsresult rv;
   mPackagedAppUtils = do_CreateInstance(NS_PACKAGEDAPPUTILS_CONTRACTID, &rv);
--- a/other-licenses/bsdiff/moz.build
+++ b/other-licenses/bsdiff/moz.build
@@ -16,14 +16,15 @@ else:
     HOST_USE_LIBS += [
         'hostbz2',
     ]
 
 if CONFIG['HOST_OS_ARCH'] == 'WINNT':
     HOST_OS_LIBS += [
         'ws2_32',
     ]
+    USE_STATIC_LIBS = True
 
 LOCAL_INCLUDES += [
     '/toolkit/mozapps/update/updater',
 ]
 
 HOST_CXXFLAGS += CONFIG['MOZ_BZ2_CFLAGS']
--- a/taskcluster/scripts/builder/build-l10n.sh
+++ b/taskcluster/scripts/builder/build-l10n.sh
@@ -1,14 +1,16 @@
 #! /bin/bash -vex
 
 set -x -e
 
 echo "running as" $(id)
 
+. /home/worker/scripts/xvfb.sh
+
 ####
 # Taskcluster friendly wrapper for performing fx desktop l10n repacks via mozharness.
 # Based on ./build-linux.sh
 ####
 
 # Inputs, with defaults
 
 : MOZHARNESS_SCRIPT             ${MOZHARNESS_SCRIPT}
@@ -38,47 +40,24 @@ export TINDERBOX_OUTPUT=1
 export LIBRARY_PATH=$LIBRARY_PATH:$WORKSPACE/src/obj-firefox:$WORKSPACE/src/gcc/lib64
 
 # test required parameters are supplied
 if [[ -z ${MOZHARNESS_SCRIPT} ]]; then fail "MOZHARNESS_SCRIPT is not set"; fi
 if [[ -z ${MOZHARNESS_CONFIG} ]]; then fail "MOZHARNESS_CONFIG is not set"; fi
 
 cleanup() {
     local rv=$?
-    if [ -n "$xvfb_pid" ]; then
-        kill $xvfb_pid || true
-    fi
+    cleanup_xvfb
     exit $rv
 }
 trap cleanup EXIT INT
 
-# run mozharness in XVfb, if necessary; this is an array to maintain the quoting in the -s argument
+# run XVfb in the background, if necessary
 if $NEED_XVFB; then
-    # Some mozharness scripts set DISPLAY=:2
-    Xvfb :2 -screen 0 1024x768x24 &
-    export DISPLAY=:2
-    xvfb_pid=$!
-    # Only error code 255 matters, because it signifies that no
-    # display could be opened. As long as we can open the display
-    # tests should work. We'll retry a few times with a sleep before
-    # failing.
-    retry_count=0
-    max_retries=2
-    xvfb_test=0
-    until [ $retry_count -gt $max_retries ]; do
-        xvinfo || xvfb_test=$?
-        if [ $xvfb_test != 255 ]; then
-            retry_count=$(($max_retries + 1))
-        else
-            retry_count=$(($retry_count + 1))
-            echo "Failed to start Xvfb, retry: $retry_count"
-            sleep 2
-        fi
-    done
-    if [ $xvfb_test == 255 ]; then fail "xvfb did not start properly"; fi
+    start_xvfb '1024x768x24' 2
 fi
 
 # set up mozharness configuration, via command line, env, etc.
 
 # $TOOLTOOL_CACHE bypasses mozharness completely and is read by tooltool_wrapper.sh to set the
 # cache.  However, only some mozharness scripts use tooltool_wrapper.sh, so this may not be
 # entirely effective.
 export TOOLTOOL_CACHE
--- a/taskcluster/scripts/builder/build-linux.sh
+++ b/taskcluster/scripts/builder/build-linux.sh
@@ -1,14 +1,16 @@
 #! /bin/bash -vex
 
 set -x -e
 
 echo "running as" $(id)
 
+. /home/worker/scripts/xvfb.sh
+
 ####
 # Taskcluster friendly wrapper for performing fx desktop builds via mozharness.
 ####
 
 # Inputs, with defaults
 
 : MOZHARNESS_SCRIPT             ${MOZHARNESS_SCRIPT}
 : MOZHARNESS_CONFIG             ${MOZHARNESS_CONFIG}
@@ -49,47 +51,24 @@ export MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 export LIBRARY_PATH=$LIBRARY_PATH:$WORKSPACE/src/obj-firefox:$WORKSPACE/src/gcc/lib64
 
 # test required parameters are supplied
 if [[ -z ${MOZHARNESS_SCRIPT} ]]; then fail "MOZHARNESS_SCRIPT is not set"; fi
 if [[ -z ${MOZHARNESS_CONFIG} ]]; then fail "MOZHARNESS_CONFIG is not set"; fi
 
 cleanup() {
     local rv=$?
-    if [ -n "$xvfb_pid" ]; then
-        kill $xvfb_pid || true
-    fi
+    cleanup_xvfb
     exit $rv
 }
 trap cleanup EXIT INT
 
-# run mozharness in XVfb, if necessary; this is an array to maintain the quoting in the -s argument
+# run XVfb in the background, if necessary
 if $NEED_XVFB; then
-    # Some mozharness scripts set DISPLAY=:2
-    Xvfb :2 -screen 0 1024x768x24 &
-    export DISPLAY=:2
-    xvfb_pid=$!
-    # Only error code 255 matters, because it signifies that no
-    # display could be opened. As long as we can open the display
-    # tests should work. We'll retry a few times with a sleep before
-    # failing.
-    retry_count=0
-    max_retries=2
-    xvfb_test=0
-    until [ $retry_count -gt $max_retries ]; do
-        xvinfo || xvfb_test=$?
-        if [ $xvfb_test != 255 ]; then
-            retry_count=$(($max_retries + 1))
-        else
-            retry_count=$(($retry_count + 1))
-            echo "Failed to start Xvfb, retry: $retry_count"
-            sleep 2
-        fi
-    done
-    if [ $xvfb_test == 255 ]; then fail "xvfb did not start properly"; fi
+    start_xvfb '1024x768x24' 2
 fi
 
 # set up mozharness configuration, via command line, env, etc.
 
 debug_flag=""
 if [ 0$DEBUG -ne 0 ]; then
   debug_flag='--debug'
 fi
--- a/taskcluster/scripts/tester/test-ubuntu1204.sh
+++ b/taskcluster/scripts/tester/test-ubuntu1204.sh
@@ -1,14 +1,16 @@
 #! /bin/bash -xe
 
 set -x -e
 
 echo "running as" $(id)
 
+. /home/worker/scripts/xvfb.sh
+
 ####
 # Taskcluster friendly wrapper for performing fx desktop tests via mozharness.
 ####
 
 # Inputs, with defaults
 
 : MOZHARNESS_URL                ${MOZHARNESS_URL}
 : MOZHARNESS_SCRIPT             ${MOZHARNESS_SCRIPT}
@@ -38,23 +40,17 @@ if [[ -z ${MOZHARNESS_CONFIG} ]]; then f
 mkdir -p ~/artifacts/public
 
 cleanup() {
     local rv=$?
     if [[ -s /home/worker/.xsession-errors ]]; then
       # To share X issues
       cp /home/worker/.xsession-errors ~/artifacts/public/xsession-errors.log
     fi
-    # When you call this script with START_VNC or TASKCLUSTER_INTERACTIVE
-    # we make sure we do not kill xvfb so you do not lose your connection
-    xvfb_pid=`pidof Xvfb`
-    if [ -n "$xvfb_pid" ] && [ $START_VNC == false ] && [ $TASKCLUSTER_INTERACTIVE == false ] ; then
-        kill $xvfb_pid || true
-        screen -XS xvfb quit || true
-    fi
+    cleanup_xvfb
     exit $rv
 }
 trap cleanup EXIT INT
 
 # Unzip the mozharness ZIP file created by the build task
 if ! curl --fail -o mozharness.zip --retry 10 -L $MOZHARNESS_URL; then
     fail "failed to download mozharness zip"
 fi
@@ -68,39 +64,19 @@ fi
 
 # start up the pulseaudio daemon.  Note that it's important this occur
 # before the Xvfb startup for ubuntu 12.04, not for 16.04
 if $NEED_PULSEAUDIO; then
     pulseaudio --fail --daemonize --start
     pactl load-module module-null-sink
 fi
 
-# run Xvfb in the background, if necessary
+# run XVfb in the background, if necessary
 if $NEED_XVFB; then
-    screen -dmS xvfb Xvfb :0 -nolisten tcp -screen 0 1600x1200x24 \
-       > ~/artifacts/public/xvfb.log 2>&1
-    export DISPLAY=:0
-    # Only error code 255 matters, because it signifies that no
-    # display could be opened. As long as we can open the display
-    # tests should work. We'll retry a few times with a sleep before
-    # failing.
-    retry_count=0
-    max_retries=2
-    xvfb_test=0
-    until [ $retry_count -gt $max_retries ]; do
-        xvinfo || xvfb_test=$?
-        if [ $xvfb_test != 255 ]; then
-            retry_count=$(($max_retries + 1))
-        else
-            retry_count=$(($retry_count + 1))
-            echo "Failed to start Xvfb, retry: $retry_count"
-            sleep 2
-        fi
-    done
-    if [ $xvfb_test == 255 ]; then fail "xvfb did not start properly"; fi
+    start_xvfb '1600x1200x24' 0
 fi
 
 if $START_VNC; then
     x11vnc > ~/artifacts/public/x11vnc.log 2>&1 &
 fi
 
 if $NEED_WINDOW_MANAGER; then
     # This is read by xsession to select the window manager
--- a/taskcluster/scripts/tester/test-ubuntu1604.sh
+++ b/taskcluster/scripts/tester/test-ubuntu1604.sh
@@ -1,14 +1,16 @@
 #! /bin/bash -xe
 
 set -x -e
 
 echo "running as" $(id)
 
+. /home/worker/scripts/xvfb.sh
+
 ####
 # Taskcluster friendly wrapper for performing fx desktop tests via mozharness.
 ####
 
 # Inputs, with defaults
 
 : MOZHARNESS_URL                ${MOZHARNESS_URL}
 : MOZHARNESS_SCRIPT             ${MOZHARNESS_SCRIPT}
@@ -38,63 +40,36 @@ if [[ -z ${MOZHARNESS_CONFIG} ]]; then f
 mkdir -p ~/artifacts/public
 
 cleanup() {
     local rv=$?
     if [[ -s /home/worker/.xsession-errors ]]; then
       # To share X issues
       cp /home/worker/.xsession-errors ~/artifacts/public/xsession-errors.log
     fi
-    # When you call this script with START_VNC or TASKCLUSTER_INTERACTIVE
-    # we make sure we do not kill xvfb so you do not lose your connection
-    xvfb_pid=`pidof Xvfb`
-    if [ -n "$xvfb_pid" ] && [ $START_VNC == false ] && [ $TASKCLUSTER_INTERACTIVE == false ] ; then
-        kill $xvfb_pid || true
-        screen -XS xvfb quit || true
-    fi
+    cleanup_xvfb
     exit $rv
 }
 trap cleanup EXIT INT
 
 # Unzip the mozharness ZIP file created by the build task
 if ! curl --fail -o mozharness.zip --retry 10 -L $MOZHARNESS_URL; then
     fail "failed to download mozharness zip"
 fi
 rm -rf mozharness
 unzip -q mozharness.zip
 rm mozharness.zip
 
 if ! [ -d mozharness ]; then
     fail "mozharness zip did not contain mozharness/"
 fi
 
-# run Xvfb in the background, if necessary
+# run XVfb in the background, if necessary
 if $NEED_XVFB; then
-    screen -dmS xvfb Xvfb :0 -nolisten tcp -screen 0 1600x1200x24 \
-       > ~/artifacts/public/xvfb.log 2>&1
-    export DISPLAY=:0
-
-    # Only error code 255 matters, because it signifies that no
-    # display could be opened. As long as we can open the display
-    # tests should work. We'll retry a few times with a sleep before
-    # failing.
-    retry_count=0
-    max_retries=2
-    xvfb_test=0
-    until [ $retry_count -gt $max_retries ]; do
-        xvinfo || xvfb_test=$?
-        if [ $xvfb_test != 255 ]; then
-            retry_count=$(($max_retries + 1))
-        else
-            retry_count=$(($retry_count + 1))
-            echo "Failed to start Xvfb, retry: $retry_count"
-            sleep 2
-        fi
-    done
-    if [ $xvfb_test == 255 ]; then fail "xvfb did not start properly"; fi
+    start_xvfb '1600x1200x24' 0
 fi
 
 if $START_VNC; then
     x11vnc > ~/artifacts/public/x11vnc.log 2>&1 &
 fi
 
 if $NEED_WINDOW_MANAGER; then
     # This is read by xsession to select the window manager
--- a/testing/docker/desktop-build/Dockerfile
+++ b/testing/docker/desktop-build/Dockerfile
@@ -6,16 +6,20 @@ MAINTAINER    Dustin J. Mitchell <dustin
 VOLUME /home/worker/workspace
 VOLUME /home/worker/tooltool-cache
 
 # Add build scripts; these are the entry points from the taskcluster worker, and
 # operate on environment variables
 ADD             bin /home/worker/bin
 RUN             chmod +x /home/worker/bin/*
 
+# Add wrapper scripts for xvfb allowing tasks to easily retry starting up xvfb
+# %include testing/docker/recipes/xvfb.sh
+ADD topsrcdir/testing/docker/recipes/xvfb.sh /home/worker/scripts/xvfb.sh
+
 # Add configuration
 COPY            dot-config                    /home/worker/.config
 
 # Generate machine uuid file
 RUN dbus-uuidgen --ensure=/var/lib/dbus/machine-id
 
 # Stubbed out credentials; mozharness looks for this file an issues a WARNING
 # if it's not found, which causes the build to fail.  Note that this needs to
@@ -28,10 +32,14 @@ ADD           oauth.txt /home/worker/
 # the directory where mozharness is run (not its --work-dir)
 ADD           buildprops.json /home/worker/
 
 # install tooltool directly from github where tooltool_wrapper.sh et al. expect
 # to find it
 RUN wget -O /builds/tooltool.py https://raw.githubusercontent.com/mozilla/build-tooltool/master/tooltool.py
 RUN chmod +x /builds/tooltool.py
 
+# Move installation to base centos6-build image once Bug 1272629 is fixed
+# Install the screen package here to use with xvfb.
+RUN yum install -y screen
+
 # Set a default command useful for debugging
 CMD ["/bin/bash", "--login"]
--- a/testing/docker/desktop-test/Dockerfile
+++ b/testing/docker/desktop-test/Dockerfile
@@ -5,16 +5,20 @@ RUN useradd -d /home/worker -s /bin/bash
 WORKDIR /home/worker
 
 # %include testing/docker/recipes/tooltool.py
 ADD topsrcdir/testing/docker/recipes/tooltool.py /setup/tooltool.py
 
 # %include testing/docker/recipes/install-mercurial.sh
 ADD topsrcdir/testing/docker/recipes/install-mercurial.sh /tmp/install-mercurial.sh
 
+# Add wrapper scripts for xvfb allowing tasks to easily retry starting up xvfb
+# %include testing/docker/recipes/xvfb.sh
+ADD topsrcdir/testing/docker/recipes/xvfb.sh /home/worker/scripts/xvfb.sh
+
 # %include testing/docker/recipes/ubuntu1204-test-system-setup.sh
 ADD topsrcdir/testing/docker/recipes/ubuntu1204-test-system-setup.sh /setup/system-setup.sh
 RUN bash /setup/system-setup.sh
 
 # %include testing/docker/recipes/run-task
 ADD topsrcdir/testing/docker/recipes/run-task /home/worker/bin/run-task
 
 # %include taskcluster/scripts/tester/test-ubuntu1204.sh
--- a/testing/docker/desktop1604-test/Dockerfile
+++ b/testing/docker/desktop1604-test/Dockerfile
@@ -9,16 +9,20 @@ ADD topsrcdir/testing/docker/recipes/too
 
 # %include testing/docker/recipes/install-mercurial.sh
 ADD topsrcdir/testing/docker/recipes/install-mercurial.sh /setup/install-mercurial.sh
 
 # %include testing/docker/recipes/ubuntu1604-test-system-setup.sh
 ADD topsrcdir/testing/docker/recipes/ubuntu1604-test-system-setup.sh /setup/system-setup.sh
 RUN           bash /setup/system-setup.sh
 
+# Add wrapper scripts for xvfb allowing tasks to easily retry starting up xvfb
+# %include testing/docker/recipes/xvfb.sh
+ADD topsrcdir/testing/docker/recipes/xvfb.sh /home/worker/scripts/xvfb.sh
+
 # %include testing/docker/recipes/run-task
 ADD topsrcdir/testing/docker/recipes/run-task /home/worker/bin/run-task
 
 # %include taskcluster/scripts/tester/test-ubuntu1604.sh
 ADD topsrcdir/taskcluster/scripts/tester/test-ubuntu1604.sh /home/worker/bin/test-linux.sh
 
 # This will create a host mounted filesystem when the cache is stripped
 # on Try. This cancels out some of the performance losses of aufs. See
new file mode 100644
--- /dev/null
+++ b/testing/docker/recipes/xvfb.sh
@@ -0,0 +1,75 @@
+#! /bin/bash -x
+
+set -x
+
+fail() {
+    echo # make sure error message is on a new line
+    echo "[xvfb.sh:error]" "${@}"
+    exit 1
+}
+
+cleanup_xvfb() {
+    # When you call this script with START_VNC or TASKCLUSTER_INTERACTIVE
+    # we make sure we do not kill xvfb so you do not lose your connection
+    local xvfb_pid=`pidof Xvfb`
+    local vnc=${START_VNC:-false}
+    local interactive=${TASKCLUSTER_INTERACTIVE:-false}
+    if [ -n "$xvfb_pid" ] && [[ $vnc == false ]] && [[ $interactive == false ]] ; then
+        kill $xvfb_pid || true
+        screen -XS xvfb quit || true
+    fi
+}
+
+# Attempt to start xvfb in a screen session with the given resolution and display
+# number.  Up to 5 attempts will be made to start xvfb with a short delay
+# between retries
+try_xvfb() {
+    screen -dmS xvfb Xvfb :$2 -nolisten tcp -screen 0 $1 \
+       > ~/artifacts/xvfb/xvfb.log 2>&1
+    export DISPLAY=:$2
+
+    # Only error code 255 matters, because it signifies that no
+    # display could be opened. As long as we can open the display
+    # tests should work. We'll retry a few times with a sleep before
+    # failing.
+    local retry_count=0
+    local max_retries=5
+    xvfb_test=0
+    until [ $retry_count -gt $max_retries ]; do
+        xvinfo || xvfb_test=$?
+        if [ $xvfb_test != 255 ]; then
+            retry_count=$(($max_retries + 1))
+        else
+            retry_count=$(($retry_count + 1))
+            echo "Failed to start Xvfb, retry: $retry_count"
+            sleep 2
+        fi
+    done
+    if [ $xvfb_test == 255 ]; then
+        return 1
+    else
+        return 0
+    fi
+}
+
+start_xvfb() {
+    set +e
+    mkdir -p ~/artifacts/xvfb
+    local retry_count=0
+    local max_retries=2
+    local success=1
+    until [ $retry_count -gt $max_retries ]; do
+        try_xvfb $1 $2
+        success=$?
+        if [ $success -eq 0 ]; then
+            retry_count=$(($max_retries + 1))
+        else
+            retry_count=$(($retry_count + 1))
+            sleep 10
+        fi
+    done
+    set -e
+    if [ $success -eq 1 ]; then
+        fail "Could not start xvfb after ${max_retries} attempts"
+    fi
+}
--- a/testing/mozharness/configs/unittests/mac_unittest.py
+++ b/testing/mozharness/configs/unittests/mac_unittest.py
@@ -109,17 +109,19 @@ config = {
             "run_filename": "runtestlist.py",
             "testsdir": "mozmill"
         },
         "reftest": {
             "options": [
                 "--appname=%(binary_path)s",
                 "--utility-path=tests/bin",
                 "--extra-profile-file=tests/bin/plugins",
-                "--symbols-path=%(symbols_path)s"
+                "--symbols-path=%(symbols_path)s",
+                "--log-raw=%(raw_log_file)s",
+                "--log-errorsummary=%(error_summary_file)s",
                 "--cleanup-crashes",
             ],
             "run_filename": "runreftest.py",
             "testsdir": "reftest"
         },
         "xpcshell": {
             "options": [
                 "--symbols-path=%(symbols_path)s",