Merge last green changeset from inbound to mozilla-central
authorMatt Brubeck <mbrubeck@mozilla.com>
Thu, 26 Jul 2012 13:56:47 -0700
changeset 100584 8a7ad0adcccf375d2d59150ac4b082e998169efc
parent 100560 f263db41eaa9dfbfaf274f253059112b5e7d4054 (current diff)
parent 100583 e4330f6365d9ff9f79c673a215119b9053202583 (diff)
child 100585 f528e021ceb1daff2d854d9c460e907d4397b0d4
push id23185
push usermbrubeck@mozilla.com
push dateThu, 26 Jul 2012 20:58:28 +0000
treeherdermozilla-central@8a7ad0adcccf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.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 last green changeset from inbound to mozilla-central
mobile/android/base/resources/drawable-hdpi/sync_fx_icon.png
mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png
mobile/android/base/resources/drawable-ldpi/sync_fx_icon.png
mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png
mobile/android/base/resources/drawable-mdpi/sync_fx_icon.png
mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png
mobile/android/base/resources/drawable/sync_ic_launcher.png
mobile/android/base/resources/layout/sync_stub.xml
mobile/android/base/resources/xml/sync_authenticator.xml
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -610,17 +610,17 @@ Services.obs.addObserver(function Conten
     data: {
       type: handler.type,
       url: handler.url
     }
   });
 }, 'content-handler', false);
 
 (function geolocationStatusTracker() {
-  gGeolocationActiveCount = 0;
+  let gGeolocationActiveCount = 0;
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     let oldCount = gGeolocationActiveCount;
     if (aData == "starting") {
       gGeolocationActiveCount += 1;
     } else if (aData == "shutdown") {
       gGeolocationActiveCount -= 1;
     }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4676,25 +4676,19 @@ var TabsOnTop = {
 }
 
 var TabsInTitlebar = {
   init: function () {
 #ifdef CAN_DRAW_IN_TITLEBAR
     this._readPref();
     Services.prefs.addObserver(this._prefName, this, false);
 
-    // Don't trust the initial value of the sizemode attribute; wait for the resize event.
+    // Don't trust the initial value of the sizemode attribute; wait for
+    // the resize event (handled in tabbrowser.xml).
     this.allowedBy("sizemode", false);
-    window.addEventListener("resize", function (event) {
-      if (event.target != window)
-        return;
-      let sizemode = document.documentElement.getAttribute("sizemode");
-      TabsInTitlebar.allowedBy("sizemode",
-                               sizemode == "maximized" || sizemode == "fullscreen");
-    }, false);
 
     this._initialized = true;
 #endif
   },
 
   allowedBy: function (condition, allow) {
 #ifdef CAN_DRAW_IN_TITLEBAR
     if (allow) {
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3087,23 +3087,29 @@
         <body><![CDATA[
           switch (aEvent.type) {
             case "load":
               this.updateVisibility();
               break;
             case "resize":
               if (aEvent.target != window)
                 break;
+
+              let sizemode = document.documentElement.getAttribute("sizemode");
+              TabsInTitlebar.allowedBy("sizemode",
+                                       sizemode == "maximized" || sizemode == "fullscreen");
+
               var width = this.mTabstrip.boxObject.width;
               if (width != this.mTabstripWidth) {
                 this.adjustTabstrip();
                 this._fillTrailingGap();
                 this._handleTabSelect();
                 this.mTabstripWidth = width;
               }
+
               this.tabbrowser.updateWindowResizers();
               break;
             case "mouseout":
               // If the "related target" (the node to which the pointer went) is not
               // a child of the current document, the mouse just left the window.
               let relatedTarget = aEvent.relatedTarget;
               if (relatedTarget && relatedTarget.ownerDocument == document)
                 break;
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1452,17 +1452,17 @@ nsXMLHttpRequest::GetAllResponseHeaders(
   nsCAutoString value;
   if (NS_SUCCEEDED(mChannel->GetContentType(value))) {
     aResponseHeaders.AppendLiteral("Content-Type: ");
     AppendASCIItoUTF16(value, aResponseHeaders);
     if (NS_SUCCEEDED(mChannel->GetContentCharset(value)) && !value.IsEmpty()) {
       aResponseHeaders.AppendLiteral(";charset=");
       AppendASCIItoUTF16(value, aResponseHeaders);
     }
-    aResponseHeaders.Append('\n');
+    aResponseHeaders.AppendLiteral("\r\n");
   }
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::GetResponseHeader(const nsACString& aHeader,
                                     nsACString& aResult)
 {
   ErrorResult rv;
@@ -3976,17 +3976,17 @@ nsHeaderVisitor::VisitHeader(const nsACS
     if (!chrome &&
          (header.LowerCaseEqualsASCII("set-cookie") ||
           header.LowerCaseEqualsASCII("set-cookie2"))) {
         NS_WARNING("blocked access to response header");
     } else {
         mHeaders.Append(header);
         mHeaders.Append(": ");
         mHeaders.Append(value);
-        mHeaders.Append('\n');
+        mHeaders.Append("\r\n");
     }
     return NS_OK;
 }
 
 // DOM event class to handle progress notifications
 nsXMLHttpProgressEvent::nsXMLHttpProgressEvent(nsIDOMProgressEvent* aInner,
                                                PRUint64 aCurrentProgress,
                                                PRUint64 aMaxProgress,
--- a/content/base/test/test_XHR.html
+++ b/content/base/test/test_XHR.html
@@ -43,17 +43,17 @@ for (i = 0; i < passFiles.length; ++i) {
   is(xhr.getResponseHeader("Content-Type"), null, "should be null");
   is(xhr.getAllResponseHeaders(), "", "should be empty string");
   is(xhr.responseType, "", "wrong initial responseType");
   xhr.open(passFiles[i][1], passFiles[i][0], false); 
   xhr.send(null);
   is(xhr.status, passFiles[i][2], "wrong status");
   is(xhr.getResponseHeader("Content-Type"), passFiles[i][3], "wrong content type");
   var headers = xhr.getAllResponseHeaders();
-  ok(/(?:^|\n)Content-Type:\s*([^\n]*)\n/i.test(headers) &&
+  ok(/(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) &&
      RegExp.$1 === passFiles[i][3], "wrong response headers");
   if (xhr.responseXML) {
     is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement),
        passFiles[i][4] || "<res>hello</res>", "wrong responseXML");
     is(xhr.response, passFiles[i][4] || "<res>hello</res>\n", "wrong response");
   }
   else {
     is(xhr.responseText, passFiles[i][4] || "hello pass\n", "wrong responseText");
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -88,16 +88,17 @@ using mozilla::PluginPRLibrary;
 using mozilla::plugins::PluginModuleParent;
 
 #ifdef MOZ_X11
 #include "mozilla/X11Util.h"
 #endif
 
 #ifdef XP_WIN
 #include <windows.h>
+#include "nsWindowsHelpers.h"
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include <android/log.h>
 #include "android_npapi.h"
 #include "ANPBase.h"
 #include "AndroidBridge.h"
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
@@ -276,30 +277,16 @@ static bool GMA9XXGraphics()
       }
     }
     ::CGLDestroyRendererInfo(renderer);
   }
   return hasIntelGMA9XX;
 }
 #endif
 
-#ifdef XP_WIN
-static bool
-IsVistaOrLater()
-{
-  OSVERSIONINFO info;
-
-  ZeroMemory(&info, sizeof(OSVERSIONINFO));
-  info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-  GetVersionEx(&info);
-
-  return info.dwMajorVersion >= 6;
-}
-#endif
-
 bool
 nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
 {
   if (PR_GetEnv("MOZ_DISABLE_OOP_PLUGINS")) {
     return false;
   }
 
   if (!aPluginTag) {
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -213,21 +213,25 @@ nsNPAPIPluginInstance::~nsNPAPIPluginIns
 
 void
 nsNPAPIPluginInstance::Destroy()
 {
   Stop();
   mPlugin = nsnull;
 
 #if MOZ_WIDGET_ANDROID
+  if (mContentSurface)
+    mContentSurface->SetFrameAvailableCallback(nsnull);
+  
   mContentTexture = nsnull;
   mContentSurface = nsnull;
 
   std::map<void*, VideoInfo*>::iterator it;
   for (it = mVideos.begin(); it != mVideos.end(); it++) {
+    it->second->mSurfaceTexture->SetFrameAvailableCallback(nsnull);
     delete it->second;
   }
   mVideos.clear();
   SetWakeLock(false);
 #endif
 }
 
 TimeStamp
@@ -983,21 +987,27 @@ nsSurfaceTexture* nsNPAPIPluginInstance:
   GLuint texture = TexturePoolOGL::AcquireTexture();
   if (!texture)
     return nsnull;
 
   nsSurfaceTexture* surface = nsSurfaceTexture::Create(texture);
   if (!surface)
     return nsnull;
 
-  nsCOMPtr<nsIRunnable> frameCallback = NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::RedrawPlugin);
+  nsCOMPtr<nsIRunnable> frameCallback = NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable);
   surface->SetFrameAvailableCallback(frameCallback);
   return surface;
 }
 
+void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
+{
+  if (mRunning == RUNNING && mOwner)
+    RedrawPlugin();
+}
+
 void* nsNPAPIPluginInstance::AcquireContentWindow()
 {
   if (!mContentSurface) {
     mContentSurface = CreateSurfaceTexture();
 
     if (!mContentSurface)
       return nsnull;
   }
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -281,16 +281,17 @@ protected:
 
 #ifdef MOZ_WIDGET_ANDROID
   PRUint32 mANPDrawingModel;
 
   friend class PluginEventRunnable;
 
   nsTArray<nsCOMPtr<PluginEventRunnable>> mPostedEvents;
   void PopPostedEvent(PluginEventRunnable* r);
+  void OnSurfaceTextureFrameAvailable();
 
   PRUint32 mFullScreenOrientation;
   bool mWakeLocked;
   bool mFullScreen;
   bool mInverted;
 
   nsRefPtr<SharedPluginTexture> mContentTexture;
   nsRefPtr<nsSurfaceTexture> mContentSurface;
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -455,16 +455,17 @@ const MSISDN_MAX_NUMBER_SIZE_BYTES = 10;
 const READ_RECORD_ABSOLUTE_MODE = 4;
 
 // GET_RESPONSE mandatory response size for EF, see TS 51.011 clause 9, 
 // 'Response data in case of an EF.'
 const GET_RESPONSE_EF_SIZE_BYTES = 15;
 
 // EF path
 const EF_PATH_MF_SIM = "3f00";
+const EF_PATH_DF_PHONEBOOK = "5f3a";
 const EF_PATH_DF_TELECOM = "7f10";
 const EF_PATH_DF_GSM = "7f20";
 
 // Status code of sw1 for ICC I/O,
 // see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
 const ICC_STATUS_NORMAL_ENDING = 0x90;
 const ICC_STATUS_NORMAL_ENDING_WITH_EXTRA = 0x91;
 const ICC_STATUS_WITH_SIM_DATA = 0x9e;
--- a/editor/composer/src/Makefile.in
+++ b/editor/composer/src/Makefile.in
@@ -27,17 +27,18 @@ CPPSRCS  = \
            nsComposerRegistration.cpp     \
            nsEditingSession.cpp	          \
            nsComposerCommandsUpdater.cpp  \
            nsEditorSpellCheck.cpp         \
            $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
-INCLUDES        += -I../../libeditor/base/src
+INCLUDES        += \
+	$(NULL)
 
 _FILES = \
 	$(srcdir)/res/EditorOverride.css \
 	$(srcdir)/res/grabber.gif \
 	$(srcdir)/res/table-add-column-after-active.gif \
 	$(srcdir)/res/table-add-column-after-hover.gif \
 	$(srcdir)/res/table-add-column-after.gif \
 	$(srcdir)/res/table-add-column-before-active.gif \
--- a/extensions/auth/nsAuthGSSAPI.cpp
+++ b/extensions/auth/nsAuthGSSAPI.cpp
@@ -562,8 +562,14 @@ nsAuthGSSAPI::Wrap(const void *inToken,
 
     /* it is not possible for output_token.length to be zero */
     *outToken = nsMemory::Clone(output_token.value, output_token.length);
     gss_release_buffer_ptr(&minor_status, &output_token);
 
     return NS_OK;
 }
 
+NS_IMETHODIMP
+nsAuthGSSAPI::GetModuleProperties(PRUint32 *flags)
+{
+    *flags = 0;
+    return NS_OK;
+}
--- a/extensions/auth/nsAuthSASL.cpp
+++ b/extensions/auth/nsAuthSASL.cpp
@@ -144,8 +144,15 @@ NS_IMETHODIMP
 nsAuthSASL::Wrap(const void *inToken,
                  PRUint32    inTokenLen,
                  bool        confidential,
                  void      **outToken,
                  PRUint32   *outTokenLen)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
+
+NS_IMETHODIMP
+nsAuthSASL::GetModuleProperties(PRUint32 *flags)
+{
+    *flags = 0;
+    return NS_OK;
+}
--- a/extensions/auth/nsAuthSSPI.cpp
+++ b/extensions/auth/nsAuthSSPI.cpp
@@ -86,60 +86,16 @@ InitSSPI()
         return NS_ERROR_UNEXPECTED;
     }
 
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 
-static nsresult
-MakeSN(const char *principal, nsCString &result)
-{
-    nsresult rv;
-
-    nsCAutoString buf(principal);
-
-    // The service name looks like "protocol@hostname", we need to map
-    // this to a value that SSPI expects.  To be consistent with IE, we
-    // need to map '@' to '/' and canonicalize the hostname.
-    PRInt32 index = buf.FindChar('@');
-    if (index == kNotFound)
-        return NS_ERROR_UNEXPECTED;
-    
-    nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
-    if (NS_FAILED(rv))
-        return rv;
-
-    // This could be expensive if our DNS cache cannot satisfy the request.
-    // However, we should have at least hit the OS resolver once prior to
-    // reaching this code, so provided the OS resolver has this information
-    // cached, we should not have to worry about blocking on this function call
-    // for very long.  NOTE: because we ask for the canonical hostname, we
-    // might end up requiring extra network activity in cases where the OS
-    // resolver might not have enough information to satisfy the request from
-    // its cache.  This is not an issue in versions of Windows up to WinXP.
-    nsCOMPtr<nsIDNSRecord> record;
-    rv = dns->Resolve(Substring(buf, index + 1),
-                      nsIDNSService::RESOLVE_CANONICAL_NAME,
-                      getter_AddRefs(record));
-    if (NS_FAILED(rv))
-        return rv;
-
-    nsCAutoString cname;
-    rv = record->GetCanonicalName(cname);
-    if (NS_SUCCEEDED(rv)) {
-        result = StringHead(buf, index) + NS_LITERAL_CSTRING("/") + cname;
-        LOG(("Using SPN of [%s]\n", result.get()));
-    }
-    return rv;
-}
-
-//-----------------------------------------------------------------------------
-
 nsAuthSSPI::nsAuthSSPI(pType package)
     : mServiceFlags(REQ_DEFAULT)
     , mMaxTokenLen(0)
     , mPackage(package)
     , mCertDERData(nsnull)
     , mCertDERLength(0)
 {
     memset(&mCred, 0, sizeof(mCred));
@@ -203,33 +159,23 @@ nsAuthSSPI::Init(const char *serviceName
         rv = InitSSPI();
         if (NS_FAILED(rv))
             return rv;
     }
     SEC_WCHAR *package;
 
     package = (SEC_WCHAR *) pTypeName[(int)mPackage];
 
-    if (mPackage == PACKAGE_TYPE_NTLM) {
-        // (bug 535193) For NTLM, just use the uri host, do not do canonical host lookups.
-        // The incoming serviceName is in the format: "protocol@hostname", SSPI expects
-        // "<service class>/<hostname>", so swap the '@' for a '/'.
-        mServiceName.Assign(serviceName);
-        PRInt32 index = mServiceName.FindChar('@');
-        if (index == kNotFound)
-            return NS_ERROR_UNEXPECTED;
-        mServiceName.Replace(index, 1, '/');
-    }
-    else {
-        // Kerberos requires the canonical host, MakeSN takes care of this through a
-        // DNS lookup.
-        rv = MakeSN(serviceName, mServiceName);
-        if (NS_FAILED(rv))
-            return rv;
-    }
+    // The incoming serviceName is in the format: "protocol@hostname", SSPI expects
+    // "<service class>/<hostname>", so swap the '@' for a '/'.
+    mServiceName.Assign(serviceName);
+    PRInt32 index = mServiceName.FindChar('@');
+    if (index == kNotFound)
+        return NS_ERROR_UNEXPECTED;
+    mServiceName.Replace(index, 1, '/');
 
     mServiceFlags = serviceFlags;
 
     SECURITY_STATUS rc;
 
     PSecPkgInfoW pinfo;
     rc = (sspi->QuerySecurityPackageInfoW)(package, &pinfo);
     if (rc != SEC_E_OK) {
@@ -648,8 +594,21 @@ nsAuthSSPI::Wrap(const void *inToken,
 
         memcpy(p,bufs.ib[2].pvBuffer, bufs.ib[2].cbBuffer);
         
         return NS_OK;
     }
 
     return NS_ERROR_FAILURE;
 }
+
+NS_IMETHODIMP
+nsAuthSSPI::GetModuleProperties(PRUint32 *flags)
+{
+    *flags = 0;
+
+    // (bug 535193) For NTLM, just use the uri host, do not do canonical host
+    // lookups. But Kerberos requires the canonical host.
+    if (mPackage != PACKAGE_TYPE_NTLM)
+        *flags |= CANONICAL_NAME_REQUIRED;
+
+    return NS_OK;
+}
--- a/extensions/auth/nsAuthSambaNTLM.cpp
+++ b/extensions/auth/nsAuthSambaNTLM.cpp
@@ -277,8 +277,15 @@ NS_IMETHODIMP
 nsAuthSambaNTLM::Wrap(const void *inToken,
                       PRUint32    inTokenLen,
                       bool        confidential,
                       void      **outToken,
                       PRUint32   *outTokenLen)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
+
+NS_IMETHODIMP
+nsAuthSambaNTLM::GetModuleProperties(PRUint32 *flags)
+{
+    *flags = 0;
+    return NS_OK;
+}
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -626,21 +626,24 @@ LayerManagerD3D10::VerifyBufferSize()
     mSwapChain->GetDesc(&swapDesc);
 
     if (swapDesc.BufferDesc.Width == rect.width &&
         swapDesc.BufferDesc.Height == rect.height) {
       return;
     }
 
     mRTView = nsnull;
-    if (gfxWindowsPlatform::IsOptimus() ||
-        gfxWindowsPlatform::IsRunningInWindows8Metro()) {
+    if (gfxWindowsPlatform::IsOptimus()) { 
       mSwapChain->ResizeBuffers(1, rect.width, rect.height,
                                 DXGI_FORMAT_B8G8R8A8_UNORM,
                                 0);
+    } else if (gfxWindowsPlatform::IsRunningInWindows8Metro()) {
+      mSwapChain->ResizeBuffers(2, rect.width, rect.height,
+                                DXGI_FORMAT_B8G8R8A8_UNORM,
+                                0);
     } else {
       mSwapChain->ResizeBuffers(1, rect.width, rect.height,
                                 DXGI_FORMAT_B8G8R8A8_UNORM,
                                 DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE);
     }
   } else {
     D3D10_TEXTURE2D_DESC oldDesc;    
     if (mBackBuffer) {
--- a/gfx/thebes/nsSurfaceTexture.h
+++ b/gfx/thebes/nsSurfaceTexture.h
@@ -39,16 +39,18 @@ public:
   void* GetNativeWindow();
 
   // This attaches the updated data to the TEXTURE_EXTERNAL target
   void UpdateTexImage();
 
   bool GetTransformMatrix(gfx3DMatrix& aMatrix);
   int ID() { return mID; }
 
+  // The callback is guaranteed to be called on the main thread even
+  // if the upstream callback is received on a different thread
   void SetFrameAvailableCallback(nsIRunnable* aRunnable);
 
   // Only should be called by AndroidJNI when we get a
   // callback from the underlying SurfaceTexture instance
   void NotifyFrameAvailable();
 private:
   nsSurfaceTexture();
 
--- a/hal/windows/WindowsBattery.cpp
+++ b/hal/windows/WindowsBattery.cpp
@@ -5,16 +5,17 @@
 
 #include "Hal.h"
 #include "HalImpl.h"
 #include "nsITimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/battery/Constants.h"
 
 #include <windows.h>
+#include "nsWindowsHelpers.h"
 
 using namespace mozilla::dom::battery;
 
 namespace mozilla {
 namespace hal_impl {
 
 static nsCOMPtr<nsITimer> sUpdateTimer;
 
@@ -22,28 +23,16 @@ static nsCOMPtr<nsITimer> sUpdateTimer;
 typedef HPOWERNOTIFY (WINAPI *REGISTERPOWERSETTINGNOTIFICATION) (HANDLE, LPCGUID, DWORD);
 typedef BOOL (WINAPI *UNREGISTERPOWERSETTINGNOTIFICATION) (HPOWERNOTIFY);
 static REGISTERPOWERSETTINGNOTIFICATION sRegisterPowerSettingNotification = nsnull;
 static UNREGISTERPOWERSETTINGNOTIFICATION sUnregisterPowerSettingNotification = nsnull;
 static HPOWERNOTIFY sPowerHandle = nsnull;
 static HPOWERNOTIFY sCapacityHandle = nsnull;
 static HWND sHWnd = nsnull;
 
-static bool
-IsVistaOrLater()
-{
-  OSVERSIONINFO info;
-
-  ZeroMemory(&info, sizeof(OSVERSIONINFO));
-  info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-  GetVersionEx(&info);
-
-  return info.dwMajorVersion >= 6;
-}
-
 static void
 UpdateHandler(nsITimer* aTimer, void* aClosure) {
   NS_ASSERTION(!IsVistaOrLater(),
                "We shouldn't call this function for Vista or later version!");
 
   static hal::BatteryInformation sLastInfo;
   hal::BatteryInformation currentInfo;
 
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -418,48 +418,57 @@ struct ArenaHeader
     size_t          firstFreeSpanOffsets;
 
     /*
      * One of AllocKind constants or FINALIZE_LIMIT when the arena does not
      * contain any GC things and is on the list of empty arenas in the GC
      * chunk. The latter allows to quickly check if the arena is allocated
      * during the conservative GC scanning without searching the arena in the
      * list.
+     *
+     * We use 8 bits for the allocKind so the compiler can use byte-level memory
+     * instructions to access it.
      */
     size_t       allocKind          : 8;
 
     /*
-     * When recursive marking uses too much stack the marking is delayed and
-     * the corresponding arenas are put into a stack using the following field
-     * as a linkage. To distinguish the bottom of the stack from the arenas
-     * not present in the stack we use an extra flag to tag arenas on the
-     * stack.
+     * When collecting we sometimes need to keep an auxillary list of arenas,
+     * for which we use the following fields.  This happens for several reasons:
+     *
+     * When recursive marking uses too much stack the marking is delayed and the
+     * corresponding arenas are put into a stack. To distinguish the bottom of
+     * the stack from the arenas not present in the stack we use the
+     * markOverflow flag to tag arenas on the stack.
      *
      * Delayed marking is also used for arenas that we allocate into during an
      * incremental GC. In this case, we intend to mark all the objects in the
      * arena, and it's faster to do this marking in bulk.
      *
-     * To minimize the ArenaHeader size we record the next delayed marking
-     * linkage as arenaAddress() >> ArenaShift and pack it with the allocKind
-     * field and hasDelayedMarking flag. We use 8 bits for the allocKind, not
-     * ArenaShift - 1, so the compiler can use byte-level memory instructions
-     * to access it.
+     * When sweeping we keep track of which arenas have been allocated since the
+     * end of the mark phase.  This allows us to tell whether a pointer to an
+     * unmarked object is yet to be finalized or has already been reallocated.
+     * We set the allocatedDuringIncremental flag for this and clear it at the
+     * end of the sweep phase.
+     *
+     * To minimize the ArenaHeader size we record the next linkage as
+     * arenaAddress() >> ArenaShift and pack it with the allocKind field and the
+     * flags.
      */
   public:
     size_t       hasDelayedMarking  : 1;
     size_t       allocatedDuringIncremental : 1;
     size_t       markOverflow : 1;
-    size_t       nextDelayedMarking : JS_BITS_PER_WORD - 8 - 1 - 1 - 1;
+    size_t       auxNextLink : JS_BITS_PER_WORD - 8 - 1 - 1 - 1;
 
     static void staticAsserts() {
         /* We must be able to fit the allockind into uint8_t. */
         JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255);
 
         /*
-         * nextDelayedMarkingpacking assumes that ArenaShift has enough bits
+         * auxNextLink packing assumes that ArenaShift has enough bits
          * to cover allocKind and hasDelayedMarking.
          */
         JS_STATIC_ASSERT(ArenaShift >= 8 + 1 + 1 + 1);
     }
 
     inline uintptr_t address() const;
     inline Chunk *chunk() const;
 
@@ -482,17 +491,17 @@ struct ArenaHeader
         firstFreeSpanOffsets = FreeSpan::FullArenaOffsets;
     }
 
     void setAsNotAllocated() {
         allocKind = size_t(FINALIZE_LIMIT);
         markOverflow = 0;
         allocatedDuringIncremental = 0;
         hasDelayedMarking = 0;
-        nextDelayedMarking = 0;
+        auxNextLink = 0;
     }
 
     inline uintptr_t arenaAddress() const;
     inline Arena *getArena();
 
     AllocKind getAllocKind() const {
         JS_ASSERT(allocated());
         return AllocKind(allocKind);
@@ -514,16 +523,21 @@ struct ArenaHeader
     inline void setFirstFreeSpan(const FreeSpan *span);
 
 #ifdef DEBUG
     void checkSynchronizedWithFreeList() const;
 #endif
 
     inline ArenaHeader *getNextDelayedMarking() const;
     inline void setNextDelayedMarking(ArenaHeader *aheader);
+    inline void unsetDelayedMarking();
+
+    inline ArenaHeader *getNextAllocDuringSweep() const;
+    inline void setNextAllocDuringSweep(ArenaHeader *aheader);
+    inline void unsetAllocDuringSweep();
 };
 
 struct Arena
 {
     /*
      * Layout of an arena:
      * An arena is 4K in size and 4K-aligned. It starts with the ArenaHeader
      * descriptor followed by some pad bytes. The remainder of the arena is
@@ -877,25 +891,58 @@ ArenaHeader::setFirstFreeSpan(const Free
 {
     JS_ASSERT(span->isWithinArena(arenaAddress()));
     firstFreeSpanOffsets = span->encodeAsOffsets();
 }
 
 inline ArenaHeader *
 ArenaHeader::getNextDelayedMarking() const
 {
-    return &reinterpret_cast<Arena *>(nextDelayedMarking << ArenaShift)->aheader;
+    JS_ASSERT(hasDelayedMarking);
+    return &reinterpret_cast<Arena *>(auxNextLink << ArenaShift)->aheader;
 }
 
 inline void
 ArenaHeader::setNextDelayedMarking(ArenaHeader *aheader)
 {
     JS_ASSERT(!(uintptr_t(aheader) & ArenaMask));
+    JS_ASSERT(!auxNextLink && !hasDelayedMarking);
     hasDelayedMarking = 1;
-    nextDelayedMarking = aheader->arenaAddress() >> ArenaShift;
+    auxNextLink = aheader->arenaAddress() >> ArenaShift;
+}
+
+inline void
+ArenaHeader::unsetDelayedMarking()
+{
+    JS_ASSERT(hasDelayedMarking);
+    hasDelayedMarking = 0;
+    auxNextLink = 0;
+}
+
+inline ArenaHeader *
+ArenaHeader::getNextAllocDuringSweep() const
+{
+    JS_ASSERT(allocatedDuringIncremental);
+    return &reinterpret_cast<Arena *>(auxNextLink << ArenaShift)->aheader;
+}
+
+inline void
+ArenaHeader::setNextAllocDuringSweep(ArenaHeader *aheader)
+{
+    JS_ASSERT(!auxNextLink && !allocatedDuringIncremental);
+    allocatedDuringIncremental = 1;
+    auxNextLink = aheader->arenaAddress() >> ArenaShift;
+}
+
+inline void
+ArenaHeader::unsetAllocDuringSweep()
+{
+    JS_ASSERT(allocatedDuringIncremental);
+    allocatedDuringIncremental = 0;
+    auxNextLink = 0;
 }
 
 JS_ALWAYS_INLINE void
 ChunkBitmap::getMarkWordAndMask(const Cell *cell, uint32_t color,
                                 uintptr_t **wordp, uintptr_t *maskp)
 {
     size_t bit = (cell->address() & ChunkMask) / Cell::CellSize + color;
     JS_ASSERT(bit < ArenaBitmapBits * ArenasPerChunk);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -771,16 +771,21 @@ JSRuntime::JSRuntime()
     gcNumber(0),
     gcStartNumber(0),
     gcIsFull(false),
     gcTriggerReason(gcreason::NO_REASON),
     gcStrictCompartmentChecking(false),
     gcDisableStrictProxyCheckingCount(0),
     gcIncrementalState(gc::NO_INCREMENTAL),
     gcLastMarkSlice(false),
+    gcSweepOnBackgroundThread(false),
+    gcSweepPhase(0),
+    gcSweepCompartmentIndex(0),
+    gcSweepKindIndex(0),
+    gcArenasAllocatedDuringSweep(NULL),
     gcInterFrameGC(0),
     gcSliceBudget(SliceBudget::Unlimited),
     gcIncrementalEnabled(true),
     gcExactScanningEnabled(true),
     gcPoke(false),
     heapState(Idle),
 #ifdef JS_GC_ZEAL
     gcZeal_(0),
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -559,16 +559,31 @@ struct JSRuntime : js::RuntimeFriendFiel
      * The current incremental GC phase. During non-incremental GC, this is
      * always NO_INCREMENTAL.
      */
     js::gc::State       gcIncrementalState;
 
     /* Indicates that the last incremental slice exhausted the mark stack. */
     bool                gcLastMarkSlice;
 
+    /* Whether any sweeping will take place in the separate GC helper thread. */
+    bool                gcSweepOnBackgroundThread;
+
+    /*
+     * Incremental sweep state.
+     */
+    int                gcSweepPhase;
+    ptrdiff_t          gcSweepCompartmentIndex;
+    int                gcSweepKindIndex;
+
+    /*
+     * List head of arenas allocated during the sweep phase.
+     */
+    js::gc::ArenaHeader *gcArenasAllocatedDuringSweep;
+
     /*
      * Indicates that a GC slice has taken place in the middle of an animation
      * frame, rather than at the beginning. In this case, the next slice will be
      * delayed so that we don't get back-to-back slices.
      */
     volatile uintptr_t  gcInterFrameGC;
 
     /* Default budget for incremental GC slice. See SliceBudget in jsgc.h. */
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -42,16 +42,17 @@ JSCompartment::JSCompartment(JSRuntime *
     principals(NULL),
     global_(NULL),
 #ifdef JSGC_GENERATIONAL
     gcStoreBuffer(&gcNursery),
 #endif
     needsBarrier_(false),
     gcState(NoGCScheduled),
     gcPreserveCode(false),
+    gcStarted(false),
     gcBytes(0),
     gcTriggerBytes(0),
     gcHeapGrowthFactor(3.0),
     hold(false),
     isSystemCompartment(false),
     lastCodeRelease(0),
     typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     data(NULL),
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -169,16 +169,17 @@ struct JSCompartment
     enum CompartmentGCState {
         NoGCScheduled,
         GCScheduled,
         GCRunning
     };
 
     CompartmentGCState           gcState;
     bool                         gcPreserveCode;
+    bool                         gcStarted;
 
   public:
     bool isCollecting() const {
         /* Allow this if we're in the middle of an incremental GC. */
         if (rt->isHeapBusy()) {
             return gcState == GCRunning;
         } else {
             JS_ASSERT(gcState != GCRunning);
@@ -221,16 +222,29 @@ struct JSCompartment
     bool isGCScheduled() const {
         return gcState == GCScheduled;
     }
 
     void setPreservingCode(bool preserving) {
         gcPreserveCode = preserving;
     }
 
+    bool wasGCStarted() const {
+        return gcStarted;
+    }
+
+    void setGCStarted(bool started) {
+        JS_ASSERT(rt->isHeapBusy());
+        gcStarted = started;
+    }
+
+    bool isGCSweeping() {
+        return wasGCStarted() && rt->gcIncrementalState == js::gc::SWEEP;
+    }
+
     size_t                       gcBytes;
     size_t                       gcTriggerBytes;
     size_t                       gcMaxMallocBytes;
     double                       gcHeapGrowthFactor;
 
     bool                         hold;
     bool                         isSystemCompartment;
 
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -122,17 +122,17 @@ js::PrepareForFullGC(JSRuntime *rt)
 
 JS_FRIEND_API(void)
 js::PrepareForIncrementalGC(JSRuntime *rt)
 {
     if (rt->gcIncrementalState == gc::NO_INCREMENTAL)
         return;
 
     for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        if (c->needsBarrier())
+        if (c->wasGCStarted())
             PrepareCompartmentForGC(c);
     }
 }
 
 JS_FRIEND_API(bool)
 js::IsGCScheduled(JSRuntime *rt)
 {
     for (CompartmentsIter c(rt); !c.done(); c.next()) {
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -627,16 +627,17 @@ SizeOfJSContext();
     D(LAST_CONTEXT)                             \
     D(DESTROY_CONTEXT)                          \
     D(LAST_DITCH)                               \
     D(TOO_MUCH_MALLOC)                          \
     D(ALLOC_TRIGGER)                            \
     D(DEBUG_GC)                                 \
     D(DEBUG_MODE_GC)                            \
     D(TRANSPLANT)                               \
+    D(RESET)                                    \
                                                 \
     /* Reasons from Firefox */                  \
     D(DOM_WINDOW_UTILS)                         \
     D(COMPONENT_UTILS)                          \
     D(MEM_PRESSURE)                             \
     D(CC_WAITING)                               \
     D(CC_FORCED)                                \
     D(LOAD_END)                                 \
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -195,16 +195,39 @@ const uint32_t Arena::FirstThingOffsets[
 #endif
     OFFSET(JSShortString),      /* FINALIZE_SHORT_STRING        */
     OFFSET(JSString),           /* FINALIZE_STRING              */
     OFFSET(JSExternalString),   /* FINALIZE_EXTERNAL_STRING     */
 };
 
 #undef OFFSET
 
+/*
+ * Finalization order for incrementally swept things.
+ */
+
+static const AllocKind FinalizePhaseShapes[] = {
+    FINALIZE_SHAPE,
+    FINALIZE_BASE_SHAPE,
+    FINALIZE_TYPE_OBJECT
+};
+
+static const AllocKind* FinalizePhases[] = {
+    FinalizePhaseShapes
+};
+static const int FinalizePhaseCount = sizeof(FinalizePhases) / sizeof(AllocKind*);
+
+static const int FinalizePhaseLength[] = {
+    sizeof(FinalizePhaseShapes) / sizeof(AllocKind)
+};
+
+static const gcstats::Phase FinalizePhaseStatsPhase[] = {
+    gcstats::PHASE_SWEEP_SHAPE
+};
+
 #ifdef DEBUG
 void
 ArenaHeader::checkSynchronizedWithFreeList() const
 {
     /*
      * Do not allow to access the free list when its real head is still stored
      * in FreeLists and is not synchronized with this one.
      */
@@ -322,98 +345,106 @@ Arena::finalize(FreeOp *fop, AllocKind t
     nfree += (newListTail->last + 1 - newListTail->first) / thingSize;
     JS_ASSERT(nfree + nmarked == thingsPerArena(thingSize));
 #endif
     aheader.setFirstFreeSpan(&newListHead);
 
     return false;
 }
 
+/*
+ * Insert an arena into the list in appropriate position and update the cursor
+ * to ensure that any arena before the cursor is full.
+ */
+void ArenaList::insert(ArenaHeader *a)
+{
+    JS_ASSERT(a);
+    JS_ASSERT_IF(!head, cursor == &head);
+    a->next = *cursor;
+    *cursor = a;
+    if (!a->hasFreeThings())
+        cursor = &a->next;
+}
+
 template<typename T>
-inline void
-FinalizeTypedArenas(FreeOp *fop, ArenaLists::ArenaList *al, AllocKind thingKind)
+inline bool
+FinalizeTypedArenas(FreeOp *fop,
+                    ArenaHeader **src,
+                    ArenaList &dest,
+                    AllocKind thingKind,
+                    SliceBudget &budget)
 {
     /*
-     * Release empty arenas and move non-full arenas with some free things into
-     * a separated list that we append to al after the loop to ensure that any
-     * arena before al->cursor is full.
+     * Finalize arenas from src list, releasing empty arenas and inserting the
+     * others into dest in an appropriate position.
      */
-    JS_ASSERT_IF(!al->head, al->cursor == &al->head);
-    ArenaLists::ArenaList available;
-    ArenaHeader **ap = &al->head;
+
     size_t thingSize = Arena::thingSize(thingKind);
-    while (ArenaHeader *aheader = *ap) {
+
+    while (ArenaHeader *aheader = *src) {
+        *src = aheader->next;
         bool allClear = aheader->getArena()->finalize<T>(fop, thingKind, thingSize);
-        if (allClear) {
-            *ap = aheader->next;
+        if (allClear)
             aheader->chunk()->releaseArena(aheader);
-        } else if (aheader->hasFreeThings()) {
-            *ap = aheader->next;
-            *available.cursor = aheader;
-            available.cursor = &aheader->next;
-        } else {
-            ap = &aheader->next;
-        }
+        else
+            dest.insert(aheader);
+        budget.step(Arena::thingsPerArena(thingSize));
+        if (budget.isOverBudget())
+            return false;
     }
 
-    /* Terminate the available list and append it to al. */
-    *available.cursor = NULL;
-    *ap = available.head;
-    al->cursor = ap;
-    JS_ASSERT_IF(!al->head, al->cursor == &al->head);
+    return true;
 }
 
 /*
  * Finalize the list. On return al->cursor points to the first non-empty arena
  * after the al->head.
  */
-static void
-FinalizeArenas(FreeOp *fop, ArenaLists::ArenaList *al, AllocKind thingKind)
+static bool
+FinalizeArenas(FreeOp *fop,
+               ArenaHeader **src,
+               ArenaList &dest,
+               AllocKind thingKind,
+               SliceBudget &budget)
 {
     switch(thingKind) {
       case FINALIZE_OBJECT0:
       case FINALIZE_OBJECT0_BACKGROUND:
       case FINALIZE_OBJECT2:
       case FINALIZE_OBJECT2_BACKGROUND:
       case FINALIZE_OBJECT4:
       case FINALIZE_OBJECT4_BACKGROUND:
       case FINALIZE_OBJECT8:
       case FINALIZE_OBJECT8_BACKGROUND:
       case FINALIZE_OBJECT12:
       case FINALIZE_OBJECT12_BACKGROUND:
       case FINALIZE_OBJECT16:
       case FINALIZE_OBJECT16_BACKGROUND:
-        FinalizeTypedArenas<JSObject>(fop, al, thingKind);
-        break;
+        return FinalizeTypedArenas<JSObject>(fop, src, dest, thingKind, budget);
       case FINALIZE_SCRIPT:
-	FinalizeTypedArenas<JSScript>(fop, al, thingKind);
-        break;
+	return FinalizeTypedArenas<JSScript>(fop, src, dest, thingKind, budget);
       case FINALIZE_SHAPE:
-	FinalizeTypedArenas<Shape>(fop, al, thingKind);
-        break;
+	return FinalizeTypedArenas<Shape>(fop, src, dest, thingKind, budget);
       case FINALIZE_BASE_SHAPE:
-        FinalizeTypedArenas<BaseShape>(fop, al, thingKind);
-        break;
+        return FinalizeTypedArenas<BaseShape>(fop, src, dest, thingKind, budget);
       case FINALIZE_TYPE_OBJECT:
-	FinalizeTypedArenas<types::TypeObject>(fop, al, thingKind);
-        break;
+	return FinalizeTypedArenas<types::TypeObject>(fop, src, dest, thingKind, budget);
 #if JS_HAS_XML_SUPPORT
       case FINALIZE_XML:
-	FinalizeTypedArenas<JSXML>(fop, al, thingKind);
-        break;
+	return FinalizeTypedArenas<JSXML>(fop, src, dest, thingKind, budget);
 #endif
       case FINALIZE_STRING:
-	FinalizeTypedArenas<JSString>(fop, al, thingKind);
-        break;
+	return FinalizeTypedArenas<JSString>(fop, src, dest, thingKind, budget);
       case FINALIZE_SHORT_STRING:
-	FinalizeTypedArenas<JSShortString>(fop, al, thingKind);
-        break;
+	return FinalizeTypedArenas<JSShortString>(fop, src, dest, thingKind, budget);
       case FINALIZE_EXTERNAL_STRING:
-	FinalizeTypedArenas<JSExternalString>(fop, al, thingKind);
-        break;
+	return FinalizeTypedArenas<JSExternalString>(fop, src, dest, thingKind, budget);
+      default:
+        JS_NOT_REACHED("Invalid alloc kind");
+        return true;
     }
 }
 
 static inline Chunk *
 AllocChunk() {
     return static_cast<Chunk *>(MapAlignedPages(ChunkSize, ChunkSize));
 }
 
@@ -1431,16 +1462,23 @@ ArenaLists::prepareForIncrementalGC(JSRu
         if (!headSpan->isEmpty()) {
             ArenaHeader *aheader = headSpan->arenaHeader();
             aheader->allocatedDuringIncremental = true;
             rt->gcMarker.delayMarkingArena(aheader);
         }
     }
 }
 
+static inline void
+PushArenaAllocatedDuringSweep(JSRuntime *runtime, ArenaHeader *arena)
+{
+    arena->setNextAllocDuringSweep(runtime->gcArenasAllocatedDuringSweep);
+    runtime->gcArenasAllocatedDuringSweep = arena;
+}
+
 inline void *
 ArenaLists::allocateFromArena(JSCompartment *comp, AllocKind thingKind)
 {
     Chunk *chunk = NULL;
 
     ArenaList *al = &arenaLists[thingKind];
     AutoLockGC maybeLock;
 
@@ -1484,19 +1522,23 @@ ArenaLists::allocateFromArena(JSCompartm
             al->cursor = &aheader->next;
 
             /*
              * Move the free span stored in the arena to the free list and
              * allocate from it.
              */
             freeLists[thingKind] = aheader->getFirstFreeSpan();
             aheader->setAsFullyUsed();
-            if (JS_UNLIKELY(comp->needsBarrier())) {
-                aheader->allocatedDuringIncremental = true;
-                comp->rt->gcMarker.delayMarkingArena(aheader);
+            if (JS_UNLIKELY(comp->wasGCStarted())) {
+                if (comp->needsBarrier()) {
+                    aheader->allocatedDuringIncremental = true;
+                    comp->rt->gcMarker.delayMarkingArena(aheader);
+                } else if (comp->isGCSweeping()) {
+                    PushArenaAllocatedDuringSweep(comp->rt, aheader);
+                }
             }
             return freeLists[thingKind].infallibleAllocate(Arena::thingSize(thingKind));
         }
 
         /* Make sure we hold the GC lock before we call PickChunk. */
         if (!maybeLock.locked())
             maybeLock.lock(comp->rt);
         chunk = PickChunk(comp);
@@ -1513,19 +1555,23 @@ ArenaLists::allocateFromArena(JSCompartm
      * cursor, so after the GC the most recently added arena will be used first
      * for allocations improving cache locality.
      */
     JS_ASSERT(!*al->cursor);
     ArenaHeader *aheader = chunk->allocateArena(comp, thingKind);
     if (!aheader)
         return NULL;
 
-    if (JS_UNLIKELY(comp->needsBarrier())) {
-        aheader->allocatedDuringIncremental = true;
-        comp->rt->gcMarker.delayMarkingArena(aheader);
+    if (JS_UNLIKELY(comp->wasGCStarted())) {
+        if (comp->needsBarrier()) {
+            aheader->allocatedDuringIncremental = true;
+            comp->rt->gcMarker.delayMarkingArena(aheader);
+        } else if (comp->isGCSweeping()) {
+            PushArenaAllocatedDuringSweep(comp->rt, aheader);
+        }
     }
     aheader->next = al->head;
     if (!al->head) {
         JS_ASSERT(al->cursor == &al->head);
         al->cursor = &aheader->next;
     }
     al->head = aheader;
 
@@ -1536,22 +1582,39 @@ ArenaLists::allocateFromArena(JSCompartm
                                                      Arena::firstThingOffset(thingKind),
                                                      Arena::thingSize(thingKind));
 }
 
 void
 ArenaLists::finalizeNow(FreeOp *fop, AllocKind thingKind)
 {
     JS_ASSERT(!fop->onBackgroundThread());
+    JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE ||
+              backgroundFinalizeState[thingKind] == BFS_JUST_FINISHED);
+
+    ArenaHeader *arenas = arenaLists[thingKind].head;
+    arenaLists[thingKind].clear();
+
+    SliceBudget budget;
+    FinalizeArenas(fop, &arenas, arenaLists[thingKind], thingKind, budget);
+    JS_ASSERT(!arenas);
+}
+
+void
+ArenaLists::queueForForegroundSweep(FreeOp *fop, AllocKind thingKind)
+{
+    JS_ASSERT(!fop->onBackgroundThread());
     JS_ASSERT(backgroundFinalizeState[thingKind] == BFS_DONE);
-    FinalizeArenas(fop, &arenaLists[thingKind], thingKind);
+    JS_ASSERT(!arenaListsToSweep[thingKind]);
+    arenaListsToSweep[thingKind] = arenaLists[thingKind].head;
+    arenaLists[thingKind].clear();
 }
 
 inline void
-ArenaLists::finalizeLater(FreeOp *fop, AllocKind thingKind)
+ArenaLists::queueForBackgroundSweep(FreeOp *fop, AllocKind thingKind)
 {
     JS_ASSERT(thingKind == FINALIZE_OBJECT0_BACKGROUND  ||
               thingKind == FINALIZE_OBJECT2_BACKGROUND  ||
               thingKind == FINALIZE_OBJECT4_BACKGROUND  ||
               thingKind == FINALIZE_OBJECT8_BACKGROUND  ||
               thingKind == FINALIZE_OBJECT12_BACKGROUND ||
               thingKind == FINALIZE_OBJECT16_BACKGROUND ||
               thingKind == FINALIZE_SHORT_STRING        ||
@@ -1580,17 +1643,17 @@ ArenaLists::finalizeLater(FreeOp *fop, A
          * To ensure the finalization order even during the background GC we
          * must use infallibleAppend so arenas scheduled for background
          * finalization would not be finalized now if the append fails.
          */
         fop->runtime()->gcHelperThread.finalizeVector.infallibleAppend(al->head);
         al->clear();
         backgroundFinalizeState[thingKind] = BFS_RUN;
     } else {
-        FinalizeArenas(fop, al, thingKind);
+        finalizeNow(fop, thingKind);
         backgroundFinalizeState[thingKind] = BFS_DONE;
     }
 
 #else /* !JS_THREADSAFE */
 
     finalizeNow(fop, thingKind);
 
 #endif
@@ -1600,19 +1663,21 @@ ArenaLists::finalizeLater(FreeOp *fop, A
 ArenaLists::backgroundFinalize(FreeOp *fop, ArenaHeader *listHead)
 {
 #ifdef JS_THREADSAFE
     JS_ASSERT(fop->onBackgroundThread());
 #endif /* JS_THREADSAFE */
     JS_ASSERT(listHead);
     AllocKind thingKind = listHead->getAllocKind();
     JSCompartment *comp = listHead->compartment;
+
     ArenaList finalized;
-    finalized.head = listHead;
-    FinalizeArenas(fop, &finalized, thingKind);
+    SliceBudget budget;
+    FinalizeArenas(fop, &listHead, finalized, thingKind, budget);
+    JS_ASSERT(!listHead);
 
     /*
      * After we finish the finalization al->cursor must point to the end of
      * the head list as we emptied the list before the background finalization
      * and the allocation adds new arenas before the cursor.
      */
     ArenaLists *lists = &comp->arenas;
     ArenaList *al = &lists->arenaLists[thingKind];
@@ -1636,58 +1701,58 @@ ArenaLists::backgroundFinalize(FreeOp *f
             al->cursor = finalized.cursor;
         lists->backgroundFinalizeState[thingKind] = BFS_JUST_FINISHED;
     } else {
         lists->backgroundFinalizeState[thingKind] = BFS_DONE;
     }
 }
 
 void
-ArenaLists::finalizeObjects(FreeOp *fop)
+ArenaLists::queueObjectsForSweep(FreeOp *fop)
 {
     finalizeNow(fop, FINALIZE_OBJECT0);
     finalizeNow(fop, FINALIZE_OBJECT2);
     finalizeNow(fop, FINALIZE_OBJECT4);
     finalizeNow(fop, FINALIZE_OBJECT8);
     finalizeNow(fop, FINALIZE_OBJECT12);
     finalizeNow(fop, FINALIZE_OBJECT16);
 
-    finalizeLater(fop, FINALIZE_OBJECT0_BACKGROUND);
-    finalizeLater(fop, FINALIZE_OBJECT2_BACKGROUND);
-    finalizeLater(fop, FINALIZE_OBJECT4_BACKGROUND);
-    finalizeLater(fop, FINALIZE_OBJECT8_BACKGROUND);
-    finalizeLater(fop, FINALIZE_OBJECT12_BACKGROUND);
-    finalizeLater(fop, FINALIZE_OBJECT16_BACKGROUND);
+    queueForBackgroundSweep(fop, FINALIZE_OBJECT0_BACKGROUND);
+    queueForBackgroundSweep(fop, FINALIZE_OBJECT2_BACKGROUND);
+    queueForBackgroundSweep(fop, FINALIZE_OBJECT4_BACKGROUND);
+    queueForBackgroundSweep(fop, FINALIZE_OBJECT8_BACKGROUND);
+    queueForBackgroundSweep(fop, FINALIZE_OBJECT12_BACKGROUND);
+    queueForBackgroundSweep(fop, FINALIZE_OBJECT16_BACKGROUND);
 
 #if JS_HAS_XML_SUPPORT
     finalizeNow(fop, FINALIZE_XML);
 #endif
 }
 
 void
-ArenaLists::finalizeStrings(FreeOp *fop)
-{
-    finalizeLater(fop, FINALIZE_SHORT_STRING);
-    finalizeLater(fop, FINALIZE_STRING);
+ArenaLists::queueStringsForSweep(FreeOp *fop)
+{
+    queueForBackgroundSweep(fop, FINALIZE_SHORT_STRING);
+    queueForBackgroundSweep(fop, FINALIZE_STRING);
 
     finalizeNow(fop, FINALIZE_EXTERNAL_STRING);
 }
 
 void
-ArenaLists::finalizeShapes(FreeOp *fop)
-{
-    finalizeNow(fop, FINALIZE_SHAPE);
-    finalizeNow(fop, FINALIZE_BASE_SHAPE);
-    finalizeNow(fop, FINALIZE_TYPE_OBJECT);
+ArenaLists::queueScriptsForSweep(FreeOp *fop)
+{
+    finalizeNow(fop, FINALIZE_SCRIPT);
 }
 
 void
-ArenaLists::finalizeScripts(FreeOp *fop)
-{
-    finalizeNow(fop, FINALIZE_SCRIPT);
+ArenaLists::queueShapesForSweep(FreeOp *fop)
+{
+    queueForForegroundSweep(fop, FINALIZE_SHAPE);
+    queueForForegroundSweep(fop, FINALIZE_BASE_SHAPE);
+    queueForForegroundSweep(fop, FINALIZE_TYPE_OBJECT);
 }
 
 static void
 RunLastDitchGC(JSContext *cx, gcreason::Reason reason)
 {
     JSRuntime *rt = cx->runtime;
 
     /* The last ditch GC preserves all atoms. */
@@ -1918,17 +1983,17 @@ GCMarker::reset()
     stack.reset();
     JS_ASSERT(isMarkStackEmpty());
 
     while (unmarkedArenaStackTop) {
         ArenaHeader *aheader = unmarkedArenaStackTop;
         JS_ASSERT(aheader->hasDelayedMarking);
         JS_ASSERT(markLaterArenas);
         unmarkedArenaStackTop = aheader->getNextDelayedMarking();
-        aheader->hasDelayedMarking = 0;
+        aheader->unsetDelayedMarking();
         aheader->markOverflow = 0;
         aheader->allocatedDuringIncremental = 0;
         markLaterArenas--;
     }
     JS_ASSERT(isDrained());
     JS_ASSERT(!markLaterArenas);
 
     grayRoots.clearAndFree();
@@ -2001,17 +2066,17 @@ GCMarker::markDelayedChildren(SliceBudge
          * If marking gets delayed at the same arena again, we must repeat
          * marking of its things. For that we pop arena from the stack and
          * clear its hasDelayedMarking flag before we begin the marking.
          */
         ArenaHeader *aheader = unmarkedArenaStackTop;
         JS_ASSERT(aheader->hasDelayedMarking);
         JS_ASSERT(markLaterArenas);
         unmarkedArenaStackTop = aheader->getNextDelayedMarking();
-        aheader->hasDelayedMarking = 0;
+        aheader->unsetDelayedMarking();
         markLaterArenas--;
         markDelayedChildren(aheader);
 
         budget.step(150);
         if (budget.isOverBudget())
             return false;
     } while (unmarkedArenaStackTop);
     JS_ASSERT(!markLaterArenas);
@@ -3037,33 +3102,35 @@ ReleaseObservedTypes(JSRuntime *rt)
     if (releaseTypes)
         rt->gcJitReleaseTime = now + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
 #endif
 
     return releaseTypes;
 }
 
 static void
-SweepCompartments(FreeOp *fop, JSGCInvocationKind gckind)
+SweepCompartments(FreeOp *fop, gcreason::Reason gcReason)
 {
     JSRuntime *rt = fop->runtime();
+    JS_ASSERT_IF(gcReason == gcreason::LAST_CONTEXT, !rt->hasContexts());
+
     JSDestroyCompartmentCallback callback = rt->destroyCompartmentCallback;
 
     /* Skip the atomsCompartment. */
     JSCompartment **read = rt->compartments.begin() + 1;
     JSCompartment **end = rt->compartments.end();
     JSCompartment **write = read;
     JS_ASSERT(rt->compartments.length() >= 1);
     JS_ASSERT(*rt->compartments.begin() == rt->atomsCompartment);
 
     while (read < end) {
         JSCompartment *compartment = *read++;
 
         if (!compartment->hold && compartment->isCollecting() &&
-            (compartment->arenas.arenaListsAreEmpty() || !rt->hasContexts()))
+            (compartment->arenas.arenaListsAreEmpty() || gcReason == gcreason::LAST_CONTEXT))
         {
             compartment->arenas.checkEmptyFreeLists();
             if (callback)
                 callback(fop, compartment);
             if (compartment->principals)
                 JS_DropPrincipals(rt, compartment->principals);
             fop->delete_(compartment);
             continue;
@@ -3128,17 +3195,23 @@ BeginMarkPhase(JSRuntime *rt, bool isInc
      */
     if (isIncremental) {
         for (GCCompartmentsIter c(rt); !c.done(); c.next())
             c->arenas.purge();
     }
 
     rt->gcIsFull = true;
     for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        if (!c->isCollecting())
+        JS_ASSERT(!c->wasGCStarted());
+        for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i)
+            JS_ASSERT(!c->arenas.arenaListsToSweep[i]);
+
+        if (c->isCollecting())
+            c->setGCStarted(true);
+        else
             rt->gcIsFull = false;
 
         c->setPreservingCode(ShouldPreserveJITCode(c, currentTime));
     }
 
     rt->gcMarker.start(rt);
     JS_ASSERT(!rt->gcMarker.callback);
     JS_ASSERT(IS_GC_MARKING_TRACER(&rt->gcMarker));
@@ -3379,17 +3452,17 @@ ValidateIncrementalMarking(JSRuntime *rt
     WeakMapBase::resetWeakMapList(rt);
     WeakMapBase::restoreWeakMapList(rt, weakmaps);
 
     rt->gcIncrementalState = state;
 }
 #endif
 
 static void
-SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
+BeginSweepPhase(JSRuntime *rt)
 {
     /*
      * Sweep phase.
      *
      * Finalize as we sweep, outside of rt->gcLock but with rt->isHeapBusy()
      * true so that any attempt to allocate a GC-thing from a finalizer will
      * fail, rather than nest badly and leave the unmarked newborn to be swept.
      *
@@ -3407,23 +3480,24 @@ SweepPhase(JSRuntime *rt, JSGCInvocation
      * BeginMarkPhase. More compartments may have been created since then.
      */
     bool isFull = true;
     for (CompartmentsIter c(rt); !c.done(); c.next()) {
         if (!c->isCollecting())
             isFull = false;
     }
 
-    *startBackgroundSweep = (rt->hasContexts() && rt->gcHelperThread.prepareForBackgroundSweep());
+    rt->gcSweepOnBackgroundThread =
+        (rt->hasContexts() && rt->gcHelperThread.prepareForBackgroundSweep());
 
     /* Purge the ArenaLists before sweeping. */
     for (GCCompartmentsIter c(rt); !c.done(); c.next())
         c->arenas.purge();
 
-    FreeOp fop(rt, *startBackgroundSweep, false);
+    FreeOp fop(rt, rt->gcSweepOnBackgroundThread, false);
 
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_START);
         if (rt->gcFinalizeCallback)
             rt->gcFinalizeCallback(&fop, JSFINALIZE_START, !isFull);
     }
 
     /* Finalize unreachable (key,value) pairs in all weak maps. */
@@ -3448,47 +3522,92 @@ SweepPhase(JSRuntime *rt, JSGCInvocation
         for (CompartmentsIter c(rt); !c.done(); c.next()) {
             if (c->isCollecting())
                 c->sweep(&fop, releaseTypes);
             else
                 c->sweepCrossCompartmentWrappers();
         }
     }
 
-    {
-        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_OBJECT);
-
-        /*
-         * We finalize objects before other GC things to ensure that the object's
-         * finalizer can access the other things even if they will be freed.
-         */
-        for (GCCompartmentsIter c(rt); !c.done(); c.next())
-            c->arenas.finalizeObjects(&fop);
-    }
+    /*
+     * Queue all GC things in all compartments for sweeping, either in the
+     * foreground or on the background thread.
+     *
+     * Note that order is important here for the background case.
+     *
+     * Objects are finalized immediately but this may change in the future.
+     */
+    for (GCCompartmentsIter c(rt); !c.done(); c.next())
+        c->arenas.queueObjectsForSweep(&fop);
+    for (GCCompartmentsIter c(rt); !c.done(); c.next())
+        c->arenas.queueStringsForSweep(&fop);
+    for (GCCompartmentsIter c(rt); !c.done(); c.next())
+        c->arenas.queueScriptsForSweep(&fop);
+    for (GCCompartmentsIter c(rt); !c.done(); c.next())
+        c->arenas.queueShapesForSweep(&fop);
+
+    rt->gcSweepPhase = 0;
+    rt->gcSweepCompartmentIndex = 0;
+    rt->gcSweepKindIndex = 0;
 
     {
-        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_STRING);
-        for (GCCompartmentsIter c(rt); !c.done(); c.next())
-            c->arenas.finalizeStrings(&fop);
+        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_END);
+        if (rt->gcFinalizeCallback)
+            rt->gcFinalizeCallback(&fop, JSFINALIZE_END, !rt->gcIsFull);
     }
-
-    {
-        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_SCRIPT);
-        for (GCCompartmentsIter c(rt); !c.done(); c.next())
-            c->arenas.finalizeScripts(&fop);
+}
+
+bool
+ArenaLists::foregroundFinalize(FreeOp *fop, AllocKind thingKind, SliceBudget &sliceBudget)
+{
+    if (!arenaListsToSweep[thingKind])
+        return true;
+
+    ArenaList &dest = arenaLists[thingKind];
+    return FinalizeArenas(fop, &arenaListsToSweep[thingKind], dest, thingKind, sliceBudget);
+}
+
+static bool
+SweepPhase(JSRuntime *rt, SliceBudget &sliceBudget)
+{
+    gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
+    FreeOp fop(rt, rt->gcSweepOnBackgroundThread, false);
+
+    for (; rt->gcSweepPhase < FinalizePhaseCount ; ++rt->gcSweepPhase) {
+        gcstats::AutoPhase ap(rt->gcStats, FinalizePhaseStatsPhase[rt->gcSweepPhase]);
+
+        ptrdiff_t len = rt->compartments.end() - rt->compartments.begin();
+        for (; rt->gcSweepCompartmentIndex < len ; ++rt->gcSweepCompartmentIndex) {
+            JSCompartment *c = rt->compartments.begin()[rt->gcSweepCompartmentIndex];
+
+            if (c->wasGCStarted()) {
+                while (rt->gcSweepKindIndex < FinalizePhaseLength[rt->gcSweepPhase]) {
+                    AllocKind kind = FinalizePhases[rt->gcSweepPhase][rt->gcSweepKindIndex];
+
+                    if (!c->arenas.foregroundFinalize(&fop, kind, sliceBudget))
+                        return false;
+                    ++rt->gcSweepKindIndex;
+                }
+            }
+            rt->gcSweepKindIndex = 0;
+        }
+        rt->gcSweepCompartmentIndex = 0;
     }
 
-    {
-        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_SHAPE);
-        for (GCCompartmentsIter c(rt); !c.done(); c.next())
-            c->arenas.finalizeShapes(&fop);
-    }
+    return true;
+}
+
+static void
+EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, gcreason::Reason gcReason)
+{
+    gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
+    FreeOp fop(rt, rt->gcSweepOnBackgroundThread, false);
 
 #ifdef DEBUG
-     PropertyTree::dumpShapes(rt);
+    PropertyTree::dumpShapes(rt);
 #endif
 
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DESTROY);
 
         /*
          * Sweep script filenames after sweeping functions in the generic loop
          * above. In this way when a scripted function's finalizer destroys the
@@ -3499,36 +3618,46 @@ SweepPhase(JSRuntime *rt, JSGCInvocation
             SweepScriptFilenames(rt);
             ScriptSource::sweep(rt);
         }
 
         /*
          * This removes compartments from rt->compartment, so we do it last to make
          * sure we don't miss sweeping any compartments.
          */
-        SweepCompartments(&fop, gckind);
+        SweepCompartments(&fop, gcReason);
 
 #ifndef JS_THREADSAFE
         /*
          * Destroy arenas after we finished the sweeping so finalizers can safely
          * use IsAboutToBeFinalized().
          * This is done on the GCHelperThread if JS_THREADSAFE is defined.
          */
         ExpireChunksAndArenas(rt, gckind == GC_SHRINK);
 #endif
     }
 
-    {
-        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_END);
-        if (rt->gcFinalizeCallback)
-            rt->gcFinalizeCallback(&fop, JSFINALIZE_END, !isFull);
+    /*
+     * Reset the list of arenas marked as being allocated during sweep phase.
+     */
+    while (ArenaHeader *arena = rt->gcArenasAllocatedDuringSweep) {
+        rt->gcArenasAllocatedDuringSweep = arena->getNextAllocDuringSweep();
+        arena->unsetAllocDuringSweep();
     }
 
-    for (CompartmentsIter c(rt); !c.done(); c.next())
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
         c->setGCLastBytes(c->gcBytes, c->gcMallocAndFreeBytes, gckind);
+        if (c->wasGCStarted())
+            c->setGCStarted(false);
+
+        JS_ASSERT(!c->wasGCStarted());
+        for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i)
+            JS_ASSERT(!c->arenas.arenaListsToSweep[i]);
+    }
+
     rt->gcLastGCTime = PRMJ_Now();
 }
 
 /*
  * This class should be used by any code that needs to exclusive access to the
  * heap in order to trace through it...
  */
 class AutoTraceSession {
@@ -3604,26 +3733,47 @@ AutoGCSession::~AutoGCSession()
     /* Clear gcMallocBytes for all compartments */
     for (CompartmentsIter c(runtime); !c.done(); c.next())
         c->resetGCMallocBytes();
 
     runtime->resetGCMallocBytes();
 }
 
 static void
+IncrementalCollectSlice(JSRuntime *rt,
+                        int64_t budget,
+                        gcreason::Reason gcReason,
+                        JSGCInvocationKind gcKind);
+
+static void
 ResetIncrementalGC(JSRuntime *rt, const char *reason)
 {
     if (rt->gcIncrementalState == NO_INCREMENTAL)
         return;
 
-    for (CompartmentsIter c(rt); !c.done(); c.next())
+    if (rt->gcIncrementalState == SWEEP) {
+        /* If we've finished marking then sweep to completion here. */
+        IncrementalCollectSlice(rt, SliceBudget::Unlimited, gcreason::RESET, GC_NORMAL);
+        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
+        rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
+        return;
+    }
+
+    JS_ASSERT(rt->gcIncrementalState == MARK);
+
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
         c->setNeedsBarrier(false);
+        c->setGCStarted(false);
+        for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i)
+            JS_ASSERT(!c->arenas.arenaListsToSweep[i]);
+    }
 
     rt->gcMarker.reset();
     rt->gcMarker.stop();
+
     rt->gcIncrementalState = NO_INCREMENTAL;
 
     JS_ASSERT(!rt->gcStrictCompartmentChecking);
 
     rt->gcStats.reset(reason);
 }
 
 class AutoGCSlice {
@@ -3643,31 +3793,34 @@ AutoGCSlice::AutoGCSlice(JSRuntime *rt)
      * there are stack frames active for any of its scripts. Normally this flag
      * is set at the beginning of the mark phase. During incremental GC, we also
      * set it at the start of every phase.
      */
     rt->stackSpace.markActiveCompartments();
 
     for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
         /* Clear this early so we don't do any write barriers during GC. */
-        if (rt->gcIncrementalState == MARK)
+        if (rt->gcIncrementalState == MARK) {
+            JS_ASSERT(c->needsBarrier());
             c->setNeedsBarrier(false);
-        else
+        } else {
             JS_ASSERT(!c->needsBarrier());
+        }
     }
 }
 
 AutoGCSlice::~AutoGCSlice()
 {
     for (GCCompartmentsIter c(runtime); !c.done(); c.next()) {
         if (runtime->gcIncrementalState == MARK) {
             c->setNeedsBarrier(true);
             c->arenas.prepareForIncrementalGC(runtime);
         } else {
-            JS_ASSERT(runtime->gcIncrementalState == NO_INCREMENTAL);
+            JS_ASSERT(runtime->gcIncrementalState == NO_INCREMENTAL ||
+                      runtime->gcIncrementalState == SWEEP);
             c->setNeedsBarrier(false);
         }
     }
 }
 
 class AutoCopyFreeListToArenas {
     JSRuntime *rt;
 
@@ -3680,88 +3833,154 @@ class AutoCopyFreeListToArenas {
 
     ~AutoCopyFreeListToArenas() {
         for (CompartmentsIter c(rt); !c.done(); c.next())
             c->arenas.clearFreeListsInArenas();
     }
 };
 
 static void
-IncrementalMarkSlice(JSRuntime *rt, int64_t budget, gcreason::Reason reason, bool *shouldSweep)
-{
+PushZealSelectedObjects(JSRuntime *rt)
+{
+#ifdef JS_GC_ZEAL
+    /* Push selected objects onto the mark stack and clear the list. */
+    for (JSObject **obj = rt->gcSelectedForMarking.begin();
+         obj != rt->gcSelectedForMarking.end(); obj++)
+    {
+        MarkObjectUnbarriered(&rt->gcMarker, obj, "selected obj");
+    }
+#endif
+}
+
+static bool
+DrainMarkStack(JSRuntime *rt, SliceBudget &sliceBudget)
+{
+    /* Run a marking slice and return whether the stack is now empty. */
+    gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK);
+    return rt->gcMarker.drainMarkStack(sliceBudget);
+}
+
+static void
+IncrementalCollectSlice(JSRuntime *rt,
+                        int64_t budget,
+                        gcreason::Reason reason,
+                        JSGCInvocationKind gckind)
+{
+    AutoCopyFreeListToArenas copy(rt);
     AutoGCSlice slice(rt);
 
     gc::State initialState = rt->gcIncrementalState;
-
-    *shouldSweep = false;
+    SliceBudget sliceBudget(budget);
 
     int zeal = 0;
 #ifdef JS_GC_ZEAL
     if (reason == gcreason::DEBUG_GC) {
-        // Do the collection type specified by zeal mode only if the collection
-        // was triggered by RunDebugGC().
+        /*
+         * Do the collection type specified by zeal mode only if the collection
+         * was triggered by RunDebugGC().
+         */
         zeal = rt->gcZeal();
+        JS_ASSERT_IF(zeal == ZealIncrementalMarkAllThenFinish ||
+                     zeal == ZealIncrementalRootsThenFinish,
+                     budget == SliceBudget::Unlimited);
     }
 #endif
 
     bool isIncremental = rt->gcIncrementalState != NO_INCREMENTAL ||
                          budget != SliceBudget::Unlimited ||
                          zeal == ZealIncrementalRootsThenFinish ||
                          zeal == ZealIncrementalMarkAllThenFinish;
 
     if (rt->gcIncrementalState == NO_INCREMENTAL) {
         rt->gcIncrementalState = MARK_ROOTS;
         rt->gcLastMarkSlice = false;
     }
 
-    if (rt->gcIncrementalState == MARK_ROOTS) {
+    switch (rt->gcIncrementalState) {
+
+      case MARK_ROOTS:
         BeginMarkPhase(rt, isIncremental);
+        PushZealSelectedObjects(rt);
+
         rt->gcIncrementalState = MARK;
 
         if (zeal == ZealIncrementalRootsThenFinish)
-            return;
-    }
-
-    if (rt->gcIncrementalState == MARK) {
-        SliceBudget sliceBudget(budget);
+            break;
+
+        /* fall through */
+
+      case MARK: {
 
         /* If we needed delayed marking for gray roots, then collect until done. */
         if (!rt->gcMarker.hasBufferedGrayRoots())
             sliceBudget.reset();
 
-#ifdef JS_GC_ZEAL
-        if (!rt->gcSelectedForMarking.empty()) {
-            for (JSObject **obj = rt->gcSelectedForMarking.begin();
-                 obj != rt->gcSelectedForMarking.end(); obj++)
-            {
-                MarkObjectUnbarriered(&rt->gcMarker, obj, "selected obj");
-            }
-        }
-#endif
-
-        bool finished;
+        bool finished = DrainMarkStack(rt, sliceBudget);
+        if (!finished)
+            break;
+
+        JS_ASSERT(rt->gcMarker.isDrained());
+
+        if (!rt->gcLastMarkSlice &&
+            ((initialState == MARK && budget != SliceBudget::Unlimited) ||
+             zeal == ZealIncrementalMarkAllThenFinish))
         {
-            gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK);
-            finished = rt->gcMarker.drainMarkStack(sliceBudget);
+            /*
+             * Yield with the aim of starting the sweep in the next
+             * slice.  We will need to mark anything new on the stack
+             * when we resume, so we stay in MARK state.
+             */
+            rt->gcLastMarkSlice = true;
+            break;
         }
-        if (finished) {
-            JS_ASSERT(rt->gcMarker.isDrained());
-
-            if (!rt->gcLastMarkSlice &&
-                ((initialState == MARK && budget != SliceBudget::Unlimited) ||
-                 zeal == ZealIncrementalMarkAllThenFinish))
-            {
-                rt->gcLastMarkSlice = true;
-            } else {
-                EndMarkPhase(rt, isIncremental);
-                rt->gcIncrementalState = NO_INCREMENTAL;
-                *shouldSweep = true;
-            }
-        }
-    }
+
+        EndMarkPhase(rt, isIncremental);
+
+        rt->gcIncrementalState = SWEEP;
+
+        /*
+         * This runs to completion, but we don't continue if the budget is
+         * now exhasted.
+         */
+        BeginSweepPhase(rt);
+        if (sliceBudget.isOverBudget())
+            break;
+
+        /*
+         * Always yield here when running in incremental multi-slice zeal
+         * mode, so RunDebugGC can reset the slice buget.
+         */
+        if (budget != SliceBudget::Unlimited && zeal == ZealIncrementalMultipleSlices)
+            break;
+
+        /* fall through */
+      }
+
+      case SWEEP: {
+#ifdef DEBUG
+        for (CompartmentsIter c(rt); !c.done(); c.next())
+            JS_ASSERT(!c->needsBarrier());
+#endif
+
+        bool finished = SweepPhase(rt, sliceBudget);
+        if (!finished)
+            break;
+
+        EndSweepPhase(rt, gckind, reason);
+
+        if (rt->gcSweepOnBackgroundThread)
+            rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK);
+
+        rt->gcIncrementalState = NO_INCREMENTAL;
+        break;
+      }
+
+      default:
+        JS_ASSERT(false);
+     }
 }
 
 class IncrementalSafety
 {
     const char *reason_;
 
     IncrementalSafety(const char *reason) : reason_(reason) {}
 
@@ -3829,18 +4048,20 @@ BudgetIncrementalGC(JSRuntime *rt, int64
             rt->gcStats.nonincremental("allocation trigger");
         }
 
         if (c->isTooMuchMalloc()) {
             *budget = SliceBudget::Unlimited;
             rt->gcStats.nonincremental("malloc bytes trigger");
         }
 
-        if (c->isCollecting() != c->needsBarrier())
+        if (rt->gcIncrementalState != NO_INCREMENTAL &&
+            c->isCollecting() != c->wasGCStarted()) {
             reset = true;
+        }
     }
 
     if (reset)
         ResetIncrementalGC(rt, "compartment change");
 }
 
 /*
  * GC, repeatedly if necessary, until we think we have not created any new
@@ -3872,44 +4093,28 @@ GCCycle(JSRuntime *rt, bool incremental,
      * background allocation to finish so we can avoid taking the GC lock
      * when manipulating the chunks during the GC.
      */
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
         rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
     }
 
-    bool startBackgroundSweep = false;
     {
         if (!incremental) {
             /* If non-incremental GC was requested, reset incremental GC. */
             ResetIncrementalGC(rt, "requested");
             rt->gcStats.nonincremental("requested");
             budget = SliceBudget::Unlimited;
         } else {
             BudgetIncrementalGC(rt, &budget);
         }
 
-        AutoCopyFreeListToArenas copy(rt);
-
-        bool shouldSweep;
-        IncrementalMarkSlice(rt, budget, reason, &shouldSweep);
-
-#ifdef DEBUG
-        if (rt->gcIncrementalState == NO_INCREMENTAL) {
-            for (CompartmentsIter c(rt); !c.done(); c.next())
-                JS_ASSERT(!c->needsBarrier());
-        }
-#endif
-        if (shouldSweep)
-            SweepPhase(rt, gckind, &startBackgroundSweep);
+        IncrementalCollectSlice(rt, budget, reason, gckind);
     }
-
-    if (startBackgroundSweep)
-        rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK);
 }
 
 #ifdef JS_GC_ZEAL
 static bool
 IsDeterministicGCReason(gcreason::Reason reason)
 {
     if (reason > gcreason::DEBUG_GC && reason != gcreason::CC_FORCED)
         return false;
@@ -4265,30 +4470,44 @@ RunDebugGC(JSContext *cx)
     JSRuntime *rt = cx->runtime;
     PrepareForDebugGC(cx->runtime);
 
     int type = rt->gcZeal();
     if (type == ZealIncrementalRootsThenFinish ||
         type == ZealIncrementalMarkAllThenFinish ||
         type == ZealIncrementalMultipleSlices)
     {
+        js::gc::State initialState = rt->gcIncrementalState;
         int64_t budget;
         if (type == ZealIncrementalMultipleSlices) {
-            // Start with a small slice limit and double it every slice. This ensure that we get
-            // multiple slices, and collection runs to completion.
-            if (rt->gcIncrementalState == NO_INCREMENTAL)
+            /*
+             * Start with a small slice limit and double it every slice. This
+             * ensure that we get multiple slices, and collection runs to
+             * completion.
+             */
+            if (initialState == NO_INCREMENTAL)
                 rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
             else
                 rt->gcIncrementalLimit *= 2;
             budget = SliceBudget::WorkBudget(rt->gcIncrementalLimit);
         } else {
-            // This triggers incremental GC but is actually ignored by IncrementalMarkSlice.
             budget = SliceBudget::Unlimited;
         }
+
         Collect(rt, true, budget, GC_NORMAL, gcreason::DEBUG_GC);
+
+        /*
+         * For multi-slice zeal, reset the slice size when we get to the sweep
+         * phase.
+         */
+        if (type == ZealIncrementalMultipleSlices &&
+            initialState == MARK && rt->gcIncrementalState == SWEEP)
+        {
+            rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
+        }
     } else {
         Collect(rt, false, SliceBudget::Unlimited, GC_NORMAL, gcreason::DEBUG_GC);
     }
 
 #endif
 }
 
 void
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -36,23 +36,25 @@ struct JSCompartment;
 #else
 # define JS_CHECK_STACK_SIZE(limit, lval)  ((uintptr_t)(lval) > limit)
 #endif
 
 namespace js {
 
 class GCHelperThread;
 struct Shape;
+struct SliceBudget;
 
 namespace gc {
 
 enum State {
     NO_INCREMENTAL,
     MARK_ROOTS,
     MARK,
+    SWEEP,
     INVALID
 };
 
 class ChunkPool {
     Chunk   *emptyChunkListHead;
     size_t  emptyCount;
 
   public:
@@ -141,42 +143,44 @@ IsNurseryAllocable(AllocKind kind)
         false      /* FINALIZE_EXTERNAL_STRING */
     };
     return map[kind];
 }
 
 inline JSGCTraceKind
 GetGCThingTraceKind(const void *thing);
 
-struct ArenaLists {
+/*
+ * ArenaList::head points to the start of the list. Normally cursor points
+ * to the first arena in the list with some free things and all arenas
+ * before cursor are fully allocated. However, as the arena currently being
+ * allocated from is considered full while its list of free spans is moved
+ * into the freeList, during the GC or cell enumeration, when an
+ * unallocated freeList is moved back to the arena, we can see an arena
+ * with some free cells before the cursor. The cursor is an indirect
+ * pointer to allow for efficient list insertion at the cursor point and
+ * other list manipulations.
+ */
+struct ArenaList {
+    ArenaHeader     *head;
+    ArenaHeader     **cursor;
 
-    /*
-     * ArenaList::head points to the start of the list. Normally cursor points
-     * to the first arena in the list with some free things and all arenas
-     * before cursor are fully allocated. However, as the arena currently being
-     * allocated from is considered full while its list of free spans is moved
-     * into the freeList, during the GC or cell enumeration, when an
-     * unallocated freeList is moved back to the arena, we can see an arena
-     * with some free cells before the cursor. The cursor is an indirect
-     * pointer to allow for efficient list insertion at the cursor point and
-     * other list manipulations.
-     */
-    struct ArenaList {
-        ArenaHeader     *head;
-        ArenaHeader     **cursor;
+    ArenaList() {
+        clear();
+    }
 
-        ArenaList() {
-            clear();
-        }
+    void clear() {
+        head = NULL;
+        cursor = &head;
+    }
 
-        void clear() {
-            head = NULL;
-            cursor = &head;
-        }
-    };
+    void insert(ArenaHeader *arena);
+};
+
+struct ArenaLists {
 
   private:
     /*
      * For each arena kind its free list is represented as the first span with
      * free things. Initially all the spans are initialized as empty. After we
      * find a new arena with available things we move its first free span into
      * the list and set the arena as fully allocated. way we do not need to
      * update the arena header after the initial allocation. When starting the
@@ -207,21 +211,27 @@ struct ArenaLists {
         BFS_DONE,
         BFS_RUN,
         BFS_JUST_FINISHED
     };
 
     volatile uintptr_t backgroundFinalizeState[FINALIZE_LIMIT];
 
   public:
+    /* For each arena kind, a list of arenas remaining to be swept. */
+    ArenaHeader *arenaListsToSweep[FINALIZE_LIMIT];
+
+  public:
     ArenaLists() {
         for (size_t i = 0; i != FINALIZE_LIMIT; ++i)
             freeLists[i].initAsEmpty();
         for (size_t i = 0; i != FINALIZE_LIMIT; ++i)
             backgroundFinalizeState[i] = BFS_DONE;
+        for (size_t i = 0; i != FINALIZE_LIMIT; ++i)
+            arenaListsToSweep[i] = NULL;
     }
 
     ~ArenaLists() {
         for (size_t i = 0; i != FINALIZE_LIMIT; ++i) {
             /*
              * We can only call this during the shutdown after the last GC when
              * the background finalization is disabled.
              */
@@ -251,16 +261,20 @@ struct ArenaLists {
             if (backgroundFinalizeState[i] != BFS_DONE)
                 return false;
             if (arenaLists[i].head)
                 return false;
         }
         return true;
     }
 
+    bool arenasAreFull(AllocKind thingKind) const {
+        return !*arenaLists[thingKind].cursor;
+    }
+
     void unmarkAll() {
         for (size_t i = 0; i != FINALIZE_LIMIT; ++i) {
             /* The background finalization must have stopped at this point. */
             JS_ASSERT(backgroundFinalizeState[i] == BFS_DONE ||
                       backgroundFinalizeState[i] == BFS_JUST_FINISHED);
             for (ArenaHeader *aheader = arenaLists[i].head; aheader; aheader = aheader->next) {
                 uintptr_t *word = aheader->chunk()->bitmap.arenaBits(aheader);
                 memset(word, 0, ArenaBitmapWords * sizeof(uintptr_t));
@@ -359,26 +373,28 @@ struct ArenaLists {
             JS_ASSERT(freeLists[i].isEmpty());
 #endif
     }
 
     void checkEmptyFreeList(AllocKind kind) {
         JS_ASSERT(freeLists[kind].isEmpty());
     }
 
-    void finalizeObjects(FreeOp *fop);
-    void finalizeStrings(FreeOp *fop);
-    void finalizeShapes(FreeOp *fop);
-    void finalizeScripts(FreeOp *fop);
+    void queueObjectsForSweep(FreeOp *fop);
+    void queueStringsForSweep(FreeOp *fop);
+    void queueShapesForSweep(FreeOp *fop);
+    void queueScriptsForSweep(FreeOp *fop);
 
+    bool foregroundFinalize(FreeOp *fop, AllocKind thingKind, SliceBudget &sliceBudget);
     static void backgroundFinalize(FreeOp *fop, ArenaHeader *listHead);
 
   private:
     inline void finalizeNow(FreeOp *fop, AllocKind thingKind);
-    inline void finalizeLater(FreeOp *fop, AllocKind thingKind);
+    inline void queueForForegroundSweep(FreeOp *fop, AllocKind thingKind);
+    inline void queueForBackgroundSweep(FreeOp *fop, AllocKind thingKind);
 
     inline void *allocateFromArena(JSCompartment *comp, AllocKind thingKind);
 };
 
 /*
  * Initial allocation size for data structures holding chunks is set to hold
  * chunks with total capacity of 16MB to avoid buffer resizes during browser
  * startup.
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -413,17 +413,17 @@ NewGCThing(JSContext *cx, js::gc::AllocK
 
     MaybeCheckStackRoots(cx, /* relax = */ false);
 
     JSCompartment *comp = cx->compartment;
     void *t = comp->arenas.allocateFromFreeList(kind, thingSize);
     if (!t)
         t = js::gc::ArenaLists::refillFreeList(cx, kind);
 
-    JS_ASSERT_IF(t && comp->needsBarrier(),
+    JS_ASSERT_IF(t && comp->wasGCStarted() && comp->needsBarrier(),
                  static_cast<T *>(t)->arenaHeader()->allocatedDuringIncremental);
 
 #if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)
     if (cx->runtime->gcVerifyPostData && IsNurseryAllocable(kind) && !IsAtomsCompartment(comp))
         comp->gcNursery.insertPointer(t);
 #endif
     return static_cast<T *>(t);
 }
@@ -440,17 +440,17 @@ TryNewGCThing(JSContext *cx, js::gc::All
     JS_ASSERT(!cx->runtime->noGCOrAllocationCheck);
 
 #ifdef JS_GC_ZEAL
     if (cx->runtime->needZealousGC())
         return NULL;
 #endif
 
     void *t = cx->compartment->arenas.allocateFromFreeList(kind, thingSize);
-    JS_ASSERT_IF(t && cx->compartment->needsBarrier(),
+    JS_ASSERT_IF(t && cx->compartment->wasGCStarted() && cx->compartment->needsBarrier(),
                  static_cast<T *>(t)->arenaHeader()->allocatedDuringIncremental);
 
 #if defined(JSGC_GENERATIONAL) && defined(JS_GC_ZEAL)
     JSCompartment *comp = cx->compartment;
     if (cx->runtime->gcVerifyPostData && IsNurseryAllocable(kind) && !IsAtomsCompartment(comp))
         comp->gcNursery.insertPointer(t);
 #endif
     return static_cast<T *>(t);
--- a/js/src/jspropertytree.cpp
+++ b/js/src/jspropertytree.cpp
@@ -97,85 +97,97 @@ PropertyTree::insertChild(JSContext *cx,
     child->setParent(parent);
     return true;
 }
 
 void
 Shape::removeChild(Shape *child)
 {
     JS_ASSERT(!child->inDictionary());
+    JS_ASSERT(child->parent == this);
 
     KidsPointer *kidp = &kids;
 
     if (kidp->isShape()) {
         JS_ASSERT(kidp->toShape() == child);
         kidp->setNull();
+        child->parent = NULL;
         return;
     }
 
     KidsHash *hash = kidp->toHash();
     JS_ASSERT(hash->count() >= 2);      /* otherwise kidp->isShape() should be true */
 
     hash->remove(child);
+    child->parent = NULL;
 
     if (hash->count() == 1) {
         /* Convert from HASH form back to SHAPE form. */
         KidsHash::Range r = hash->all();
         Shape *otherChild = r.front();
         JS_ASSERT((r.popFront(), r.empty()));    /* No more elements! */
         kidp->setShape(otherChild);
         js::UnwantedForeground::delete_(hash);
     }
 }
 
-/*
- * We need a read barrier for the shape tree, since these are weak pointers.
- */
-static Shape *
-ReadBarrier(Shape *shape)
-{
-#ifdef JSGC_INCREMENTAL
-    JSCompartment *comp = shape->compartment();
-    if (comp->needsBarrier()) {
-        Shape *tmp = shape;
-        MarkShapeUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
-        JS_ASSERT(tmp == shape);
-    }
-#endif
-    return shape;
-}
-
 Shape *
 PropertyTree::getChild(JSContext *cx, Shape *parent_, uint32_t nfixed, const StackShape &child)
 {
-    Shape *shape;
+    Shape *shape = NULL;
 
     JS_ASSERT(parent_);
 
     /*
      * The property tree has extremely low fan-out below its root in
      * popular embeddings with real-world workloads. Patterns such as
      * defining closures that capture a constructor's environment as
      * getters or setters on the new object that is passed in as
      * |this| can significantly increase fan-out below the property
      * tree root -- see bug 335700 for details.
      */
     KidsPointer *kidp = &parent_->kids;
     if (kidp->isShape()) {
-        shape = kidp->toShape();
-        if (shape->matches(child))
-            return ReadBarrier(shape);
+        Shape *kid = kidp->toShape();
+        if (kid->matches(child))
+            shape = kid;
     } else if (kidp->isHash()) {
         shape = *kidp->toHash()->lookup(child);
-        if (shape)
-            return ReadBarrier(shape);
     } else {
         /* If kidp->isNull(), we always insert. */
     }
 
+#ifdef JSGC_INCREMENTAL
+    if (shape) {
+        JSCompartment *comp = shape->compartment();
+        if (comp->needsBarrier()) {
+            /*
+             * We need a read barrier for the shape tree, since these are weak
+             * pointers.
+             */
+            Shape *tmp = shape;
+            MarkShapeUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
+            JS_ASSERT(tmp == shape);
+        } else if (comp->isGCSweeping() && !shape->isMarked() &&
+                   !shape->arenaHeader()->allocatedDuringIncremental)
+        {
+            /*
+             * The shape we've found is unreachable and due to be finalized, so
+             * remove our weak reference to it and don't use it.
+             */
+            JS_ASSERT(parent_->isMarked());
+            parent_->removeChild(shape);
+            shape = NULL;
+        }
+    }
+#endif
+
+    if (shape)
+        return shape;
+
     StackShape::AutoRooter childRoot(cx, &child);
     RootedShape parent(cx, parent_);
 
     shape = newShape(cx);
     if (!shape)
         return NULL;
 
     new (shape) Shape(child, nfixed);
@@ -185,16 +197,21 @@ PropertyTree::getChild(JSContext *cx, Sh
 
     return shape;
 }
 
 void
 Shape::finalize(FreeOp *fop)
 {
     if (!inDictionary()) {
+        /*
+         * Note that due to incremental sweeping, if !parent->isMarked() then
+         * the parent may point to a new shape allocated in the same cell that
+         * use to hold our parent.
+         */
         if (parent && parent->isMarked())
             parent->removeChild(this);
 
         if (kids.isHash())
             fop->delete_(kids.toHash());
     }
 }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1196,17 +1196,17 @@ ScriptSource::createFromSource(JSContext
 #endif
 
 #ifdef JSGC_INCREMENTAL
     /*
      * During the IGC we need to ensure that source is marked whenever it is
      * accessed even if the name was already in the table. At this point old
      * scripts pointing to the source may no longer be reachable.
      */
-    if (cx->runtime->gcIncrementalState == MARK && cx->runtime->gcIsFull)
+    if (cx->runtime->gcIncrementalState != NO_INCREMENTAL && cx->runtime->gcIsFull)
         ss->marked = true;
 #endif
 
     JS_ASSERT_IF(ownSource, !tok);
 
 #ifdef JS_THREADSAFE
     if (tok && 0) {
         tok->ss = ss;
@@ -1336,17 +1336,17 @@ ScriptSource::performXDR(XDRState<mode> 
         ss->marked = ss->onRuntime_ = ss->argumentsNotIncluded_ = false;
 #ifdef DEBUG
         ss->ready_ = false;
 #endif
         ss->data.compressed = NULL;
         cleanup.protect(ss);
 #ifdef JSGC_INCREMENTAL
         // See comment in ScriptSource::createFromSource.
-        if (xdr->cx()->runtime->gcIncrementalState == MARK &&
+        if (xdr->cx()->runtime->gcIncrementalState != NO_INCREMENTAL &&
             xdr->cx()->runtime->gcIsFull)
             ss->marked = true;
 #endif
     }
     if (!xdr->codeUint32(&ss->length_))
         return false;
     if (!xdr->codeUint32(&ss->compressedLength))
         return false;
@@ -1404,17 +1404,17 @@ js::SaveScriptFilename(JSContext *cx, co
     ScriptFilenameEntry *sfe = *p;
 #ifdef JSGC_INCREMENTAL
     /*
      * During the IGC we need to ensure that filename is marked whenever it is
      * accessed even if the name was already in the table. At this point old
      * scripts or exceptions pointing to the filename may no longer be
      * reachable.
      */
-    if (rt->gcIncrementalState == MARK && rt->gcIsFull)
+    if (rt->gcIncrementalState != NO_INCREMENTAL && rt->gcIsFull)
         sfe->marked = true;
 #endif
 
     return sfe->filename;
 }
 
 void
 js::SweepScriptFilenames(JSRuntime *rt)
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2083,17 +2083,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
   const nsStyleDisplay* disp = child->GetStyleDisplay();
   bool isVisuallyAtomic = disp->mOpacity != 1.0f
     || child->IsTransformed()
     || nsSVGIntegrationUtils::UsingEffectsForFrame(child);
 
   bool isPositioned = !isSVG && disp->IsPositioned();
   if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating()) ||
       ((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
-       IsSVGContentWithCSSClip(this)) ||
+       IsSVGContentWithCSSClip(child)) ||
       (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
     // If you change this, also change IsPseudoStackingContextFromStyle()
     pseudoStackingContext = true;
   }
 
   // This controls later whether we build an nsDisplayWrapList or an
   // nsDisplayFixedPosition. We check if we're already building a fixed-pos
   // item and disallow nesting, to prevent the situation of bug #769541
--- a/layout/style/nsStyleTransformMatrix.cpp
+++ b/layout/style/nsStyleTransformMatrix.cpp
@@ -34,58 +34,50 @@ namespace nsStyleTransformMatrix {
 static double FlushToZero(double aVal)
 {
   if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON)
     return 0.0f;
   else
     return aVal;
 }
 
-/* Helper function to fill in an nscoord with the specified nsCSSValue. */
-static nscoord CalcLength(const nsCSSValue &aValue,
-                          nsStyleContext* aContext,
-                          nsPresContext* aPresContext,
-                          bool &aCanStoreInRuleTree)
-{
-  if (aValue.GetUnit() == eCSSUnit_Pixel ||
-      aValue.GetUnit() == eCSSUnit_Number) {
-    // Handle this here (even though nsRuleNode::CalcLength handles it
-    // fine) so that callers are allowed to pass a null style context
-    // and pres context to SetToTransformFunction if they know (as
-    // nsStyleAnimation does) that all lengths within the transform
-    // function have already been computed to pixels and percents.
-    //
-    // Raw numbers are treated as being pixels.
-    return nsPresContext::CSSPixelsToAppUnits(aValue.GetFloatValue());
-  }
-  return nsRuleNode::CalcLength(aValue, aContext, aPresContext,
-                                aCanStoreInRuleTree);
-}
-
 static float
 ProcessTranslatePart(const nsCSSValue& aValue,
                      nsStyleContext* aContext,
                      nsPresContext* aPresContext,
                      bool& aCanStoreInRuleTree,
                      nscoord aSize, float aAppUnitsPerMatrixUnit)
 {
   nscoord offset = 0;
   float percent = 0.0f;
 
   if (aValue.GetUnit() == eCSSUnit_Percent) {
     percent = aValue.GetPercentValue();
+  } else if (aValue.GetUnit() == eCSSUnit_Pixel ||
+             aValue.GetUnit() == eCSSUnit_Number) {
+    // Handle this here (even though nsRuleNode::CalcLength handles it
+    // fine) so that callers are allowed to pass a null style context
+    // and pres context to SetToTransformFunction if they know (as
+    // nsStyleAnimation does) that all lengths within the transform
+    // function have already been computed to pixels and percents.
+    //
+    // Raw numbers are treated as being pixels.
+    //
+    // Don't convert to aValue to AppUnits here to avoid precision issues.
+    return aValue.GetFloatValue() *
+           (float(nsPresContext::AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit);
   } else if (aValue.IsCalcUnit()) {
     nsRuleNode::ComputedCalc result =
       nsRuleNode::SpecifiedCalcToComputedCalc(aValue, aContext, aPresContext,
                                               aCanStoreInRuleTree);
     percent = result.mPercent;
     offset = result.mLength;
   } else {
-    offset = CalcLength(aValue, aContext, aPresContext,
-                         aCanStoreInRuleTree);
+    offset = nsRuleNode::CalcLength(aValue, aContext, aPresContext,
+                                    aCanStoreInRuleTree);
   }
 
   return (percent * NSAppUnitsToFloatPixels(aSize, aAppUnitsPerMatrixUnit)) + 
          NSAppUnitsToFloatPixels(offset, aAppUnitsPerMatrixUnit);
 }
 
 /**
  * Helper functions to process all the transformation function types.
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -680,8 +680,11 @@ pref("dom.min_background_timeout_value",
 // The default of font size in reader (1-7)
 pref("reader.font_size", 4);
 
 // The default of margin size in reader (5%-25%)
 pref("reader.margin_size", 5);
 
 // The default color scheme in reader (light, dark, sepia)
 pref("reader.color_scheme", "light");
+
+// Used to show a first-launch tip in reader
+pref("reader.has_used_toolbar", false);
\ No newline at end of file
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -11,20 +11,16 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/ipc/app/defs.mk
 
 DIRS = locales
 
 DIST_FILES = package-name.txt
 
 include $(topsrcdir)/mobile/android/base/android-sync-files.mk
 
-#These SYNC_ variables could be moved to android-sync/fennec-copy-code.sh
-SYNC_RES_XML=res/xml/sync_authenticator.xml
-SYNC_PP_RES_XML=res/xml/sync_syncadapter.xml res/xml/sync_options.xml
-
 FENNEC_JAVA_FILES = \
   AboutHomeContent.java \
   AboutHomeSection.java \
   ActivityHandlerHelper.java \
   ActivityResultHandler.java \
   ActivityResultHandlerMap.java \
   AndroidImport.java \
   AndroidImportPreference.java \
@@ -236,36 +232,49 @@ GARBAGE += \
   $(FENNEC_PP_XML_FILES) \
   $(SYNC_PP_RES_XML) \
   package-name.txt \
   Manifest.java \
   $(NULL)
 
 GARBAGE_DIRS += classes res sync db
 
+MOZ_ANDROID_SHARED_ID = "$(ANDROID_PACKAGE_NAME).sharedID"
+MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "$(ANDROID_PACKAGE_NAME)_sync"
+
 # Bug 567884 - Need a way to find appropriate icons during packaging
 ifeq ($(MOZ_APP_NAME),fennec)
 ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_48x48.png
 ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_72x72.png
 
 # we released these builds to the public with shared IDs and need to keep them
 ifeq (org.mozilla.firefox,$(ANDROID_PACKAGE_NAME))
-DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.firefox.sharedID"
+MOZ_ANDROID_SHARED_ID = "org.mozilla.firefox.sharedID"
+MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "org.mozilla.firefox_sync"
 else ifeq (org.mozilla.firefox_beta,$(ANDROID_PACKAGE_NAME))
-DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.firefox.sharedID"
+MOZ_ANDROID_SHARED_ID = "org.mozilla.firefox.sharedID"
+MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "org.mozilla.firefox_sync"
 else ifeq (org.mozilla.fennec_aurora,$(ANDROID_PACKAGE_NAME))
-DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.fennec.sharedID"
+MOZ_ANDROID_SHARED_ID = "org.mozilla.fennec.sharedID"
+MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "org.mozilla.fennec_sync"
 else ifeq (org.mozilla.fennec,$(ANDROID_PACKAGE_NAME))
-DEFINES += -DMOZ_ANDROID_SHARED_ID="org.mozilla.fennec.sharedID"
+MOZ_ANDROID_SHARED_ID = "org.mozilla.fennec.sharedID"
+MOZ_ANDROID_SHARED_ACCOUNT_TYPE = "org.mozilla.fennec_sync"
 endif
 
 else
 ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon48.png
 ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
-DEFINES += -DMOZ_ANDROID_SHARED_ID="$(ANDROID_PACKAGE_NAME).sharedID"
+endif
+
+ifdef MOZ_ANDROID_SHARED_ID
+DEFINES += -DMOZ_ANDROID_SHARED_ID="$(MOZ_ANDROID_SHARED_ID)"
+endif
+ifdef MOZ_ANDROID_SHARED_ACCOUNT_TYPE
+DEFINES += -DMOZ_ANDROID_SHARED_ACCOUNT_TYPE="$(MOZ_ANDROID_SHARED_ACCOUNT_TYPE)"
 endif
 
 RES_LAYOUT = \
   $(SYNC_RES_LAYOUT) \
   res/layout/autocomplete_list.xml \
   res/layout/autocomplete_list_item.xml \
   res/layout/awesomebar.xml \
   res/layout/awesomebar_actionbar.xml \
@@ -1084,17 +1093,17 @@ res/values/defaults.xml: $(topsrcdir)/$(
 	$(RM) -r $@
 	$(NSINSTALL) -D $@
 
 $(RESOURCES): $(RES_DIRS) $(subst res/,$(srcdir)/resources/,$(RESOURCES))
 	@echo "creating $@"
 	$(NSINSTALL) $(subst res/,$(srcdir)/resources/,$@) $(dir $@)
 
 
-R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/drawable/sync_ic_launcher.png res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
+R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/drawable/icon.png res/drawable-hdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
 
-gecko.ap_: AndroidManifest.xml res/drawable/sync_ic_launcher.png res/drawable/icon.png res/drawable-hdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/values/strings.xml FORCE
+gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(RES_DRAWABLE_LDPI) $(RES_DRAWABLE_MDPI) $(RES_DRAWABLE_HDPI) $(PP_RES_XML) res/values/defaults.xml res/values/strings.xml FORCE
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar  -S res -F $@
 
 libs:: classes.dex package-name.txt
 	$(INSTALL) classes.dex $(FINAL_TARGET)
 	$(INSTALL) package-name.txt $(FINAL_TARGET)
--- a/mobile/android/base/SyncPreference.java
+++ b/mobile/android/base/SyncPreference.java
@@ -18,19 +18,16 @@ class SyncPreference extends Preference 
 
     public SyncPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
     }
 
     @Override
     protected void onClick() {
-        // Make sure we use the same account type as our bundled version of Sync!
-        final String accountType = org.mozilla.gecko.sync.setup.Constants.ACCOUNTTYPE_SYNC;
-
         // Show Sync setup if no accounts exist; otherwise, show account settings.
         if (SyncAccounts.syncAccountsExist(mContext)) {
             SyncAccounts.openSyncSettings(mContext);
         } else {
             Intent intent = new Intent(mContext, SetupSyncActivity.class);
             mContext.startActivity(intent);
         }
     }
--- a/mobile/android/base/TextSelection.java
+++ b/mobile/android/base/TextSelection.java
@@ -1,24 +1,31 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import android.util.Log;
 import android.view.View;
+import org.mozilla.gecko.gfx.Layer;
+import org.mozilla.gecko.gfx.Layer.RenderContext;
+import org.mozilla.gecko.gfx.LayerController;
 import org.json.JSONObject;
 
-class TextSelection implements GeckoEventListener {
+class TextSelection extends Layer implements GeckoEventListener {
     private static final String LOGTAG = "GeckoTextSelection";
 
     private final TextSelectionHandle mStartHandle;
     private final TextSelectionHandle mEndHandle;
 
+    private float mViewLeft;
+    private float mViewTop;
+    private float mViewZoom;
+
     TextSelection(TextSelectionHandle startHandle, TextSelectionHandle endHandle) {
         mStartHandle = startHandle;
         mEndHandle = endHandle;
 
         // Only register listeners if we have valid start/end handles
         if (mStartHandle == null || mEndHandle == null) {
             Log.e(LOGTAG, "Failed to initialize text selection because at least one handle is null");
         } else {
@@ -36,21 +43,34 @@ class TextSelection implements GeckoEven
 
     public void handleMessage(String event, JSONObject message) {
         try {
             if (event.equals("TextSelection:ShowHandles")) {
                 GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
                     public void run() {
                         mStartHandle.setVisibility(View.VISIBLE);
                         mEndHandle.setVisibility(View.VISIBLE);
+
+                        mViewLeft = 0.0f;
+                        mViewTop = 0.0f;
+                        mViewZoom = 0.0f;
+                        LayerController layerController = GeckoApp.mAppContext.getLayerController();
+                        if (layerController != null) {
+                            layerController.getView().addLayer(TextSelection.this);
+                        }
                     }
                 });
             } else if (event.equals("TextSelection:HideHandles")) {
                 GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
                     public void run() {
+                        LayerController layerController = GeckoApp.mAppContext.getLayerController();
+                        if (layerController != null) {
+                            layerController.getView().removeLayer(TextSelection.this);
+                        }
+
                         mStartHandle.setVisibility(View.GONE);
                         mEndHandle.setVisibility(View.GONE);
                     }
                 });
             } else if (event.equals("TextSelection:PositionHandles")) {
                 final int startLeft = message.getInt("startLeft");
                 final int startTop = message.getInt("startTop");
                 final int endLeft = message.getInt("endLeft");
@@ -62,9 +82,31 @@ class TextSelection implements GeckoEven
                         mEndHandle.positionFromGecko(endLeft, endTop);
                     }
                 });
             }
         } catch (Exception e) {
             Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
         }
     }
+
+    @Override
+    public void draw(final RenderContext context) {
+        // cache the relevant values from the context and bail out if they are the same. we do this
+        // because this draw function gets called a lot (once per compositor frame) and we want to
+        // avoid doing a lot of extra work in cases where it's not needed.
+        if (FloatUtils.fuzzyEquals(mViewLeft, context.viewport.left)
+                && FloatUtils.fuzzyEquals(mViewTop, context.viewport.top)
+                && FloatUtils.fuzzyEquals(mViewZoom, context.zoomFactor)) {
+            return;
+        }
+        mViewLeft = context.viewport.left;
+        mViewTop = context.viewport.top;
+        mViewZoom = context.zoomFactor;
+
+        GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
+            public void run() {
+                mStartHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
+                mEndHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
+            }
+        });
+    }
 }
--- a/mobile/android/base/TextSelectionHandle.java
+++ b/mobile/android/base/TextSelectionHandle.java
@@ -8,31 +8,33 @@ import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.PointF;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.RelativeLayout;
 import android.widget.ImageView;
+import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
 import org.mozilla.gecko.gfx.LayerController;
 import org.json.JSONObject;
 
 class TextSelectionHandle extends ImageView implements View.OnTouchListener {
     private static final String LOGTAG = "GeckoTextSelectionHandle";
 
     private enum HandleType { START, END }; 
 
     private final HandleType mHandleType;
     private final int mWidth;
     private final int mHeight;
     private final int mShadow;
 
     private int mLeft;
     private int mTop;
+    private PointF mGeckoPoint;
     private int mTouchStartX;
     private int mTouchStartY;
 
     private RelativeLayout.LayoutParams mLayoutParams;
 
     TextSelectionHandle(Context context, AttributeSet attrs) {
         super(context, attrs);
         setOnTouchListener(this);
@@ -103,21 +105,28 @@ class TextSelectionHandle extends ImageV
     }
 
     void positionFromGecko(int left, int top) {
         LayerController layerController = GeckoApp.mAppContext.getLayerController();
         if (layerController == null) {
             Log.e(LOGTAG, "Can't position handle because layerController is null");
             return;
         }
-        PointF geckoPoint = new PointF((float) left, (float) top);
-        geckoPoint = layerController.convertLayerPointToViewPoint(geckoPoint);
+
+        mGeckoPoint = new PointF((float) left, (float) top);
+        ImmutableViewportMetrics metrics = layerController.getViewportMetrics();
+        repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
+    }
 
-        mLeft = Math.round(geckoPoint.x) - (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
-        mTop = Math.round(geckoPoint.y);
+    void repositionWithViewport(float x, float y, float zoom) {
+        PointF viewPoint = new PointF((mGeckoPoint.x * zoom) - x,
+                                      (mGeckoPoint.y * zoom) - y);
+
+        mLeft = Math.round(viewPoint.x) - (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
+        mTop = Math.round(viewPoint.y);
 
         setLayoutPosition();
     }
 
     private void setLayoutPosition() {
         if (mLayoutParams == null) {
             mLayoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
             // Set negative right/bottom margins so that the handles can be dragged outside of
--- a/mobile/android/base/android-sync-files.mk
+++ b/mobile/android/base/android-sync-files.mk
@@ -1,14 +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/.
 
 # These files are managed in the android-sync repo. Do not modify directly, or your changes will be lost.
 SYNC_JAVA_FILES := sync/AlreadySyncingException.java sync/CollectionKeys.java sync/CommandProcessor.java sync/CommandRunner.java sync/config/AccountPickler.java sync/CredentialsSource.java sync/crypto/CryptoException.java sync/crypto/CryptoInfo.java sync/crypto/HKDF.java sync/crypto/HMACVerificationException.java sync/crypto/KeyBundle.java sync/crypto/MissingCryptoInputException.java sync/crypto/NoKeyBundleException.java sync/crypto/PersistedCrypto5Keys.java sync/CryptoRecord.java sync/DelayedWorkTracker.java sync/delegates/ClientsDataDelegate.java sync/delegates/FreshStartDelegate.java sync/delegates/GlobalSessionCallback.java sync/delegates/InfoCollectionsDelegate.java sync/delegates/KeyUploadDelegate.java sync/delegates/MetaGlobalDelegate.java sync/delegates/WipeServerDelegate.java sync/EngineSettings.java sync/ExtendedJSONObject.java sync/GlobalSession.java sync/HTTPFailureException.java sync/InfoCollections.java sync/jpake/BigIntegerHelper.java sync/jpake/Gx3OrGx4IsZeroOrOneException.java sync/jpake/IncorrectZkpException.java sync/jpake/JPakeClient.java sync/jpake/JPakeCrypto.java sync/jpake/JPakeJson.java sync/jpake/JPakeNoActivePairingException.java sync/jpake/JPakeNumGenerator.java sync/jpake/JPakeNumGeneratorRandom.java sync/jpake/JPakeParty.java sync/jpake/JPakeRequest.java sync/jpake/JPakeRequestDelegate.java sync/jpake/JPakeResponse.java sync/jpake/stage/CompleteStage.java sync/jpake/stage/ComputeFinalStage.java sync/jpake/stage/ComputeKeyVerificationStage.java sync/jpake/stage/ComputeStepOneStage.java sync/jpake/stage/ComputeStepTwoStage.java sync/jpake/stage/DecryptDataStage.java sync/jpake/stage/DeleteChannel.java sync/jpake/stage/GetChannelStage.java sync/jpake/stage/GetRequestStage.java sync/jpake/stage/JPakeStage.java sync/jpake/stage/PutRequestStage.java sync/jpake/stage/VerifyPairingStage.java sync/jpake/Zkp.java sync/KeyBundleProvider.java sync/log/writers/AndroidLevelCachingLogWriter.java sync/log/writers/AndroidLogWriter.java sync/log/writers/LevelFilteringLogWriter.java sync/log/writers/LogWriter.java sync/log/writers/PrintLogWriter.java sync/log/writers/SingleTagLogWriter.java sync/log/writers/StringLogWriter.java sync/Logger.java sync/MetaGlobal.java sync/MetaGlobalException.java sync/MetaGlobalMissingEnginesException.java sync/MetaGlobalNotSetException.java sync/middleware/Crypto5MiddlewareRepository.java sync/middleware/Crypto5MiddlewareRepositorySession.java sync/middleware/MiddlewareRepository.java sync/middleware/MiddlewareRepositorySession.java sync/net/BaseResource.java sync/net/ConnectionMonitorThread.java sync/net/HandleProgressException.java sync/net/HttpResponseObserver.java sync/net/Resource.java sync/net/ResourceDelegate.java sync/net/SyncResourceDelegate.java sync/net/SyncResponse.java sync/net/SyncStorageCollectionRequest.java sync/net/SyncStorageCollectionRequestDelegate.java sync/net/SyncStorageRecordRequest.java sync/net/SyncStorageRequest.java sync/net/SyncStorageRequestDelegate.java sync/net/SyncStorageRequestIncrementalDelegate.java sync/net/SyncStorageResponse.java sync/net/TLSSocketFactory.java sync/net/WBOCollectionRequestDelegate.java sync/net/WBORequestDelegate.java sync/NoCollectionKeysSetException.java sync/NodeAuthenticationException.java sync/NonArrayJSONException.java sync/NonObjectJSONException.java sync/NullClusterURLException.java sync/PersistedMetaGlobal.java sync/PrefsSource.java sync/receivers/UpgradeReceiver.java sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java sync/repositories/android/AndroidBrowserBookmarksRepository.java sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java sync/repositories/android/AndroidBrowserHistoryDataAccessor.java sync/repositories/android/AndroidBrowserHistoryDataExtender.java sync/repositories/android/AndroidBrowserHistoryRepository.java sync/repositories/android/AndroidBrowserHistoryRepositorySession.java sync/repositories/android/AndroidBrowserRepository.java sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java sync/repositories/android/AndroidBrowserRepositorySession.java sync/repositories/android/BookmarksDeletionManager.java sync/repositories/android/BookmarksInsertionManager.java sync/repositories/android/BrowserContractHelpers.java sync/repositories/android/CachedSQLiteOpenHelper.java sync/repositories/android/ClientsDatabase.java sync/repositories/android/ClientsDatabaseAccessor.java sync/repositories/android/FennecControlHelper.java sync/repositories/android/FennecTabsRepository.java sync/repositories/android/FormHistoryRepositorySession.java sync/repositories/android/PasswordsRepositorySession.java sync/repositories/android/RepoUtils.java sync/repositories/BookmarkNeedsReparentingException.java sync/repositories/BookmarksRepository.java sync/repositories/ConstrainedServer11Repository.java sync/repositories/delegates/DeferrableRepositorySessionCreationDelegate.java sync/repositories/delegates/DeferredRepositorySessionBeginDelegate.java sync/repositories/delegates/DeferredRepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/DeferredRepositorySessionFinishDelegate.java sync/repositories/delegates/DeferredRepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionBeginDelegate.java sync/repositories/delegates/RepositorySessionCleanDelegate.java sync/repositories/delegates/RepositorySessionCreationDelegate.java sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java sync/repositories/delegates/RepositorySessionFinishDelegate.java sync/repositories/delegates/RepositorySessionGuidsSinceDelegate.java sync/repositories/delegates/RepositorySessionStoreDelegate.java sync/repositories/delegates/RepositorySessionWipeDelegate.java sync/repositories/domain/BookmarkRecord.java sync/repositories/domain/BookmarkRecordFactory.java sync/repositories/domain/ClientRecord.java sync/repositories/domain/ClientRecordFactory.java sync/repositories/domain/FormHistoryRecord.java sync/repositories/domain/HistoryRecord.java sync/repositories/domain/HistoryRecordFactory.java sync/repositories/domain/PasswordRecord.java sync/repositories/domain/Record.java sync/repositories/domain/TabsRecord.java sync/repositories/domain/VersionConstants.java sync/repositories/FetchFailedException.java sync/repositories/HashSetStoreTracker.java sync/repositories/HistoryRepository.java sync/repositories/IdentityRecordFactory.java sync/repositories/InactiveSessionException.java sync/repositories/InvalidBookmarkTypeException.java sync/repositories/InvalidRequestException.java sync/repositories/InvalidSessionTransitionException.java sync/repositories/MultipleRecordsForGuidException.java sync/repositories/NoContentProviderException.java sync/repositories/NoGuidForIdException.java sync/repositories/NoStoreDelegateException.java sync/repositories/NullCursorException.java sync/repositories/ParentNotFoundException.java sync/repositories/ProfileDatabaseException.java sync/repositories/RecordFactory.java sync/repositories/RecordFilter.java sync/repositories/Repository.java sync/repositories/RepositorySession.java sync/repositories/RepositorySessionBundle.java sync/repositories/Server11Repository.java sync/repositories/Server11RepositorySession.java sync/repositories/StoreFailedException.java sync/repositories/StoreTracker.java sync/repositories/StoreTrackingRepositorySession.java sync/Server11PreviousPostFailedException.java sync/Server11RecordPostFailedException.java sync/setup/activities/AccountActivity.java sync/setup/activities/ActivityUtils.java sync/setup/activities/ClientRecordArrayAdapter.java sync/setup/activities/RedirectToSetupActivity.java sync/setup/activities/SendTabActivity.java sync/setup/activities/SetupFailureActivity.java sync/setup/activities/SetupSuccessActivity.java sync/setup/activities/SetupSyncActivity.java sync/setup/auth/AccountAuthenticator.java sync/setup/auth/AuthenticateAccountStage.java sync/setup/auth/AuthenticationResult.java sync/setup/auth/AuthenticatorStage.java sync/setup/auth/EnsureUserExistenceStage.java sync/setup/auth/FetchUserNodeStage.java sync/setup/Constants.java sync/setup/InvalidSyncKeyException.java sync/setup/SyncAccounts.java sync/setup/SyncAuthenticatorService.java sync/stage/AbstractNonRepositorySyncStage.java sync/stage/AndroidBrowserBookmarksServerSyncStage.java sync/stage/AndroidBrowserHistoryServerSyncStage.java sync/stage/CheckPreconditionsStage.java sync/stage/CompletedStage.java sync/stage/EnsureClusterURLStage.java sync/stage/EnsureCrypto5KeysStage.java sync/stage/FennecTabsServerSyncStage.java sync/stage/FetchInfoCollectionsStage.java sync/stage/FetchMetaGlobalStage.java sync/stage/FormHistoryServerSyncStage.java sync/stage/GlobalSyncStage.java sync/stage/NoSuchStageException.java sync/stage/NoSyncIDException.java sync/stage/PasswordsServerSyncStage.java sync/stage/ServerSyncStage.java sync/stage/SyncClientsEngineStage.java sync/stage/UploadMetaGlobalStage.java sync/StubActivity.java sync/syncadapter/SyncAdapter.java sync/syncadapter/SyncService.java sync/SyncConfiguration.java sync/SyncConfigurationException.java sync/SyncException.java sync/synchronizer/ConcurrentRecordConsumer.java sync/synchronizer/RecordConsumer.java sync/synchronizer/RecordsChannel.java sync/synchronizer/RecordsChannelDelegate.java sync/synchronizer/RecordsConsumerDelegate.java sync/synchronizer/SerialRecordConsumer.java sync/synchronizer/ServerLocalSynchronizer.java sync/synchronizer/ServerLocalSynchronizerSession.java sync/synchronizer/SessionNotBegunException.java sync/synchronizer/Synchronizer.java sync/synchronizer/SynchronizerDelegate.java sync/synchronizer/SynchronizerSession.java sync/synchronizer/SynchronizerSessionDelegate.java sync/synchronizer/UnbundleError.java sync/synchronizer/UnexpectedSessionException.java sync/SynchronizerConfiguration.java sync/ThreadPool.java sync/UnexpectedJSONException.java sync/UnknownSynchronizerConfigurationVersionException.java sync/Utils.java
 SYNC_PP_JAVA_FILES := sync/GlobalConstants.java
 SYNC_THIRDPARTY_JAVA_FILES := httpclientandroidlib/androidextra/HttpClientAndroidLog.java httpclientandroidlib/annotation/GuardedBy.java httpclientandroidlib/annotation/Immutable.java httpclientandroidlib/annotation/NotThreadSafe.java httpclientandroidlib/annotation/ThreadSafe.java httpclientandroidlib/auth/AUTH.java httpclientandroidlib/auth/AuthenticationException.java httpclientandroidlib/auth/AuthScheme.java httpclientandroidlib/auth/AuthSchemeFactory.java httpclientandroidlib/auth/AuthSchemeRegistry.java httpclientandroidlib/auth/AuthScope.java httpclientandroidlib/auth/AuthState.java httpclientandroidlib/auth/BasicUserPrincipal.java httpclientandroidlib/auth/ContextAwareAuthScheme.java httpclientandroidlib/auth/Credentials.java httpclientandroidlib/auth/InvalidCredentialsException.java httpclientandroidlib/auth/MalformedChallengeException.java httpclientandroidlib/auth/NTCredentials.java httpclientandroidlib/auth/NTUserPrincipal.java httpclientandroidlib/auth/params/AuthParamBean.java httpclientandroidlib/auth/params/AuthParams.java httpclientandroidlib/auth/params/AuthPNames.java httpclientandroidlib/auth/UsernamePasswordCredentials.java httpclientandroidlib/client/AuthCache.java httpclientandroidlib/client/AuthenticationHandler.java httpclientandroidlib/client/CircularRedirectException.java httpclientandroidlib/client/ClientProtocolException.java httpclientandroidlib/client/CookieStore.java httpclientandroidlib/client/CredentialsProvider.java httpclientandroidlib/client/entity/DecompressingEntity.java httpclientandroidlib/client/entity/DeflateDecompressingEntity.java httpclientandroidlib/client/entity/GzipDecompressingEntity.java httpclientandroidlib/client/entity/UrlEncodedFormEntity.java httpclientandroidlib/client/HttpClient.java httpclientandroidlib/client/HttpRequestRetryHandler.java httpclientandroidlib/client/HttpResponseException.java httpclientandroidlib/client/methods/AbortableHttpRequest.java httpclientandroidlib/client/methods/HttpDelete.java httpclientandroidlib/client/methods/HttpEntityEnclosingRequestBase.java httpclientandroidlib/client/methods/HttpGet.java httpclientandroidlib/client/methods/HttpHead.java httpclientandroidlib/client/methods/HttpOptions.java httpclientandroidlib/client/methods/HttpPost.java httpclientandroidlib/client/methods/HttpPut.java httpclientandroidlib/client/methods/HttpRequestBase.java httpclientandroidlib/client/methods/HttpTrace.java httpclientandroidlib/client/methods/HttpUriRequest.java httpclientandroidlib/client/NonRepeatableRequestException.java httpclientandroidlib/client/params/AllClientPNames.java httpclientandroidlib/client/params/AuthPolicy.java httpclientandroidlib/client/params/ClientParamBean.java httpclientandroidlib/client/params/ClientPNames.java httpclientandroidlib/client/params/CookiePolicy.java httpclientandroidlib/client/params/HttpClientParams.java httpclientandroidlib/client/protocol/ClientContext.java httpclientandroidlib/client/protocol/ClientContextConfigurer.java httpclientandroidlib/client/protocol/RequestAcceptEncoding.java httpclientandroidlib/client/protocol/RequestAddCookies.java httpclientandroidlib/client/protocol/RequestAuthCache.java httpclientandroidlib/client/protocol/RequestClientConnControl.java httpclientandroidlib/client/protocol/RequestDefaultHeaders.java httpclientandroidlib/client/protocol/RequestProxyAuthentication.java httpclientandroidlib/client/protocol/RequestTargetAuthentication.java httpclientandroidlib/client/protocol/ResponseAuthCache.java httpclientandroidlib/client/protocol/ResponseContentEncoding.java httpclientandroidlib/client/protocol/ResponseProcessCookies.java httpclientandroidlib/client/RedirectException.java httpclientandroidlib/client/RedirectHandler.java httpclientandroidlib/client/RedirectStrategy.java httpclientandroidlib/client/RequestDirector.java httpclientandroidlib/client/ResponseHandler.java httpclientandroidlib/client/UserTokenHandler.java httpclientandroidlib/client/utils/CloneUtils.java httpclientandroidlib/client/utils/Idn.java httpclientandroidlib/client/utils/JdkIdn.java httpclientandroidlib/client/utils/Punycode.java httpclientandroidlib/client/utils/Rfc3492Idn.java httpclientandroidlib/client/utils/URIUtils.java httpclientandroidlib/client/utils/URLEncodedUtils.java httpclientandroidlib/conn/BasicEofSensorWatcher.java httpclientandroidlib/conn/BasicManagedEntity.java httpclientandroidlib/conn/ClientConnectionManager.java httpclientandroidlib/conn/ClientConnectionManagerFactory.java httpclientandroidlib/conn/ClientConnectionOperator.java httpclientandroidlib/conn/ClientConnectionRequest.java httpclientandroidlib/conn/ConnectionKeepAliveStrategy.java httpclientandroidlib/conn/ConnectionPoolTimeoutException.java httpclientandroidlib/conn/ConnectionReleaseTrigger.java httpclientandroidlib/conn/ConnectTimeoutException.java httpclientandroidlib/conn/EofSensorInputStream.java httpclientandroidlib/conn/EofSensorWatcher.java httpclientandroidlib/conn/HttpHostConnectException.java httpclientandroidlib/conn/HttpRoutedConnection.java httpclientandroidlib/conn/ManagedClientConnection.java httpclientandroidlib/conn/MultihomePlainSocketFactory.java httpclientandroidlib/conn/OperatedClientConnection.java httpclientandroidlib/conn/params/ConnConnectionParamBean.java httpclientandroidlib/conn/params/ConnConnectionPNames.java httpclientandroidlib/conn/params/ConnManagerParamBean.java httpclientandroidlib/conn/params/ConnManagerParams.java httpclientandroidlib/conn/params/ConnManagerPNames.java httpclientandroidlib/conn/params/ConnPerRoute.java httpclientandroidlib/conn/params/ConnPerRouteBean.java httpclientandroidlib/conn/params/ConnRouteParamBean.java httpclientandroidlib/conn/params/ConnRouteParams.java httpclientandroidlib/conn/params/ConnRoutePNames.java httpclientandroidlib/conn/routing/BasicRouteDirector.java httpclientandroidlib/conn/routing/HttpRoute.java httpclientandroidlib/conn/routing/HttpRouteDirector.java httpclientandroidlib/conn/routing/HttpRoutePlanner.java httpclientandroidlib/conn/routing/RouteInfo.java httpclientandroidlib/conn/routing/RouteTracker.java httpclientandroidlib/conn/scheme/HostNameResolver.java httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactory.java httpclientandroidlib/conn/scheme/LayeredSchemeSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/LayeredSocketFactory.java httpclientandroidlib/conn/scheme/LayeredSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/PlainSocketFactory.java httpclientandroidlib/conn/scheme/Scheme.java httpclientandroidlib/conn/scheme/SchemeRegistry.java httpclientandroidlib/conn/scheme/SchemeSocketFactory.java httpclientandroidlib/conn/scheme/SchemeSocketFactoryAdaptor.java httpclientandroidlib/conn/scheme/SocketFactory.java httpclientandroidlib/conn/scheme/SocketFactoryAdaptor.java httpclientandroidlib/conn/ssl/AbstractVerifier.java httpclientandroidlib/conn/ssl/AllowAllHostnameVerifier.java httpclientandroidlib/conn/ssl/BrowserCompatHostnameVerifier.java httpclientandroidlib/conn/ssl/SSLSocketFactory.java httpclientandroidlib/conn/ssl/StrictHostnameVerifier.java httpclientandroidlib/conn/ssl/TrustManagerDecorator.java httpclientandroidlib/conn/ssl/TrustSelfSignedStrategy.java httpclientandroidlib/conn/ssl/TrustStrategy.java httpclientandroidlib/conn/ssl/X509HostnameVerifier.java httpclientandroidlib/conn/util/InetAddressUtils.java httpclientandroidlib/ConnectionClosedException.java httpclientandroidlib/ConnectionReuseStrategy.java httpclientandroidlib/cookie/ClientCookie.java httpclientandroidlib/cookie/Cookie.java httpclientandroidlib/cookie/CookieAttributeHandler.java httpclientandroidlib/cookie/CookieIdentityComparator.java httpclientandroidlib/cookie/CookieOrigin.java httpclientandroidlib/cookie/CookiePathComparator.java httpclientandroidlib/cookie/CookieRestrictionViolationException.java httpclientandroidlib/cookie/CookieSpec.java httpclientandroidlib/cookie/CookieSpecFactory.java httpclientandroidlib/cookie/CookieSpecRegistry.java httpclientandroidlib/cookie/MalformedCookieException.java httpclientandroidlib/cookie/params/CookieSpecParamBean.java httpclientandroidlib/cookie/params/CookieSpecPNames.java httpclientandroidlib/cookie/SetCookie.java httpclientandroidlib/cookie/SetCookie2.java httpclientandroidlib/cookie/SM.java httpclientandroidlib/entity/AbstractHttpEntity.java httpclientandroidlib/entity/BasicHttpEntity.java httpclientandroidlib/entity/BufferedHttpEntity.java httpclientandroidlib/entity/ByteArrayEntity.java httpclientandroidlib/entity/ContentLengthStrategy.java httpclientandroidlib/entity/ContentProducer.java httpclientandroidlib/entity/EntityTemplate.java httpclientandroidlib/entity/FileEntity.java httpclientandroidlib/entity/HttpEntityWrapper.java httpclientandroidlib/entity/InputStreamEntity.java httpclientandroidlib/entity/SerializableEntity.java httpclientandroidlib/entity/StringEntity.java httpclientandroidlib/FormattedHeader.java httpclientandroidlib/Header.java httpclientandroidlib/HeaderElement.java httpclientandroidlib/HeaderElementIterator.java httpclientandroidlib/HeaderIterator.java httpclientandroidlib/HttpClientConnection.java httpclientandroidlib/HttpConnection.java httpclientandroidlib/HttpConnectionMetrics.java httpclientandroidlib/HttpEntity.java httpclientandroidlib/HttpEntityEnclosingRequest.java httpclientandroidlib/HttpException.java httpclientandroidlib/HttpHeaders.java httpclientandroidlib/HttpHost.java httpclientandroidlib/HttpInetConnection.java httpclientandroidlib/HttpMessage.java httpclientandroidlib/HttpRequest.java httpclientandroidlib/HttpRequestFactory.java httpclientandroidlib/HttpRequestInterceptor.java httpclientandroidlib/HttpResponse.java httpclientandroidlib/HttpResponseFactory.java httpclientandroidlib/HttpResponseInterceptor.java httpclientandroidlib/HttpServerConnection.java httpclientandroidlib/HttpStatus.java httpclientandroidlib/HttpVersion.java httpclientandroidlib/impl/AbstractHttpClientConnection.java httpclientandroidlib/impl/AbstractHttpServerConnection.java httpclientandroidlib/impl/auth/AuthSchemeBase.java httpclientandroidlib/impl/auth/BasicScheme.java httpclientandroidlib/impl/auth/BasicSchemeFactory.java httpclientandroidlib/impl/auth/DigestScheme.java httpclientandroidlib/impl/auth/DigestSchemeFactory.java httpclientandroidlib/impl/auth/NTLMEngine.java httpclientandroidlib/impl/auth/NTLMEngineException.java httpclientandroidlib/impl/auth/NTLMEngineImpl.java httpclientandroidlib/impl/auth/NTLMScheme.java httpclientandroidlib/impl/auth/NTLMSchemeFactory.java httpclientandroidlib/impl/auth/RFC2617Scheme.java httpclientandroidlib/impl/auth/SpnegoTokenGenerator.java httpclientandroidlib/impl/auth/UnsupportedDigestAlgorithmException.java httpclientandroidlib/impl/client/AbstractAuthenticationHandler.java httpclientandroidlib/impl/client/AbstractHttpClient.java httpclientandroidlib/impl/client/BasicAuthCache.java httpclientandroidlib/impl/client/BasicCookieStore.java httpclientandroidlib/impl/client/BasicCredentialsProvider.java httpclientandroidlib/impl/client/BasicResponseHandler.java httpclientandroidlib/impl/client/ClientParamsStack.java httpclientandroidlib/impl/client/ContentEncodingHttpClient.java httpclientandroidlib/impl/client/DefaultConnectionKeepAliveStrategy.java httpclientandroidlib/impl/client/DefaultHttpClient.java httpclientandroidlib/impl/client/DefaultHttpRequestRetryHandler.java httpclientandroidlib/impl/client/DefaultProxyAuthenticationHandler.java httpclientandroidlib/impl/client/DefaultRedirectHandler.java httpclientandroidlib/impl/client/DefaultRedirectStrategy.java httpclientandroidlib/impl/client/DefaultRedirectStrategyAdaptor.java httpclientandroidlib/impl/client/DefaultRequestDirector.java httpclientandroidlib/impl/client/DefaultTargetAuthenticationHandler.java httpclientandroidlib/impl/client/DefaultUserTokenHandler.java httpclientandroidlib/impl/client/EntityEnclosingRequestWrapper.java httpclientandroidlib/impl/client/RedirectLocations.java httpclientandroidlib/impl/client/RequestWrapper.java httpclientandroidlib/impl/client/RoutedRequest.java httpclientandroidlib/impl/client/TunnelRefusedException.java httpclientandroidlib/impl/conn/AbstractClientConnAdapter.java httpclientandroidlib/impl/conn/AbstractPooledConnAdapter.java httpclientandroidlib/impl/conn/AbstractPoolEntry.java httpclientandroidlib/impl/conn/ConnectionShutdownException.java httpclientandroidlib/impl/conn/DefaultClientConnection.java httpclientandroidlib/impl/conn/DefaultClientConnectionOperator.java httpclientandroidlib/impl/conn/DefaultHttpRoutePlanner.java httpclientandroidlib/impl/conn/DefaultResponseParser.java httpclientandroidlib/impl/conn/HttpInetSocketAddress.java httpclientandroidlib/impl/conn/IdleConnectionHandler.java httpclientandroidlib/impl/conn/LoggingSessionInputBuffer.java httpclientandroidlib/impl/conn/LoggingSessionOutputBuffer.java httpclientandroidlib/impl/conn/ProxySelectorRoutePlanner.java httpclientandroidlib/impl/conn/SchemeRegistryFactory.java httpclientandroidlib/impl/conn/SingleClientConnManager.java httpclientandroidlib/impl/conn/tsccm/AbstractConnPool.java httpclientandroidlib/impl/conn/tsccm/BasicPooledConnAdapter.java httpclientandroidlib/impl/conn/tsccm/BasicPoolEntry.java httpclientandroidlib/impl/conn/tsccm/BasicPoolEntryRef.java httpclientandroidlib/impl/conn/tsccm/ConnPoolByRoute.java httpclientandroidlib/impl/conn/tsccm/PoolEntryRequest.java httpclientandroidlib/impl/conn/tsccm/RefQueueHandler.java httpclientandroidlib/impl/conn/tsccm/RefQueueWorker.java httpclientandroidlib/impl/conn/tsccm/RouteSpecificPool.java httpclientandroidlib/impl/conn/tsccm/ThreadSafeClientConnManager.java httpclientandroidlib/impl/conn/tsccm/WaitingThread.java httpclientandroidlib/impl/conn/tsccm/WaitingThreadAborter.java httpclientandroidlib/impl/conn/Wire.java httpclientandroidlib/impl/cookie/AbstractCookieAttributeHandler.java httpclientandroidlib/impl/cookie/AbstractCookieSpec.java httpclientandroidlib/impl/cookie/BasicClientCookie.java httpclientandroidlib/impl/cookie/BasicClientCookie2.java httpclientandroidlib/impl/cookie/BasicCommentHandler.java httpclientandroidlib/impl/cookie/BasicDomainHandler.java httpclientandroidlib/impl/cookie/BasicExpiresHandler.java httpclientandroidlib/impl/cookie/BasicMaxAgeHandler.java httpclientandroidlib/impl/cookie/BasicPathHandler.java httpclientandroidlib/impl/cookie/BasicSecureHandler.java httpclientandroidlib/impl/cookie/BestMatchSpec.java httpclientandroidlib/impl/cookie/BestMatchSpecFactory.java httpclientandroidlib/impl/cookie/BrowserCompatSpec.java httpclientandroidlib/impl/cookie/BrowserCompatSpecFactory.java httpclientandroidlib/impl/cookie/CookieSpecBase.java httpclientandroidlib/impl/cookie/DateParseException.java httpclientandroidlib/impl/cookie/DateUtils.java httpclientandroidlib/impl/cookie/IgnoreSpec.java httpclientandroidlib/impl/cookie/IgnoreSpecFactory.java httpclientandroidlib/impl/cookie/NetscapeDomainHandler.java httpclientandroidlib/impl/cookie/NetscapeDraftHeaderParser.java httpclientandroidlib/impl/cookie/NetscapeDraftSpec.java httpclientandroidlib/impl/cookie/NetscapeDraftSpecFactory.java httpclientandroidlib/impl/cookie/PublicSuffixFilter.java httpclientandroidlib/impl/cookie/PublicSuffixListParser.java httpclientandroidlib/impl/cookie/RFC2109DomainHandler.java httpclientandroidlib/impl/cookie/RFC2109Spec.java httpclientandroidlib/impl/cookie/RFC2109SpecFactory.java httpclientandroidlib/impl/cookie/RFC2109VersionHandler.java httpclientandroidlib/impl/cookie/RFC2965CommentUrlAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965DiscardAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965PortAttributeHandler.java httpclientandroidlib/impl/cookie/RFC2965Spec.java httpclientandroidlib/impl/cookie/RFC2965SpecFactory.java httpclientandroidlib/impl/cookie/RFC2965VersionAttributeHandler.java httpclientandroidlib/impl/DefaultConnectionReuseStrategy.java httpclientandroidlib/impl/DefaultHttpClientConnection.java httpclientandroidlib/impl/DefaultHttpRequestFactory.java httpclientandroidlib/impl/DefaultHttpResponseFactory.java httpclientandroidlib/impl/DefaultHttpServerConnection.java httpclientandroidlib/impl/EnglishReasonPhraseCatalog.java httpclientandroidlib/impl/entity/EntityDeserializer.java httpclientandroidlib/impl/entity/EntitySerializer.java httpclientandroidlib/impl/entity/LaxContentLengthStrategy.java httpclientandroidlib/impl/entity/StrictContentLengthStrategy.java httpclientandroidlib/impl/HttpConnectionMetricsImpl.java httpclientandroidlib/impl/io/AbstractMessageParser.java httpclientandroidlib/impl/io/AbstractMessageWriter.java httpclientandroidlib/impl/io/AbstractSessionInputBuffer.java httpclientandroidlib/impl/io/AbstractSessionOutputBuffer.java httpclientandroidlib/impl/io/ChunkedInputStream.java httpclientandroidlib/impl/io/ChunkedOutputStream.java httpclientandroidlib/impl/io/ContentLengthInputStream.java httpclientandroidlib/impl/io/ContentLengthOutputStream.java httpclientandroidlib/impl/io/HttpRequestParser.java httpclientandroidlib/impl/io/HttpRequestWriter.java httpclientandroidlib/impl/io/HttpResponseParser.java httpclientandroidlib/impl/io/HttpResponseWriter.java httpclientandroidlib/impl/io/HttpTransportMetricsImpl.java httpclientandroidlib/impl/io/IdentityInputStream.java httpclientandroidlib/impl/io/IdentityOutputStream.java httpclientandroidlib/impl/io/SocketInputBuffer.java httpclientandroidlib/impl/io/SocketOutputBuffer.java httpclientandroidlib/impl/NoConnectionReuseStrategy.java httpclientandroidlib/impl/SocketHttpClientConnection.java httpclientandroidlib/impl/SocketHttpServerConnection.java httpclientandroidlib/io/BufferInfo.java httpclientandroidlib/io/EofSensor.java httpclientandroidlib/io/HttpMessageParser.java httpclientandroidlib/io/HttpMessageWriter.java httpclientandroidlib/io/HttpTransportMetrics.java httpclientandroidlib/io/SessionInputBuffer.java httpclientandroidlib/io/SessionOutputBuffer.java httpclientandroidlib/MalformedChunkCodingException.java httpclientandroidlib/message/AbstractHttpMessage.java httpclientandroidlib/message/BasicHeader.java httpclientandroidlib/message/BasicHeaderElement.java httpclientandroidlib/message/BasicHeaderElementIterator.java httpclientandroidlib/message/BasicHeaderIterator.java httpclientandroidlib/message/BasicHeaderValueFormatter.java httpclientandroidlib/message/BasicHeaderValueParser.java httpclientandroidlib/message/BasicHttpEntityEnclosingRequest.java httpclientandroidlib/message/BasicHttpRequest.java httpclientandroidlib/message/BasicHttpResponse.java httpclientandroidlib/message/BasicLineFormatter.java httpclientandroidlib/message/BasicLineParser.java httpclientandroidlib/message/BasicListHeaderIterator.java httpclientandroidlib/message/BasicNameValuePair.java httpclientandroidlib/message/BasicRequestLine.java httpclientandroidlib/message/BasicStatusLine.java httpclientandroidlib/message/BasicTokenIterator.java httpclientandroidlib/message/BufferedHeader.java httpclientandroidlib/message/HeaderGroup.java httpclientandroidlib/message/HeaderValueFormatter.java httpclientandroidlib/message/HeaderValueParser.java httpclientandroidlib/message/LineFormatter.java httpclientandroidlib/message/LineParser.java httpclientandroidlib/message/ParserCursor.java httpclientandroidlib/MethodNotSupportedException.java httpclientandroidlib/NameValuePair.java httpclientandroidlib/NoHttpResponseException.java httpclientandroidlib/params/AbstractHttpParams.java httpclientandroidlib/params/BasicHttpParams.java httpclientandroidlib/params/CoreConnectionPNames.java httpclientandroidlib/params/CoreProtocolPNames.java httpclientandroidlib/params/DefaultedHttpParams.java httpclientandroidlib/params/HttpAbstractParamBean.java httpclientandroidlib/params/HttpConnectionParamBean.java httpclientandroidlib/params/HttpConnectionParams.java httpclientandroidlib/params/HttpParams.java httpclientandroidlib/params/HttpProtocolParamBean.java httpclientandroidlib/params/HttpProtocolParams.java httpclientandroidlib/params/SyncBasicHttpParams.java httpclientandroidlib/ParseException.java httpclientandroidlib/protocol/BasicHttpContext.java httpclientandroidlib/protocol/BasicHttpProcessor.java httpclientandroidlib/protocol/DefaultedHttpContext.java httpclientandroidlib/protocol/ExecutionContext.java httpclientandroidlib/protocol/HTTP.java httpclientandroidlib/protocol/HttpContext.java httpclientandroidlib/protocol/HttpDateGenerator.java httpclientandroidlib/protocol/HttpExpectationVerifier.java httpclientandroidlib/protocol/HttpProcessor.java httpclientandroidlib/protocol/HttpRequestExecutor.java httpclientandroidlib/protocol/HttpRequestHandler.java httpclientandroidlib/protocol/HttpRequestHandlerRegistry.java httpclientandroidlib/protocol/HttpRequestHandlerResolver.java httpclientandroidlib/protocol/HttpRequestInterceptorList.java httpclientandroidlib/protocol/HttpResponseInterceptorList.java httpclientandroidlib/protocol/HttpService.java httpclientandroidlib/protocol/ImmutableHttpProcessor.java httpclientandroidlib/protocol/RequestConnControl.java httpclientandroidlib/protocol/RequestContent.java httpclientandroidlib/protocol/RequestDate.java httpclientandroidlib/protocol/RequestExpectContinue.java httpclientandroidlib/protocol/RequestTargetHost.java httpclientandroidlib/protocol/RequestUserAgent.java httpclientandroidlib/protocol/ResponseConnControl.java httpclientandroidlib/protocol/ResponseContent.java httpclientandroidlib/protocol/ResponseDate.java httpclientandroidlib/protocol/ResponseServer.java httpclientandroidlib/protocol/SyncBasicHttpContext.java httpclientandroidlib/protocol/UriPatternMatcher.java httpclientandroidlib/ProtocolException.java httpclientandroidlib/ProtocolVersion.java httpclientandroidlib/ReasonPhraseCatalog.java httpclientandroidlib/RequestLine.java httpclientandroidlib/StatusLine.java httpclientandroidlib/TokenIterator.java httpclientandroidlib/TruncatedChunkException.java httpclientandroidlib/UnsupportedHttpVersionException.java httpclientandroidlib/util/ByteArrayBuffer.java httpclientandroidlib/util/CharArrayBuffer.java httpclientandroidlib/util/EncodingUtils.java httpclientandroidlib/util/EntityUtils.java httpclientandroidlib/util/ExceptionUtils.java httpclientandroidlib/util/LangUtils.java httpclientandroidlib/util/VersionInfo.java json-simple/ItemList.java json-simple/JSONArray.java json-simple/JSONAware.java json-simple/JSONObject.java json-simple/JSONStreamAware.java json-simple/JSONValue.java json-simple/parser/ContainerFactory.java json-simple/parser/ContentHandler.java json-simple/parser/JSONParser.java json-simple/parser/ParseException.java json-simple/parser/Yylex.java json-simple/parser/Yytoken.java apache/commons/codec/binary/Base32.java apache/commons/codec/binary/Base32InputStream.java apache/commons/codec/binary/Base32OutputStream.java apache/commons/codec/binary/Base64.java apache/commons/codec/binary/Base64InputStream.java apache/commons/codec/binary/Base64OutputStream.java apache/commons/codec/binary/BaseNCodec.java apache/commons/codec/binary/BaseNCodecInputStream.java apache/commons/codec/binary/BaseNCodecOutputStream.java apache/commons/codec/binary/BinaryCodec.java apache/commons/codec/binary/Hex.java apache/commons/codec/binary/StringUtils.java apache/commons/codec/BinaryDecoder.java apache/commons/codec/BinaryEncoder.java apache/commons/codec/CharEncoding.java apache/commons/codec/Decoder.java apache/commons/codec/DecoderException.java apache/commons/codec/digest/DigestUtils.java apache/commons/codec/Encoder.java apache/commons/codec/EncoderException.java apache/commons/codec/language/AbstractCaverphone.java apache/commons/codec/language/Caverphone.java apache/commons/codec/language/Caverphone1.java apache/commons/codec/language/Caverphone2.java apache/commons/codec/language/ColognePhonetic.java apache/commons/codec/language/DoubleMetaphone.java apache/commons/codec/language/Metaphone.java apache/commons/codec/language/RefinedSoundex.java apache/commons/codec/language/Soundex.java apache/commons/codec/language/SoundexUtils.java apache/commons/codec/net/BCodec.java apache/commons/codec/net/QCodec.java apache/commons/codec/net/QuotedPrintableCodec.java apache/commons/codec/net/RFC1522Codec.java apache/commons/codec/net/URLCodec.java apache/commons/codec/net/Utils.java apache/commons/codec/StringDecoder.java apache/commons/codec/StringEncoder.java apache/commons/codec/StringEncoderComparator.java
-SYNC_RES_DRAWABLE := mobile/android/base/resources/drawable/desktop.png mobile/android/base/resources/drawable/mobile.png mobile/android/base/resources/drawable/pin_background.xml mobile/android/base/resources/drawable/sync_ic_launcher.png
-SYNC_RES_DRAWABLE_LDPI := mobile/android/base/resources/drawable-ldpi/sync_fx_icon.png mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png
-SYNC_RES_DRAWABLE_MDPI := mobile/android/base/resources/drawable-mdpi/sync_fx_icon.png mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png
-SYNC_RES_DRAWABLE_HDPI := mobile/android/base/resources/drawable-hdpi/sync_fx_icon.png mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png
-SYNC_RES_LAYOUT := res/layout/sync_account.xml res/layout/sync_list_item.xml res/layout/sync_redirect_to_setup.xml res/layout/sync_send_tab.xml res/layout/sync_setup.xml res/layout/sync_setup_failure.xml res/layout/sync_setup_jpake_waiting.xml res/layout/sync_setup_nointernet.xml res/layout/sync_setup_pair.xml res/layout/sync_setup_success.xml res/layout/sync_stub.xml
+SYNC_RES_DRAWABLE := mobile/android/base/resources/drawable/desktop.png mobile/android/base/resources/drawable/mobile.png mobile/android/base/resources/drawable/pin_background.xml
+SYNC_RES_DRAWABLE_LDPI := 
+SYNC_RES_DRAWABLE_MDPI := 
+SYNC_RES_DRAWABLE_HDPI := 
+SYNC_RES_LAYOUT := res/layout/sync_account.xml res/layout/sync_list_item.xml res/layout/sync_redirect_to_setup.xml res/layout/sync_send_tab.xml res/layout/sync_setup.xml res/layout/sync_setup_failure.xml res/layout/sync_setup_jpake_waiting.xml res/layout/sync_setup_nointernet.xml res/layout/sync_setup_pair.xml res/layout/sync_setup_success.xml
 SYNC_RES_VALUES := res/values/sync_styles.xml
+SYNC_RES_XML :=
+SYNC_PP_RES_XML := res/xml/sync_syncadapter.xml res/xml/sync_options.xml res/xml/sync_authenticator.xml
--- a/mobile/android/base/gfx/LayerController.java
+++ b/mobile/android/base/gfx/LayerController.java
@@ -295,38 +295,16 @@ public class LayerController {
         // the current Gecko coordinate in CSS pixels.
         PointF layerPoint = new PointF(
                 ((viewPoint.x + origin.x) / zoom) - (geckoOrigin.x / geckoZoom),
                 ((viewPoint.y + origin.y) / zoom) - (geckoOrigin.y / geckoZoom));
 
         return layerPoint;
     }
 
-    /**
-     * Does the opposite of convertViewPointToLayerPoint.
-     */
-    public PointF convertLayerPointToViewPoint(PointF layerPoint) {
-        if (mLayerClient == null) {
-            return null;
-        }
-
-        ImmutableViewportMetrics viewportMetrics = mViewportMetrics;
-        PointF origin = viewportMetrics.getOrigin();
-        float zoom = viewportMetrics.zoomFactor;
-        ViewportMetrics geckoViewport = mLayerClient.getGeckoViewportMetrics();
-        PointF geckoOrigin = geckoViewport.getOrigin();
-        float geckoZoom = geckoViewport.getZoomFactor();
-
-        PointF viewPoint = new PointF(
-                ((layerPoint.x + (geckoOrigin.x / geckoZoom)) * zoom - origin.x),
-                ((layerPoint.y + (geckoOrigin.y / geckoZoom)) * zoom - origin.y));
-
-        return viewPoint;
-    }
-
     /** Retrieves whether we should show checkerboard checks or not. */
     public boolean checkerboardShouldShowChecks() {
         return mCheckerboardShouldShowChecks;
     }
 
     /** Retrieves the color that the checkerboard should be. */
     public int getCheckerboardColor() {
         return mCheckerboardColor;
deleted file mode 100644
index 04ccdfcb4dbc973aa6f4603090ddace0485d466d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 5c6a89f801c19b84469c7a609fca180c07e8bd41..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 2db3b7771bf5bdc73df2fe859b6d38ca9d52338b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 7e383f14932ff0635f6bcf0807a2ce97c6a49c41..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index b982cf97903836a406b640bc76ca4de112f1d788..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index f2d917b905cb81ca29a8d528b4f0c33823332623..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index f2d917b905cb81ca29a8d528b4f0c33823332623..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
--- a/mobile/android/base/resources/layout/sync_account.xml
+++ b/mobile/android/base/resources/layout/sync_account.xml
@@ -1,26 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout" >
-  <LinearLayout
-    android:id="@+id/account_top"
-    style="@style/SyncTop">
-
-    <ImageView
-      style="@style/SyncTopIcon" />
-    <TextView
-      style="@style/SyncTextTitle"
+  <TextView
+      style="@style/SyncTop"
+      android:id="@+id/account_top"
       android:text="@string/sync_title_connect" />
-  </LinearLayout>
-
   <ScrollView
     android:id="@+id/account_content"
     style="@style/SyncLayout"
     android:layout_below="@id/account_top"
     android:layout_above="@+id/account_bottom">
 
 	<LinearLayout
       style="@style/SyncLayout.Vertical"
--- a/mobile/android/base/resources/layout/sync_redirect_to_setup.xml
+++ b/mobile/android/base/resources/layout/sync_redirect_to_setup.xml
@@ -1,37 +1,28 @@
 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout" >
-  <LinearLayout
-    android:id="@+id/redirect_top"
-    style="@style/SyncTop">
-    <ImageView
-      style="@style/SyncTopIcon" />
-    <TextView
-      style="@style/SyncTextTitle"
+  <TextView
+      style="@style/SyncTop"
+      android:id="@+id/redirect_top"
       android:text="@string/sync_title_redirect_to_set_up_sync" />
-  </LinearLayout>
   <TextView
     style="@style/SyncTextItem"
     android:layout_below="@id/redirect_top"
     android:layout_above="@+id/redirect_bottom"
     android:padding="20dp"
     android:text="@string/sync_text_redirect_to_set_up_sync" />
   <LinearLayout
     android:id="@id/redirect_bottom"
     style="@style/SyncBottom"
     android:orientation="horizontal" >
 
     <Button
-      android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:layout_weight="1"
+      style="@style/SyncButton"
       android:onClick="redirectToSetupHandler"
       android:text="@string/sync_button_set_up_sync" />
-     <Button
-      android:layout_width="fill_parent"
-      android:layout_height="wrap_content"
-      android:layout_weight="1"
+    <Button
+      style="@style/SyncButton"
       android:onClick="cancelClickHandler"
       android:text="@string/sync_button_cancel" />
   </LinearLayout>
 </RelativeLayout>
--- a/mobile/android/base/resources/layout/sync_send_tab.xml
+++ b/mobile/android/base/resources/layout/sync_send_tab.xml
@@ -1,20 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout.Vertical" >
-  <LinearLayout
-    android:id="@+id/sendtab_top"
-    style="@style/SyncTop" >
-    <ImageView
-      style="@style/SyncTopIcon" />
-    <TextView
-      style="@style/SyncTextTitle"
+  <TextView
+      style="@style/SyncTop"
+      android:id="@+id/sendtab_top"
       android:text="@string/sync_title_send_tab" />
-  </LinearLayout>
 
   <ListView
     android:id="@+id/device_list"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_below="@id/sendtab_top"
     android:layout_above="@+id/sendtab_bottom" >
   </ListView>
--- a/mobile/android/base/resources/layout/sync_setup.xml
+++ b/mobile/android/base/resources/layout/sync_setup.xml
@@ -1,36 +1,30 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout" >
 
-  <LinearLayout
-    android:id="@+id/setup_top"
-    style="@style/SyncTop" >
-    <ImageView
-      style="@style/SyncTopIcon" />
-    <TextView
-      android:id="@+id/setup_title"
-      style="@style/SyncTextTitle"
+  <TextView
+      style="@style/SyncTop"
+      android:id="@+id/setup_top"
       android:text="@string/sync_title_connect" />
-  </LinearLayout>
 
   <ScrollView
     style="@style/SyncLayout"
     android:fillViewport="true"
     android:layout_below="@id/setup_top"
     android:layout_above="@+id/setup_bottom" >
 
     <LinearLayout
         style="@style/SyncLayout.Vertical"
-        android:layout_height="fill_parent"
+        android:layout_height="wrap_content"
         android:padding="15dp" >
 
       <TextView
         android:id="@+id/setup_header"
         style="@style/SyncTextItem"
         android:gravity="left"
         android:layout_marginTop="15dp"
         android:text="@string/sync_subtitle_header"
--- a/mobile/android/base/resources/layout/sync_setup_failure.xml
+++ b/mobile/android/base/resources/layout/sync_setup_failure.xml
@@ -1,24 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout" >
-  <LinearLayout
-    android:id="@+id/failure_top"
-    style="@style/SyncTop" >
-  <ImageView
-    style="@style/SyncTopIcon" />
   <TextView
-    style="@style/SyncTextTitle"
-    android:text="@string/sync_title_fail" />
-  </LinearLayout>
+      style="@style/SyncTop"
+      android:id="@+id/failure_top"
+      android:text="@string/sync_title_fail" />
 
   <TextView
     android:id="@+id/failure_subtitle1"
     style="@style/SyncTextItem"
     android:layout_below="@id/failure_top"
     android:padding="20dp"
     android:text="@string/sync_subtitle_fail" />
 
--- a/mobile/android/base/resources/layout/sync_setup_jpake_waiting.xml
+++ b/mobile/android/base/resources/layout/sync_setup_jpake_waiting.xml
@@ -1,24 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout" >
-  <LinearLayout
+  <TextView
+    style="@style/SyncTop"
     android:id="@+id/waiting_top"
-    style="@style/SyncTop" >
-  <ImageView
-    style="@style/SyncTopIcon" />
-  <TextView
-    style="@style/SyncTextTitle"
     android:text="@string/sync_title_connect" />
-  </LinearLayout>
 
   <ProgressBar
     android:id="@+id/waiting_content1"
     style="@android:style/Widget.ProgressBar.Horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:layout_below="@id/waiting_top"
     android:indeterminateOnly="true"
--- a/mobile/android/base/resources/layout/sync_setup_nointernet.xml
+++ b/mobile/android/base/resources/layout/sync_setup_nointernet.xml
@@ -1,30 +1,27 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 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/. -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout" >
-  <LinearLayout
+  <TextView
+    style="@style/SyncTop"
     android:id="@+id/internet_top"
-    style="@style/SyncTop">
-    <ImageView
-      style="@style/SyncTopIcon" />
-    <TextView
-      style="@style/SyncTextTitle"
-      android:text="@string/sync_title_fail" />
-  </LinearLayout>
+    android:text="@string/sync_title_fail" />
+
   <TextView
     style="@style/SyncTextItem"
     android:layout_below="@id/internet_top"
     android:layout_marginTop="20dp"
     android:gravity="center"
     android:text="@string/sync_subtitle_nointernet" />
+
   <LinearLayout
     style="@style/SyncBottom" >
     <Button
       style="@style/SyncButton"
       android:onClick="cancelClickHandler"
       android:text="@string/sync_button_ok" />
   </LinearLayout>
 </RelativeLayout>
--- a/mobile/android/base/resources/layout/sync_setup_pair.xml
+++ b/mobile/android/base/resources/layout/sync_setup_pair.xml
@@ -1,25 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- 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/. -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout" >
-  <LinearLayout
+  <TextView
+    style="@style/SyncTop"
     android:id="@+id/pair_top"
-    style="@style/SyncTop" >
-    <ImageView
-      style="@style/SyncTopIcon" />
-    <TextView
-      android:id="@+id/setup_title"
-      style="@style/SyncTextTitle"
-      android:text="@string/sync_title_pair" />
-  </LinearLayout>
+    android:text="@string/sync_title_pair" />
+
   <ScrollView
     style="@style/SyncLayout"
     android:layout_below="@id/pair_top"
     android:layout_above="@+id/pair_bottom" >
 
     <LinearLayout
       style="@style/SyncLayout.Vertical"
       android:gravity="center"
--- a/mobile/android/base/resources/layout/sync_setup_success.xml
+++ b/mobile/android/base/resources/layout/sync_setup_success.xml
@@ -1,32 +1,28 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   style="@style/SyncLayout" >
 
-  <LinearLayout
+  <TextView
+    style="@style/SyncTop"
     android:id="@+id/success_top"
-    style="@style/SyncTop" >
-    <ImageView
-      style="@style/SyncTopIcon"/>
-    <TextView
-      style="@style/SyncTextTitle"
-      android:text="@string/sync_title_success" />
-  </LinearLayout>
+    android:text="@string/sync_title_success" />
+
   <TextView
     android:id="@+id/setup_success_subtitle"
-	style="@style/SyncTextItem"
-	android:gravity="left"
+    style="@style/SyncTextItem"
+    android:gravity="left"
     android:padding="20dp"
     android:layout_below="@id/success_top"
-	android:text="@string/sync_subtitle_success" />
+    android:text="@string/sync_subtitle_success" />
 
   <LinearLayout
     style="@style/SyncBottom"
     android:orientation="horizontal" >
     <Button
       style="@style/SyncButton"
       android:onClick="settingsClickHandler"
       android:text="@string/sync_settings" />
deleted file mode 100644
--- a/mobile/android/base/resources/layout/sync_stub.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:orientation="vertical" >
-
-    <TextView
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:text="Hello… is it me you're looking for?" />
-
-</LinearLayout>
--- a/mobile/android/base/resources/values/sync_styles.xml
+++ b/mobile/android/base/resources/values/sync_styles.xml
@@ -56,25 +56,30 @@
     <item name="android:ems">4</item>
     <item name="android:maxLength">4</item>
     <item name="android:imeOptions">actionNext|flagNoExtractUi</item>
   </style>
 
   <!-- Theme Styles -->
   <style name="SyncTheme" parent="@android:style/Theme.NoTitleBar"/>
 
+  <!-- Top title bar: a text view with the Sync icon to the left. -->
   <style name="SyncTop">
+    <item name="android:textAppearance">@android:style/TextAppearance.Large</item>
     <item name="android:layout_width">fill_parent</item>
     <item name="android:layout_height">wrap_content</item>
-    <item name="android:gravity">left</item>
-    <item name="android:orientation">horizontal</item>
+    <item name="android:gravity">center_vertical|left</item>
+    <item name="android:drawableLeft">@drawable/icon</item>
+    <item name="android:padding">4dp</item>
+    <item name="android:drawablePadding">4dp</item>
     <item name="android:layout_alignParentTop">true</item>
     <item name="android:background">@android:drawable/bottom_bar</item>
   </style>
-    <style name="SyncBottom">
+  <!-- Bottom bar: a horizontal linear layout with buttons in it. -->
+  <style name="SyncBottom">
     <item name="android:layout_width">fill_parent</item>
     <item name="android:layout_height">wrap_content</item>
     <item name="android:layout_gravity">center</item>
     <item name="android:gravity">center</item>
     <item name="android:layout_alignParentBottom">true</item>
     <item name="android:background">@android:drawable/bottom_bar</item>
   </style>
   <style name="SyncButton" parent="@android:style/Widget.Button">
@@ -90,16 +95,9 @@
     <item name="android:layout_gravity">center</item>
     <item name="android:layout_marginBottom">5dp</item>
     <item name="android:gravity">center</item>
     <item name="android:background">@drawable/pin_background</item>
     <item name="android:textColor">#FFFFFF</item>
     <item name="android:textSize">35sp</item>
     <item name="android:text">@string/sync_pin_default</item>
   </style>
-  <style name="SyncTopIcon">
-    <item name="android:src">@drawable/sync_fx_icon</item>
-    <item name="android:layout_width">wrap_content</item>
-    <item name="android:layout_height">wrap_content</item>
-    <item name="android:paddingTop">2dp</item>
-    <item name="android:paddingLeft">4dp</item>
-  </style>
 </resources>
deleted file mode 100644
--- a/mobile/android/base/resources/xml/sync_authenticator.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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/. -->
-
-<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:accountType="org.mozilla.firefox_sync"
-    android:icon="@drawable/sync_ic_launcher"
-    android:smallIcon="@drawable/sync_ic_launcher"
-    android:label="@string/sync_account_label"
-    android:accountPreferences="@xml/sync_options" />
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/xml/sync_authenticator.xml.in
@@ -0,0 +1,12 @@
+#filter substitution
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accountType="@MOZ_ANDROID_SHARED_ACCOUNT_TYPE@"
+    android:icon="@drawable/icon"
+    android:smallIcon="@drawable/icon"
+    android:label="@string/sync_account_label"
+    android:accountPreferences="@xml/sync_options" />
--- a/mobile/android/base/resources/xml/sync_syncadapter.xml.in
+++ b/mobile/android/base/resources/xml/sync_syncadapter.xml.in
@@ -1,12 +1,12 @@
 #filter substitution
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
     android:contentAuthority="@ANDROID_PACKAGE_NAME@.db.browser"
-    android:accountType="org.mozilla.firefox_sync"
+    android:accountType="@MOZ_ANDROID_SHARED_ACCOUNT_TYPE@"
     android:supportsUploading="true"
     android:userVisible="true"
 />
--- a/mobile/android/base/sync/CommandProcessor.java
+++ b/mobile/android/base/sync/CommandProcessor.java
@@ -236,17 +236,17 @@ public class CommandProcessor {
     if (args.size() == 3) {
       title = args.get(2);
     }
 
     final String ns = Context.NOTIFICATION_SERVICE;
     final NotificationManager notificationManager = (NotificationManager) context.getSystemService(ns);
 
     // Create a Notificiation.
-    final int icon = R.drawable.sync_ic_launcher;
+    final int icon = R.drawable.icon;
     String notificationTitle = context.getString(R.string.sync_new_tab);
     if (title != null) {
       notificationTitle = notificationTitle.concat(": " + title);
     }
 
     final long when = System.currentTimeMillis();
     Notification notification = new Notification(icon, notificationTitle, when);
     notification.flags = Notification.FLAG_AUTO_CANCEL;
--- a/mobile/android/base/sync/GlobalConstants.java.in
+++ b/mobile/android/base/sync/GlobalConstants.java.in
@@ -11,9 +11,11 @@ package org.mozilla.gecko.sync;
 public class GlobalConstants {
   public static final String PRODUCT_NAME = "@MOZ_APP_DISPLAYNAME@";
   public static final String SYNC_VERSION_STRING = "1.@MOZ_APP_VERSION@.0";
 
   public static final String USER_AGENT = "Firefox AndroidSync " + SYNC_VERSION_STRING +
                                           " (" + PRODUCT_NAME + ")";
   public static final String BROWSER_INTENT_PACKAGE = "@ANDROID_PACKAGE_NAME@";
   public static final String BROWSER_INTENT_CLASS = BROWSER_INTENT_PACKAGE + ".App";
+
+  public static final String ACCOUNTTYPE_SYNC     = "@MOZ_ANDROID_SHARED_ACCOUNT_TYPE@";
 }
--- a/mobile/android/base/sync/Logger.java
+++ b/mobile/android/base/sync/Logger.java
@@ -36,17 +36,18 @@ public class Logger {
 
   /**
    * Default set of log writers to log to.
    */
   protected final static Set<LogWriter> defaultLogWriters() {
     final Set<LogWriter> defaultLogWriters = new LinkedHashSet<LogWriter>();
     LogWriter log = new AndroidLogWriter();
     LogWriter cache = new AndroidLevelCachingLogWriter(log);
-    LogWriter single = new SingleTagLogWriter(GLOBAL_LOG_TAG, cache);
+    final String processedPackage = GlobalConstants.BROWSER_INTENT_PACKAGE.replace("org.mozilla.", "");
+    LogWriter single = new SingleTagLogWriter(processedPackage, new SingleTagLogWriter(GLOBAL_LOG_TAG, cache));
     defaultLogWriters.add(single);
     return defaultLogWriters;
   }
 
   public static synchronized void startLoggingTo(LogWriter logWriter) {
     logWriters.add(logWriter);
   }
 
--- a/mobile/android/base/sync/StubActivity.java
+++ b/mobile/android/base/sync/StubActivity.java
@@ -1,22 +1,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync;
 
-import org.mozilla.gecko.R;
-
 import android.app.Activity;
 import android.os.Bundle;
 
 /*
  * Activity is just here for testing.
  */
 public class StubActivity extends Activity {
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
-      setContentView(R.layout.sync_stub);
   }
 }
--- a/mobile/android/base/sync/setup/Constants.java
+++ b/mobile/android/base/sync/setup/Constants.java
@@ -3,17 +3,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.setup;
 
 import android.content.Intent;
 
 public class Constants {
   // Constants for Firefox Sync SyncAdapter Accounts.
-  public static final String ACCOUNTTYPE_SYNC     = "org.mozilla.firefox_sync";
   public static final String OPTION_SYNCKEY       = "option.synckey";
   public static final String OPTION_USERNAME      = "option.username";
   public static final String AUTHTOKEN_TYPE_PLAIN = "auth.plain";
   public static final String OPTION_SERVER        = "option.serverUrl";
   public static final String ACCOUNT_GUID         = "account.guid";
   public static final String CLIENT_NAME          = "account.clientName";
   public static final String NUM_CLIENTS          = "account.numClients";
   public static final String DATA_ENABLE_ON_UPGRADE = "data.enableOnUpgrade";
--- a/mobile/android/base/sync/setup/SyncAccounts.java
+++ b/mobile/android/base/sync/setup/SyncAccounts.java
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.setup;
 
 import java.io.File;
 
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
+import org.mozilla.gecko.sync.GlobalConstants;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.SyncConfiguration;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.config.AccountPickler;
 import org.mozilla.gecko.sync.repositories.android.RepoUtils;
 import org.mozilla.gecko.sync.syncadapter.SyncAdapter;
 
 import android.accounts.Account;
@@ -45,17 +46,17 @@ public class SyncAccounts {
   /**
    * Returns true if a Sync account is set up, or we have a pickled Sync account
    * on disk that should be un-pickled (Bug 769745). If we have a pickled Sync
    * account, try to un-pickle it and create the corresponding Sync account.
    * <p>
    * Do not call this method from the main thread.
    */
   public static boolean syncAccountsExist(Context c) {
-    final boolean accountsExist = AccountManager.get(c).getAccountsByType(Constants.ACCOUNTTYPE_SYNC).length > 0;
+    final boolean accountsExist = AccountManager.get(c).getAccountsByType(GlobalConstants.ACCOUNTTYPE_SYNC).length > 0;
     if (accountsExist) {
       return true;
     }
 
     final File file = c.getFileStreamPath(Constants.ACCOUNT_PICKLE_FILENAME);
     if (!file.exists()) {
       return false;
     }
@@ -281,23 +282,23 @@ public class SyncAccounts {
     final String serverURL = (syncAccount.serverURL == null) ?
         DEFAULT_SERVER : syncAccount.serverURL;
 
     Logger.debug(LOG_TAG, "Using account manager " + accountManager);
     if (!RepoUtils.stringsEqual(syncAccount.serverURL, DEFAULT_SERVER)) {
       Logger.info(LOG_TAG, "Setting explicit server URL: " + serverURL);
     }
 
-    final Account account = new Account(username, Constants.ACCOUNTTYPE_SYNC);
+    final Account account = new Account(username, GlobalConstants.ACCOUNTTYPE_SYNC);
     final Bundle userbundle = new Bundle();
 
     // Add sync key and server URL.
     userbundle.putString(Constants.OPTION_SYNCKEY, syncKey);
     userbundle.putString(Constants.OPTION_SERVER, serverURL);
-    Logger.debug(LOG_TAG, "Adding account for " + Constants.ACCOUNTTYPE_SYNC);
+    Logger.debug(LOG_TAG, "Adding account for " + GlobalConstants.ACCOUNTTYPE_SYNC);
     boolean result = false;
     try {
       result = accountManager.addAccountExplicitly(account, password, userbundle);
     } catch (SecurityException e) {
       // We use Log rather than Logger here to avoid possibly hiding these errors.
       final String message = e.getMessage();
       if (message != null && (message.indexOf("is different than the authenticator's uid") > 0)) {
         Log.wtf(Logger.GLOBAL_LOG_TAG,
--- a/mobile/android/base/sync/setup/SyncAuthenticatorService.java
+++ b/mobile/android/base/sync/setup/SyncAuthenticatorService.java
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.setup;
 
 import java.io.UnsupportedEncodingException;
 import java.security.NoSuchAlgorithmException;
 
+import org.mozilla.gecko.sync.GlobalConstants;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.config.AccountPickler;
 import org.mozilla.gecko.sync.setup.activities.SetupSyncActivity;
 
 import android.accounts.AbstractAccountAuthenticator;
 import android.accounts.Account;
 import android.accounts.AccountAuthenticatorResponse;
@@ -58,17 +59,17 @@ public class SyncAuthenticatorService ex
     @Override
     public Bundle addAccount(AccountAuthenticatorResponse response,
         String accountType, String authTokenType, String[] requiredFeatures,
         Bundle options) throws NetworkErrorException {
       Logger.debug(LOG_TAG, "addAccount()");
       final Intent intent = new Intent(mContext, SetupSyncActivity.class);
       intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
                       response);
-      intent.putExtra("accountType", Constants.ACCOUNTTYPE_SYNC);
+      intent.putExtra("accountType", GlobalConstants.ACCOUNTTYPE_SYNC);
       intent.putExtra(Constants.INTENT_EXTRA_IS_SETUP, true);
 
       final Bundle result = new Bundle();
       result.putParcelable(AccountManager.KEY_INTENT, intent);
 
       return result;
     }
 
@@ -102,17 +103,17 @@ public class SyncAuthenticatorService ex
       // Extract the username and password from the Account Manager, and ask
       // the server for an appropriate AuthToken.
       final AccountManager am = AccountManager.get(mContext);
       final String password = am.getPassword(account);
       if (password != null) {
         final Bundle result = new Bundle();
 
         // This is a Sync account.
-        result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
+        result.putString(AccountManager.KEY_ACCOUNT_TYPE, GlobalConstants.ACCOUNTTYPE_SYNC);
 
         // Server.
         String serverURL = am.getUserData(account, Constants.OPTION_SERVER);
         result.putString(Constants.OPTION_SERVER, serverURL);
 
         // Full username, before hashing.
         result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
 
--- a/mobile/android/base/sync/setup/activities/AccountActivity.java
+++ b/mobile/android/base/sync/setup/activities/AccountActivity.java
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.setup.activities;
 
 import java.util.Locale;
 
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.sync.GlobalConstants;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.ThreadPool;
 import org.mozilla.gecko.sync.setup.Constants;
 import org.mozilla.gecko.sync.setup.InvalidSyncKeyException;
 import org.mozilla.gecko.sync.setup.SyncAccounts;
 import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
 import org.mozilla.gecko.sync.setup.auth.AccountAuthenticator;
 import org.mozilla.gecko.sync.setup.auth.AuthenticationResult;
@@ -259,18 +260,18 @@ public class AccountActivity extends Acc
           return;
         }
 
         // Account created successfully.
         clearErrors();
 
         Bundle resultBundle = new Bundle();
         resultBundle.putString(AccountManager.KEY_ACCOUNT_NAME, syncAccount.username);
-        resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
-        resultBundle.putString(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC);
+        resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, GlobalConstants.ACCOUNTTYPE_SYNC);
+        resultBundle.putString(AccountManager.KEY_AUTHTOKEN, GlobalConstants.ACCOUNTTYPE_SYNC);
         setAccountAuthenticatorResult(resultBundle);
 
         setResult(RESULT_OK);
         runOnUiThread(new Runnable() {
           @Override
           public void run() {
             authSuccess();
           }
--- a/mobile/android/base/sync/setup/activities/SendTabActivity.java
+++ b/mobile/android/base/sync/setup/activities/SendTabActivity.java
@@ -4,16 +4,17 @@
 
 package org.mozilla.gecko.sync.setup.activities;
 
 import java.util.List;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.sync.CommandProcessor;
 import org.mozilla.gecko.sync.CommandRunner;
+import org.mozilla.gecko.sync.GlobalConstants;
 import org.mozilla.gecko.sync.GlobalSession;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.repositories.NullCursorException;
 import org.mozilla.gecko.sync.repositories.android.ClientsDatabaseAccessor;
 import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
 import org.mozilla.gecko.sync.setup.Constants;
 import org.mozilla.gecko.sync.stage.SyncClientsEngineStage;
 import org.mozilla.gecko.sync.syncadapter.SyncAdapter;
@@ -82,17 +83,17 @@ public class SendTabActivity extends Act
       public void executeCommand(final GlobalSession session, List<String> args) {
         CommandProcessor.displayURI(args, session.getContext());
       }
     });
   }
 
   private void redirectIfNoSyncAccount() {
     accountManager = AccountManager.get(getApplicationContext());
-    Account[] accts = accountManager.getAccountsByType(Constants.ACCOUNTTYPE_SYNC);
+    Account[] accts = accountManager.getAccountsByType(GlobalConstants.ACCOUNTTYPE_SYNC);
 
     // A Sync account exists.
     if (accts.length > 0) {
       localAccount = accts[0];
       return;
     }
 
     Intent intent = new Intent(this, RedirectToSetupActivity.class);
--- a/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
+++ b/mobile/android/base/sync/setup/activities/SetupSyncActivity.java
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sync.setup.activities;
 
 import java.util.HashMap;
 
 import org.json.simple.JSONObject;
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.sync.GlobalConstants;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.ThreadPool;
 import org.mozilla.gecko.sync.jpake.JPakeClient;
 import org.mozilla.gecko.sync.jpake.JPakeNoActivePairingException;
 import org.mozilla.gecko.sync.setup.Constants;
 import org.mozilla.gecko.sync.setup.SyncAccounts;
 import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
 
@@ -45,19 +46,16 @@ public class SetupSyncActivity extends A
   // UI elements for pairing through PIN entry.
   private EditText            row1;
   private EditText            row2;
   private EditText            row3;
   private Button              connectButton;
   private LinearLayout        pinError;
 
   // UI elements for pairing through PIN generation.
-  private TextView            setupTitleView;
-  private TextView            setupNoDeviceLinkTitleView;
-  private TextView            setupSubtitleView;
   private TextView            pinTextView1;
   private TextView            pinTextView2;
   private TextView            pinTextView3;
   private JPakeClient         jClient;
 
   // Android context.
   private AccountManager      mAccountManager;
   private Context             mContext;
@@ -97,17 +95,17 @@ public class SetupSyncActivity extends A
       return;
     }
 
     // Check whether Sync accounts exist; if not, display J-PAKE PIN.
     // Run this on a separate thread to comply with Strict Mode thread policies.
     ThreadPool.run(new Runnable() {
       @Override
       public void run() {
-        Account[] accts = mAccountManager.getAccountsByType(Constants.ACCOUNTTYPE_SYNC);
+        Account[] accts = mAccountManager.getAccountsByType(GlobalConstants.ACCOUNTTYPE_SYNC);
         finishResume(accts);
       }
     });
   }
 
   public void finishResume(Account[] accts) {
     Logger.debug(LOG_TAG, "Finishing Resume after fetching accounts.");
 
@@ -335,17 +333,17 @@ public class SetupSyncActivity extends A
   }
 
   /**
    * Device has finished key exchange, waiting for remote device to set up or
    * link to a Sync account. Display "waiting for other device" dialog.
    */
   public void onPaired() {
     // Extract Sync account data.
-    Account[] accts = mAccountManager.getAccountsByType(Constants.ACCOUNTTYPE_SYNC);
+    Account[] accts = mAccountManager.getAccountsByType(GlobalConstants.ACCOUNTTYPE_SYNC);
     if (accts.length == 0) {
       // Error, no account present.
       Logger.error(LOG_TAG, "No accounts present.");
       displayAbort(Constants.JPAKE_ERROR_INVALID);
       return;
     }
 
     // TODO: Single account supported. Create account selection if spec changes.
@@ -419,18 +417,18 @@ public class SetupSyncActivity extends A
     ThreadPool.run(new Runnable() {
       @Override
       public void run() {
         Account account = SyncAccounts.createSyncAccount(syncAccount);
         boolean isSuccess = (account != null);
         if (isSuccess) {
           Bundle resultBundle = new Bundle();
           resultBundle.putString(AccountManager.KEY_ACCOUNT_NAME, syncAccount.username);
-          resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNTTYPE_SYNC);
-          resultBundle.putString(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNTTYPE_SYNC);
+          resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, GlobalConstants.ACCOUNTTYPE_SYNC);
+          resultBundle.putString(AccountManager.KEY_AUTHTOKEN, GlobalConstants.ACCOUNTTYPE_SYNC);
           setAccountAuthenticatorResult(resultBundle);
         }
         displayResultAndFinish(isSuccess);
       }
     });
   }
 
   /*
@@ -585,33 +583,19 @@ public class SetupSyncActivity extends A
     Logger.debug(LOG_TAG, "ReceiveNoPin initiated");
     runOnUiThread(new Runnable(){
 
       @Override
       public void run() {
         setContentView(R.layout.sync_setup);
 
         // Set up UI.
-        setupTitleView = ((TextView) findViewById(R.id.setup_title));
-        setupSubtitleView = (TextView) findViewById(R.id.setup_subtitle);
-        setupNoDeviceLinkTitleView = (TextView) findViewById(R.id.link_nodevice);
         pinTextView1 = ((TextView) findViewById(R.id.text_pin1));
         pinTextView2 = ((TextView) findViewById(R.id.text_pin2));
         pinTextView3 = ((TextView) findViewById(R.id.text_pin3));
-
-        // UI checks.
-        if (setupTitleView == null) {
-          Logger.error(LOG_TAG, "No title view.");
-        }
-        if (setupSubtitleView == null) {
-          Logger.error(LOG_TAG, "No subtitle view.");
-        }
-        if (setupNoDeviceLinkTitleView == null) {
-          Logger.error(LOG_TAG, "No 'no device' link view.");
-        }
       }
     });
   }
 
   @Override
   public void onActivityResult(int requestCode, int resultCode, Intent data) {
     switch (resultCode) {
     case Activity.RESULT_OK:
--- a/mobile/android/base/sync/syncadapter/SyncAdapter.java
+++ b/mobile/android/base/sync/syncadapter/SyncAdapter.java
@@ -44,17 +44,16 @@ import android.content.ContentResolver;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
 import android.content.SyncResult;
 import android.database.sqlite.SQLiteConstraintException;
 import android.database.sqlite.SQLiteException;
 import android.os.Bundle;
 import android.os.Handler;
-import android.util.Log;
 
 public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSessionCallback, ClientsDataDelegate {
   private static final String  LOG_TAG = "SyncAdapter";
 
   private static final String  PREFS_EARLIEST_NEXT_SYNC = "earliestnextsync";
   private static final String  PREFS_INVALIDATE_AUTH_TOKEN = "invalidateauthtoken";
   private static final String  PREFS_CLUSTER_URL_IS_STALE = "clusterurlisstale";
 
@@ -121,59 +120,59 @@ public class SyncAdapter extends Abstrac
     edit.putBoolean(PREFS_INVALIDATE_AUTH_TOKEN, true);
     edit.commit();
   }
 
   private void handleException(Exception e, SyncResult syncResult) {
     setShouldInvalidateAuthToken();
     try {
       if (e instanceof SQLiteConstraintException) {
-        Log.e(LOG_TAG, "Constraint exception. Aborting sync.", e);
+        Logger.error(LOG_TAG, "Constraint exception. Aborting sync.", e);
         syncResult.stats.numParseExceptions++;       // This is as good as we can do.
         return;
       }
       if (e instanceof SQLiteException) {
-        Log.e(LOG_TAG, "Couldn't open database (locked?). Aborting sync.", e);
+        Logger.error(LOG_TAG, "Couldn't open database (locked?). Aborting sync.", e);
         syncResult.stats.numIoExceptions++;
         return;
       }
       if (e instanceof OperationCanceledException) {
-        Log.e(LOG_TAG, "Operation canceled. Aborting sync.", e);
+        Logger.error(LOG_TAG, "Operation canceled. Aborting sync.", e);
         return;
       }
       if (e instanceof AuthenticatorException) {
         syncResult.stats.numParseExceptions++;
-        Log.e(LOG_TAG, "AuthenticatorException. Aborting sync.", e);
+        Logger.error(LOG_TAG, "AuthenticatorException. Aborting sync.", e);
         return;
       }
       if (e instanceof IOException) {
         syncResult.stats.numIoExceptions++;
-        Log.e(LOG_TAG, "IOException. Aborting sync.", e);
+        Logger.error(LOG_TAG, "IOException. Aborting sync.", e);
         e.printStackTrace();
         return;
       }
       syncResult.stats.numIoExceptions++;
-      Log.e(LOG_TAG, "Unknown exception. Aborting sync.", e);
+      Logger.error(LOG_TAG, "Unknown exception. Aborting sync.", e);
     } finally {
       notifyMonitor();
     }
   }
 
   private AccountManagerFuture<Bundle> getAuthToken(final Account account,
                             AccountManagerCallback<Bundle> callback,
                             Handler handler) {
     return mAccountManager.getAuthToken(account, Constants.AUTHTOKEN_TYPE_PLAIN, true, callback, handler);
   }
 
   private void invalidateAuthToken(Account account) {
     AccountManagerFuture<Bundle> future = getAuthToken(account, null, null);
     String token;
     try {
       token = future.getResult().getString(AccountManager.KEY_AUTHTOKEN);
-      mAccountManager.invalidateAuthToken(Constants.ACCOUNTTYPE_SYNC, token);
+      mAccountManager.invalidateAuthToken(GlobalConstants.ACCOUNTTYPE_SYNC, token);
     } catch (Exception e) {
       Logger.error(LOG_TAG, "Couldn't invalidate auth token: " + e);
     }
   }
 
   @Override
   public void onSyncCanceled() {
     super.onSyncCanceled();
@@ -258,29 +257,29 @@ public class SyncAdapter extends Abstrac
                             final SyncResult syncResult) {
     Logger.resetLogging();
     Utils.reseedSharedRandom(); // Make sure we don't work with the same random seed for too long.
 
     // Set these so that we don't need to thread them through assorted calls and callbacks.
     this.syncResult   = syncResult;
     this.localAccount = account;
 
-    Log.i(LOG_TAG,
+    Logger.info(LOG_TAG,
         "Syncing account named " + account.name +
         " for client named '" + getClientName() +
         "' with client guid " + getAccountGUID() +
         " (sync account has " + getClientsCount() + " clients).");
 
     thisSyncIsForced = (extras != null) && (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false));
     long delay = delayMilliseconds();
     if (delay > 0) {
       if (thisSyncIsForced) {
-        Log.i(LOG_TAG, "Forced sync: overruling remaining backoff of " + delay + "ms.");
+        Logger.info(LOG_TAG, "Forced sync: overruling remaining backoff of " + delay + "ms.");
       } else {
-        Log.i(LOG_TAG, "Not syncing: must wait another " + delay + "ms.");
+        Logger.info(LOG_TAG, "Not syncing: must wait another " + delay + "ms.");
         long remainingSeconds = delay / 1000;
         syncResult.delayUntil = remainingSeconds + BACKOFF_PAD_SECONDS;
         return;
       }
     }
 
     // TODO: don't clear the auth token unless we have a sync error.
     Logger.debug(LOG_TAG, "Got onPerformSync. Extras bundle is " + extras);
@@ -294,17 +293,17 @@ public class SyncAdapter extends Abstrac
     final AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
       @Override
       public void run(AccountManagerFuture<Bundle> future) {
         Logger.trace(LOG_TAG, "AccountManagerCallback invoked.");
         // TODO: N.B.: Future must not be used on the main thread.
         try {
           Bundle bundle = future.getResult(60L, TimeUnit.SECONDS);
           if (bundle.containsKey("KEY_INTENT")) {
-            Log.w(LOG_TAG, "KEY_INTENT included in AccountManagerFuture bundle. Problem?");
+            Logger.warn(LOG_TAG, "KEY_INTENT included in AccountManagerFuture bundle. Problem?");
           }
           String username  = bundle.getString(Constants.OPTION_USERNAME);
           String syncKey   = bundle.getString(Constants.OPTION_SYNCKEY);
           String serverURL = bundle.getString(Constants.OPTION_SERVER);
           String password  = bundle.getString(AccountManager.KEY_AUTHTOKEN);
           Logger.debug(LOG_TAG, "Username: " + username);
           Logger.debug(LOG_TAG, "Server:   " + serverURL);
           Logger.debug(LOG_TAG, "Password? " + (password != null));
@@ -327,24 +326,24 @@ public class SyncAdapter extends Abstrac
             syncResult.stats.numAuthExceptions++;
             localAccount = null;
             notifyMonitor();
             return;
           }
 
           // Now catch the individual cases.
           if (password == null) {
-            Log.e(LOG_TAG, "No password: aborting sync.");
+            Logger.error(LOG_TAG, "No password: aborting sync.");
             syncResult.stats.numAuthExceptions++;
             notifyMonitor();
             return;
           }
 
           if (syncKey == null) {
-            Log.e(LOG_TAG, "No Sync Key: aborting sync.");
+            Logger.error(LOG_TAG, "No Sync Key: aborting sync.");
             syncResult.stats.numAuthExceptions++;
             notifyMonitor();
             return;
           }
 
           // Support multiple accounts by mapping each server/account pair to a branch of the
           // shared preferences space.
           String prefsPath = Utils.getPrefsPath(username, serverURL);
@@ -374,21 +373,21 @@ public class SyncAdapter extends Abstrac
       ConnectionMonitorThread stale = new ConnectionMonitorThread();
       stale.start();
 
       Logger.trace(LOG_TAG, "Waiting on sync monitor.");
       try {
         syncMonitor.wait();
         long interval = getSyncInterval();
         long next = System.currentTimeMillis() + interval;
-        Log.i(LOG_TAG, "Setting minimum next sync time to " + next + " (" + interval + "ms from now).");
+        Logger.info(LOG_TAG, "Setting minimum next sync time to " + next + " (" + interval + "ms from now).");
         extendEarliestNextSync(next);
-        Log.i(LOG_TAG, "Sync took " + Utils.formatDuration(syncStartTimestamp, System.currentTimeMillis()) + ".");
+        Logger.info(LOG_TAG, "Sync took " + Utils.formatDuration(syncStartTimestamp, System.currentTimeMillis()) + ".");
       } catch (InterruptedException e) {
-        Log.w(LOG_TAG, "Waiting on sync monitor interrupted.", e);
+        Logger.warn(LOG_TAG, "Waiting on sync monitor interrupted.", e);
       } finally {
         // And we're done with HTTP stuff.
         stale.shutdown();
       }
     }
  }
 
   public int getSyncInterval() {
@@ -484,25 +483,25 @@ public class SyncAdapter extends Abstrac
       Logger.trace(LOG_TAG, "Notifying sync monitor.");
       syncMonitor.notifyAll();
     }
   }
 
   // Implementing GlobalSession callbacks.
   @Override
   public void handleError(GlobalSession globalSession, Exception ex) {
-    Log.i(LOG_TAG, "GlobalSession indicated error. Flagging auth token as invalid, just in case.");
+    Logger.info(LOG_TAG, "GlobalSession indicated error. Flagging auth token as invalid, just in case.");
     setShouldInvalidateAuthToken();
     this.updateStats(globalSession, ex);
     notifyMonitor();
   }
 
   @Override
   public void handleAborted(GlobalSession globalSession, String reason) {
-    Log.w(LOG_TAG, "Sync aborted: " + reason);
+    Logger.warn(LOG_TAG, "Sync aborted: " + reason);
     notifyMonitor();
   }
 
   /**
    * Introspect the exception, incrementing the appropriate stat counters.
    * TODO: increment number of inserts, deletes, conflicts.
    *
    * @param globalSession
@@ -514,17 +513,17 @@ public class SyncAdapter extends Abstrac
       ((SyncException) ex).updateStats(globalSession, syncResult);
     }
     // TODO: non-SyncExceptions.
     // TODO: wouldn't it be nice to update stats for *every* exception we get?
   }
 
   @Override
   public void handleSuccess(GlobalSession globalSession) {
-    Log.i(LOG_TAG, "GlobalSession indicated success.");
+    Logger.info(LOG_TAG, "GlobalSession indicated success.");
     Logger.debug(LOG_TAG, "Prefs target: " + globalSession.config.prefsPath);
     globalSession.config.persistToPrefs();
     notifyMonitor();
   }
 
   @Override
   public void handleStageCompleted(Stage currentState,
                                    GlobalSession globalSession) {
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -200,16 +200,26 @@ let AboutReader = {
 
     if (!this._toolbarEnabled)
       return;
 
     if (this._getToolbarVisibility() === visible)
       return;
 
     this._toolbarElement.classList.toggle("toolbar-hidden");
+
+    if (!visible && !this._hasUsedToolbar) {
+      this._hasUsedToolbar = Services.prefs.getBoolPref("reader.has_used_toolbar");
+      if (!this._hasUsedToolbar) {
+        gChromeWin.NativeWindow.toast.show(gStrings.GetStringFromName("aboutReader.toolbarTip"), "short");
+
+        Services.prefs.setBoolPref("reader.has_used_toolbar", true);
+        this._hasUsedToolbar = true;
+      }
+    }
   },
 
   _toggleToolbarVisibility: function Reader_toggleToolbarVisibility(visible) {
     this._setToolbarVisibility(!this._getToolbarVisibility());
   },
 
   _loadFromURL: function Reader_loadFromURL(url) {
     this._showProgress();
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1560,20 +1560,18 @@ var SelectionHandler = {
       case "Tab:Selected":
       case "Window:Resize": {
         // Knowing when the page is done drawing is hard, so let's just cancel
         // the selection when the window changes. We should fix this later.
         this.endSelection();
         break;
       }
       case "after-viewport-change": {
-        // Update the cache and reposition the handles after the viewport
-        // changes (e.g. panning, zooming).
+        // Update the cache after the viewport changes (e.g. panning, zooming).
         this.updateCacheForSelection();
-        this.positionHandles();
         break;
       }
       case "TextSelection:Move": {
         let data = JSON.parse(aData);
         this.moveSelection(data.handleType == this.HANDLE_TYPE_START, data.x, data.y);
         break;
       }
       case "TextSelection:Position": {
@@ -1866,23 +1864,25 @@ var SelectionHandler = {
 
     return selectionReversed;
   },
 
   positionHandles: function sh_positionHandles() {
     // Translate coordinates to account for selections in sub-frames. We can't cache
     // this because the top-level page may have scrolled since selection started.
     let offset = this._getViewOffset();
+    let scrollX = {}, scrollY = {};
+    this._view.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).getScrollXY(false, scrollX, scrollY);
     sendMessageToJava({
       gecko: {
         type: "TextSelection:PositionHandles",
-        startLeft: this.cache.start.x + offset.x,
-        startTop: this.cache.start.y + offset.y,
-        endLeft: this.cache.end.x + offset.x,
-        endTop: this.cache.end.y + offset.y
+        startLeft: this.cache.start.x + offset.x + scrollX.value,
+        startTop: this.cache.start.y + offset.y + scrollY.value,
+        endLeft: this.cache.end.x + offset.x + scrollX.value,
+        endTop: this.cache.end.y + offset.y + scrollY.value
       }
     });
   },
 
   showHandles: function sh_showHandles() {
     this.positionHandles();
 
     sendMessageToJava({
--- a/mobile/android/locales/en-US/chrome/aboutReader.properties
+++ b/mobile/android/locales/en-US/chrome/aboutReader.properties
@@ -6,8 +6,10 @@ aboutReader.loading=Loading...
 aboutReader.loadError=Failed to load article from page
 
 aboutReader.textTitle=Text
 aboutReader.marginTitle=Margins
 
 aboutReader.colorSchemeLight=Light
 aboutReader.colorSchemeDark=Dark
 aboutReader.colorSchemeSepia=Sepia
+
+aboutReader.toolbarTip=Tap the screen to show reader options
--- a/mobile/android/sync/android-drawable-hdpi-resources.mn
+++ b/mobile/android/sync/android-drawable-hdpi-resources.mn
@@ -1,2 +0,0 @@
-mobile/android/base/resources/drawable-hdpi/sync_fx_icon.png
-mobile/android/base/resources/drawable-hdpi/sync_ic_launcher.png
--- a/mobile/android/sync/android-drawable-ldpi-resources.mn
+++ b/mobile/android/sync/android-drawable-ldpi-resources.mn
@@ -1,2 +0,0 @@
-mobile/android/base/resources/drawable-ldpi/sync_fx_icon.png
-mobile/android/base/resources/drawable-ldpi/sync_ic_launcher.png
--- a/mobile/android/sync/android-drawable-mdpi-resources.mn
+++ b/mobile/android/sync/android-drawable-mdpi-resources.mn
@@ -1,2 +0,0 @@
-mobile/android/base/resources/drawable-mdpi/sync_fx_icon.png
-mobile/android/base/resources/drawable-mdpi/sync_ic_launcher.png
--- a/mobile/android/sync/android-drawable-resources.mn
+++ b/mobile/android/sync/android-drawable-resources.mn
@@ -1,4 +1,3 @@
 mobile/android/base/resources/drawable/desktop.png
 mobile/android/base/resources/drawable/mobile.png
 mobile/android/base/resources/drawable/pin_background.xml
-mobile/android/base/resources/drawable/sync_ic_launcher.png
--- a/mobile/android/sync/android-layout-resources.mn
+++ b/mobile/android/sync/android-layout-resources.mn
@@ -3,9 +3,8 @@ res/layout/sync_list_item.xml
 res/layout/sync_redirect_to_setup.xml
 res/layout/sync_send_tab.xml
 res/layout/sync_setup.xml
 res/layout/sync_setup_failure.xml
 res/layout/sync_setup_jpake_waiting.xml
 res/layout/sync_setup_nointernet.xml
 res/layout/sync_setup_pair.xml
 res/layout/sync_setup_success.xml
-res/layout/sync_stub.xml
--- a/mobile/android/sync/manifests/SyncAndroidManifest_activities.xml.in
+++ b/mobile/android/sync/manifests/SyncAndroidManifest_activities.xml.in
@@ -1,10 +1,10 @@
         <activity
-            android:icon="@drawable/sync_ic_launcher"
+            android:icon="@drawable/icon"
             android:label="@string/sync_app_name"
             android:configChanges="keyboardHidden|orientation|screenSize"
             android:windowSoftInputMode="adjustResize|stateHidden"
             android:taskAffinity="org.mozilla.gecko.sync.setup"
             android:name="org.mozilla.gecko.sync.setup.activities.SetupSyncActivity" >
             <!-- android:configChanges: SetupSyncActivity will handle orientation changes; no longer restarts activity (default) -->
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -32,17 +32,17 @@
         <receiver
             android:name="org.mozilla.gecko.sync.receivers.UpgradeReceiver">
             <intent-filter>
                 <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
             </intent-filter>
         </receiver>
 
         <activity
-            android:icon="@drawable/sync_ic_launcher"
+            android:icon="@drawable/icon"
             android:label="@string/sync_app_name"
             android:configChanges="orientation"
             android:windowSoftInputMode="adjustResize|stateHidden"
             android:taskAffinity="org.mozilla.gecko.sync.setup"
             android:name="org.mozilla.gecko.sync.setup.activities.SendTabActivity" >
 
             <intent-filter>
                 <action android:name="android.intent.action.SEND" />
--- a/netwerk/base/public/nsIAuthModule.idl
+++ b/netwerk/base/public/nsIAuthModule.idl
@@ -1,15 +1,15 @@
 /* vim:set ts=4 sw=4 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
-[uuid(6e35dbc0-49ef-4e2c-b1ea-b72ec64450a2)]
+[uuid(fb82a326-1311-4c45-b5b3-84eb883d4b70)]
 interface nsIAuthModule : nsISupports
 {
     /**
      * Default behavior.
      */
     const unsigned long REQ_DEFAULT = 0;
 
     /**
@@ -111,16 +111,23 @@ interface nsIAuthModule : nsISupports
      *
      * Unwrap() may return NS_ERROR_NOT_IMPLEMENTED, if the underlying  
      * authentication mechanism does not support security layers.
      */
     void unwrap([const] in voidPtr aInToken,
                 in unsigned long   aInTokenLength,
                 out voidPtr        aOutToken,
                 out unsigned long  aOutTokenLength);
+
+    /* Flags defining various properties of the auth module. */
+    readonly attribute unsigned long moduleProperties;
+
+    /* The service name in Init() is required to be the Canonical DNS
+       name for that host */
+    const unsigned long CANONICAL_NAME_REQUIRED = (1<<0);
 };
 
 %{C++
 /**
  * nsIAuthModule implementations are registered under the following contract
  * ID prefix:
  */
 #define NS_AUTH_MODULE_CONTRACTID_PREFIX \
--- a/netwerk/cache/nsDeleteDir.cpp
+++ b/netwerk/cache/nsDeleteDir.cpp
@@ -174,18 +174,26 @@ nsDeleteDir::TimerCallback(nsITimer *aTi
 
     gInstance->mTimers.RemoveObjectAt(idx);
   }
 
   nsAutoPtr<nsCOMArray<nsIFile> > dirList;
   dirList = static_cast<nsCOMArray<nsIFile> *>(arg);
 
   bool shuttingDown = false;
-  for (PRInt32 i = 0; i < dirList->Count() && !shuttingDown; i++) {
-    gInstance->RemoveDir((*dirList)[i], &shuttingDown);
+
+  // Intentional extra braces to control variable sope.
+  {
+    // Low IO priority can only be set when running in the context of the
+    // current thread.  So this shouldn't be moved to where we set the priority
+    // of the Cache deleter thread using the nsThread's NSPR priority constants.
+    nsAutoLowPriorityIO autoLowPriority;
+    for (PRInt32 i = 0; i < dirList->Count() && !shuttingDown; i++) {
+      gInstance->RemoveDir((*dirList)[i], &shuttingDown);
+    }
   }
 
   {
     MutexAutoLock lock(gInstance->mLock);
     gInstance->DestroyThread();
   }
 }
 
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -4214,16 +4214,29 @@ NS_IMETHODIMP nsHttpChannel::OnAuthCance
 
         if (NS_FAILED(rv))
             mTransactionPump->Cancel(rv);
     }
     
     return NS_OK;
 }
 
+NS_IMETHODIMP nsHttpChannel::GetAsciiHostForAuth(nsACString &host)
+{
+    if (mAuthProvider)
+        return mAuthProvider->GetAsciiHostForAuth(host);
+
+    nsresult rv;
+    nsCOMPtr<nsIURI> uri;
+    rv = GetURI(getter_AddRefs(uri));
+    if (NS_FAILED(rv))
+        return rv;
+    return uri->GetAsciiHost(host);
+}
+
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsISupports
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ADDREF_INHERITED(nsHttpChannel, HttpBaseChannel)
 NS_IMPL_RELEASE_INHERITED(nsHttpChannel, HttpBaseChannel)
 
 NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -77,16 +77,17 @@ public:
     NS_IMETHOD GetProxyMethodIsConnect(bool *aProxyMethodIsConnect);
     NS_IMETHOD GetServerResponseHeader(nsACString & aServerResponseHeader);
     NS_IMETHOD GetProxyChallenges(nsACString & aChallenges);
     NS_IMETHOD GetWWWChallenges(nsACString & aChallenges);
     NS_IMETHOD SetProxyCredentials(const nsACString & aCredentials);
     NS_IMETHOD SetWWWCredentials(const nsACString & aCredentials);
     NS_IMETHOD OnAuthAvailable();
     NS_IMETHOD OnAuthCancelled(bool userCancel);
+    NS_IMETHOD GetAsciiHostForAuth(nsACString &aHost);
     // Functions we implement from nsIHttpAuthenticableChannel but are
     // declared in HttpBaseChannel must be implemented in this class. We
     // just call the HttpBaseChannel:: impls.
     NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags);
     NS_IMETHOD GetURI(nsIURI **aURI);
     NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks);
     NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
     NS_IMETHOD GetRequestMethod(nsACString& aMethod);
--- a/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
+++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.cpp
@@ -11,25 +11,30 @@
 #include "nsIAuthPrompt2.h"
 #include "nsIAuthPromptProvider.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsEscape.h"
 #include "nsAuthInformationHolder.h"
 #include "nsIStringBundle.h"
 #include "nsIPrompt.h"
+#include "nsIAuthModule.h"
+#include "nsIDNSService.h"
+#include "nsNetCID.h"
+#include "nsIDNSRecord.h"
 
 nsHttpChannelAuthProvider::nsHttpChannelAuthProvider()
     : mAuthChannel(nsnull)
     , mProxyAuthContinuationState(nsnull)
     , mAuthContinuationState(nsnull)
     , mProxyAuth(false)
     , mTriedProxyAuth(false)
     , mTriedHostAuth(false)
     , mSuppressDefensiveAuth(false)
+    , mResolvedHost(0)
 {
     // grab a reference to the handler to ensure that it doesn't go away.
     nsHttpHandler *handler = gHttpHandler;
     NS_ADDREF(handler);
 }
 
 nsHttpChannelAuthProvider::~nsHttpChannelAuthProvider()
 {
@@ -70,16 +75,19 @@ NS_IMETHODIMP
 nsHttpChannelAuthProvider::ProcessAuthentication(PRUint32 httpStatus,
                                                  bool     SSLConnectFailed)
 {
     LOG(("nsHttpChannelAuthProvider::ProcessAuthentication "
          "[this=%p channel=%p code=%u SSLConnectFailed=%d]\n",
          this, mAuthChannel, httpStatus, SSLConnectFailed));
 
     NS_ASSERTION(mAuthChannel, "Channel not initialized");
+    
+    mCanonicalizedHost.Truncate();
+    mResolvedHost = 0;
 
     nsCOMPtr<nsIProxyInfo> proxyInfo;
     nsresult rv = mAuthChannel->GetProxyInfo(getter_AddRefs(proxyInfo));
     if (NS_FAILED(rv)) return rv;
     if (proxyInfo) {
         mProxyInfo = do_QueryInterface(proxyInfo);
         if (!mProxyInfo) return NS_ERROR_NO_INTERFACE;
     }
@@ -219,28 +227,36 @@ NS_IMETHODIMP
 nsHttpChannelAuthProvider::Cancel(nsresult status)
 {
     NS_ASSERTION(mAuthChannel, "Channel not initialized");
 
     if (mAsyncPromptAuthCancelable) {
         mAsyncPromptAuthCancelable->Cancel(status);
         mAsyncPromptAuthCancelable = nsnull;
     }
+    if (mDNSQuery) {
+        mDNSQuery->Cancel(status);
+        mDNSQuery = nsnull;
+    }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHttpChannelAuthProvider::Disconnect(nsresult status)
 {
     mAuthChannel = nsnull;
 
     if (mAsyncPromptAuthCancelable) {
         mAsyncPromptAuthCancelable->Cancel(status);
         mAsyncPromptAuthCancelable = nsnull;
     }
+    if (mDNSQuery) {
+        mDNSQuery->Cancel(status);
+        mDNSQuery = nsnull;
+    }
 
     NS_IF_RELEASE(mProxyAuthContinuationState);
     NS_IF_RELEASE(mAuthContinuationState);
 
     return NS_OK;
 }
 
 // buf contains "domain\user"
@@ -421,16 +437,68 @@ nsHttpChannelAuthProvider::PrepareForAut
             if (NS_FAILED(rv)) return rv;
             LOG(("  cleared proxy authorization header"));
         }
     }
 
     return NS_OK;
 }
 
+bool
+nsHttpChannelAuthProvider::AuthModuleRequiresCanonicalName(nsISupports *state)
+{
+    if (mResolvedHost || !state)
+        return false;
+
+    nsCOMPtr<nsIAuthModule> module = do_QueryInterface(state);
+    if (!module)
+        return false;
+
+    PRUint32 flags;
+    if (NS_FAILED(module->GetModuleProperties(&flags)))
+        return false;
+
+    if (!(flags & nsIAuthModule::CANONICAL_NAME_REQUIRED))
+        return false;
+    
+    LOG(("nsHttpChannelAuthProvider::AuthModuleRequiresCanoncialName "
+         "this=%p\n", this));
+    return true;
+}
+
+nsresult
+nsHttpChannelAuthProvider::ResolveHost()
+{
+    mResolvedHost = 1;
+
+    nsresult rv;
+    static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID);
+        nsCOMPtr<nsIDNSService> dns = do_GetService(kDNSServiceCID, &rv);
+    if (NS_FAILED(rv))
+        return rv;
+
+    nsCOMPtr<nsIURI> uri;
+    rv = mAuthChannel->GetURI(getter_AddRefs(uri));
+    if (NS_FAILED(rv))
+        return rv;
+    nsCAutoString host;
+    rv = uri->GetAsciiHost(host);
+    if (NS_FAILED(rv))
+        return rv;
+
+    LOG(("nsHttpChannelAuthProvider::ResolveHost() this=%p "
+         "looking up canoncial of %s\n", this, host.get()));
+    nsRefPtr<DNSCallback> dnsCallback = new DNSCallback(this);
+    rv = dns->AsyncResolve(host,
+                           nsIDNSService::RESOLVE_CANONICAL_NAME,
+                           dnsCallback, NS_GetCurrentThread(),
+                           getter_AddRefs(mDNSQuery));
+    return rv;
+}
+
 nsresult
 nsHttpChannelAuthProvider::GetCredentials(const char     *challenges,
                                           bool            proxyAuth,
                                           nsAFlatCString &creds)
 {
     nsCOMPtr<nsIHttpAuthenticator> auth;
     nsCAutoString challenge;
 
@@ -709,16 +777,23 @@ nsHttpChannelAuthProvider::GetCredential
             // this return code alone is not equivalent to Cancel, since
             // it only instructs our caller that authentication failed.
             // without an explicit call to Cancel, our caller would just
             // load the page that accompanies the HTTP auth challenge.
             return NS_ERROR_ABORT;
         }
     }
 
+    if (AuthModuleRequiresCanonicalName(*continuationState)) {
+        nsresult rv = ResolveHost();
+        if (NS_SUCCEEDED(rv))
+            return NS_ERROR_IN_PROGRESS;
+        return rv;
+    }
+
     //
     // get credentials for the given user:pass
     //
     // always store the credentials we're trying now so that they will be used
     // on subsequent links.  This will potentially remove good credentials from
     // the cache.  This is ok as we don't want to use cached credentials if the
     // user specified something on the URI or in another manner.  This is so
     // that we don't transparently authenticate as someone they're not
@@ -974,19 +1049,28 @@ NS_IMETHODIMP nsHttpChannelAuthProvider:
                                      realm.get(), &entry);
 
     nsCOMPtr<nsISupports> sessionStateGrip;
     if (entry)
         sessionStateGrip = entry->mMetaData;
 
     nsAuthInformationHolder* holder =
             static_cast<nsAuthInformationHolder*>(aAuthInfo);
-    ident->Set(holder->Domain().get(),
-               holder->User().get(),
-               holder->Password().get());
+    if (holder) {
+        ident->Set(holder->Domain().get(),
+                   holder->User().get(),
+                   holder->Password().get());
+    }
+
+    if (AuthModuleRequiresCanonicalName(*continuationState)) {
+        rv = ResolveHost();
+        if (NS_FAILED(rv))
+            OnAuthCancelled(aContext, true);
+        return NS_OK;
+    }
 
     nsCAutoString unused;
     nsCOMPtr<nsIHttpAuthenticator> auth;
     rv = GetAuthenticator(mCurrentChallenge.get(), unused,
                           getter_AddRefs(auth));
     if (NS_FAILED(rv)) {
         NS_ASSERTION(false, "GetAuthenticator failed");
         OnAuthCancelled(aContext, true);
@@ -1268,10 +1352,59 @@ nsHttpChannelAuthProvider::GetCurrentPat
     nsCOMPtr<nsIURL> url = do_QueryInterface(mURI);
     if (url)
         rv = url->GetDirectory(path);
     else
         rv = mURI->GetPath(path);
     return rv;
 }
 
+nsresult
+nsHttpChannelAuthProvider::GetAsciiHostForAuth(nsACString &host)
+{
+    if (!mCanonicalizedHost.IsEmpty()) {
+        LOG(("nsHttpChannelAuthProvider::GetAsciiHostForAuth"
+             " this=%p host is %s\n", this, mCanonicalizedHost.get()));
+        host = mCanonicalizedHost;
+        return NS_OK;
+    }
+    
+    // fallback
+    nsresult rv;
+    nsCOMPtr<nsIURI> uri;
+    rv = mAuthChannel->GetURI(getter_AddRefs(uri));
+    if (NS_FAILED(rv))
+        return rv;
+    return uri->GetAsciiHost(host);
+}
+
+NS_IMETHODIMP
+nsHttpChannelAuthProvider::DNSCallback::OnLookupComplete(nsICancelable *request,
+                                                         nsIDNSRecord  *record,
+                                                         nsresult       rv)
+{
+    nsCString cname;
+    mAuthProvider->SetDNSQuery(nsnull);
+
+    LOG(("nsHttpChannelAuthProvider::OnLookupComplete this=%p "
+         "rv=%X\n", mAuthProvider.get(), rv));
+
+    if (NS_SUCCEEDED(rv))
+        rv = record->GetCanonicalName(cname);
+
+    if (NS_SUCCEEDED(rv)) {
+        LOG(("nsHttpChannelAuthProvider::OnLookupComplete this=%p "
+             "resolved to %s\n", mAuthProvider.get(), cname.get()));
+        mAuthProvider->SetCanonicalizedHost(cname);
+        mAuthProvider->OnAuthAvailable(nsnull, nsnull);
+    }
+    else {
+        LOG(("nsHttpChannelAuthProvider::OnLookupComplete this=%p "
+             "GetCanonicalName failed\n", mAuthProvider.get()));
+        mAuthProvider->OnAuthCancelled(nsnull, false);
+    }
+    return NS_OK;
+}
+
 NS_IMPL_ISUPPORTS3(nsHttpChannelAuthProvider, nsICancelable,
                    nsIHttpChannelAuthProvider, nsIAuthPromptCallback)
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsHttpChannelAuthProvider::DNSCallback,
+                              nsIDNSListener)
--- a/netwerk/protocol/http/nsHttpChannelAuthProvider.h
+++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.h
@@ -11,16 +11,17 @@
 #include "nsIHttpChannelAuthProvider.h"
 #include "nsIAuthPromptCallback.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIHttpAuthenticableChannel.h"
 #include "nsIURI.h"
 #include "nsHttpAuthCache.h"
 #include "nsProxyInfo.h"
+#include "nsIDNSListener.h"
 
 class nsIHttpAuthenticator;
 
 class nsHttpChannelAuthProvider : public nsIHttpChannelAuthProvider
                                 , public nsIAuthPromptCallback
 {
 public:
     NS_DECL_ISUPPORTS
@@ -51,16 +52,19 @@ private:
                                  PRInt32 port, const char *dir,
                                  const char *realm, const char *challenge,
                                  const nsHttpAuthIdentity &ident,
                                  nsCOMPtr<nsISupports> &session, char **result);
     nsresult GetAuthenticator(const char *challenge, nsCString &scheme,
                               nsIHttpAuthenticator **auth);
     void     ParseRealm(const char *challenge, nsACString &realm);
     void     GetIdentityFromURI(PRUint32 authFlags, nsHttpAuthIdentity&);
+    bool     AuthModuleRequiresCanonicalName(nsISupports *state);
+    nsresult ResolveHost();
+
     /**
      * Following three methods return NS_ERROR_IN_PROGRESS when
      * nsIAuthPrompt2.asyncPromptAuth method is called. This result indicates
      * the user's decision will be gathered in a callback and is not an actual
      * error.
      */
     nsresult GetCredentials(const char *challenges, bool proxyAuth,
                             nsAFlatCString &creds);
@@ -100,22 +104,26 @@ private:
     /**
      * A function that takes care of reading STS headers and enforcing STS 
      * load rules.  After a secure channel is erected, STS requires the channel
      * to be trusted or any STS header data on the channel is ignored.
      * This is called from ProcessResponse.
      */
     nsresult ProcessSTSHeader();
 
+    void SetDNSQuery(nsICancelable *aQuery) { mDNSQuery = aQuery; }
+    void SetCanonicalizedHost(nsACString &aHost) { mCanonicalizedHost = aHost; }
+
 private:
     nsIHttpAuthenticableChannel      *mAuthChannel;  // weak ref
 
     nsCOMPtr<nsIURI>                  mURI;
     nsCOMPtr<nsProxyInfo>             mProxyInfo;
     nsCString                         mHost;
+    nsCString                         mCanonicalizedHost;
     PRInt32                           mPort;
     bool                              mUsingSSL;
 
     nsISupports                      *mProxyAuthContinuationState;
     nsCString                         mProxyAuthType;
     nsISupports                      *mAuthContinuationState;
     nsCString                         mAuthType;
     nsHttpAuthIdentity                mIdent;
@@ -135,11 +143,27 @@ private:
     nsCString                         mRemainingChallenges;
 
     // True when we need to authenticate to proxy, i.e. when we get 407
     // response. Used in OnAuthAvailable and OnAuthCancelled callbacks.
     PRUint32                          mProxyAuth                : 1;
     PRUint32                          mTriedProxyAuth           : 1;
     PRUint32                          mTriedHostAuth            : 1;
     PRUint32                          mSuppressDefensiveAuth    : 1;
+    PRUint32                          mResolvedHost             : 1;
+
+    // define a separate threadsafe class for use with the DNS callback
+    class DNSCallback : public nsIDNSListener
+    {
+        NS_DECL_ISUPPORTS
+        NS_DECL_NSIDNSLISTENER
+
+        DNSCallback(nsHttpChannelAuthProvider *authProvider)
+            : mAuthProvider(authProvider)
+        { }
+
+    private:
+        nsRefPtr<nsHttpChannelAuthProvider> mAuthProvider;
+    };
+    nsCOMPtr<nsICancelable>          mDNSQuery;
 };
 
 #endif // nsHttpChannelAuthProvider_h__
--- a/netwerk/protocol/http/nsHttpNTLMAuth.cpp
+++ b/netwerk/protocol/http/nsHttpNTLMAuth.cpp
@@ -346,22 +346,18 @@ nsHttpNTLMAuth::GenerateCredentials(nsIH
     NS_ENSURE_SUCCESS(rv, rv);
 
     void *inBuf, *outBuf;
     PRUint32 inBufLen, outBufLen;
 
     // initial challenge
     if (PL_strcasecmp(challenge, "NTLM") == 0) {
         // NTLM service name format is 'HTTP@host' for both http and https
-        nsCOMPtr<nsIURI> uri;
-        rv = authChannel->GetURI(getter_AddRefs(uri));
-        if (NS_FAILED(rv))
-            return rv;
         nsCAutoString serviceName, host;
-        rv = uri->GetAsciiHost(host);
+        rv = authChannel->GetAsciiHostForAuth(host);
         if (NS_FAILED(rv))
             return rv;
         serviceName.AppendLiteral("HTTP@");
         serviceName.Append(host);
         // initialize auth module
         rv = module->Init(serviceName.get(), nsIAuthModule::REQ_DEFAULT, domain, user, pass);
         if (NS_FAILED(rv))
             return rv;
--- a/netwerk/protocol/http/nsIHttpAuthenticableChannel.idl
+++ b/netwerk/protocol/http/nsIHttpAuthenticableChannel.idl
@@ -5,17 +5,17 @@
 
 #include "nsIProxiedChannel.idl"
 #include "nsIChannel.idl"
 
 interface nsILoadGroup;
 interface nsIURI;
 interface nsIInterfaceRequestor;
 
-[scriptable, uuid(701093ac-5c7f-429c-99e3-423b041fccb4)]
+[scriptable, uuid(ea5f7698-c4e4-48fd-aa54-6fdcf1dc349b)]
 interface nsIHttpAuthenticableChannel : nsIProxiedChannel
 {
     /**
      * If the channel being authenticated is using SSL.
      */
     readonly attribute boolean isSSL;
     
     /**
@@ -67,16 +67,21 @@ interface nsIHttpAuthenticableChannel : 
     readonly attribute ACString proxyChallenges;
 
     /**
      * The WWW-Authenticate response header.
      */
     readonly attribute ACString WWWChallenges;
 
     /**
+     * The host portion of the URI, possibly canonicalized
+     */
+    readonly attribute ACString asciiHostForAuth;
+
+    /**
      * Sets the Proxy-Authorization request header. An empty string 
      * will clear it.
      */
     void setProxyCredentials(in ACString credentials);
 
     /**
      * Sets the Authorization request header. An empty string
      * will clear it.
--- a/netwerk/protocol/http/nsIHttpChannelAuthProvider.idl
+++ b/netwerk/protocol/http/nsIHttpChannelAuthProvider.idl
@@ -20,40 +20,38 @@ interface nsIHttpAuthenticableChannel;
  * in order to get the http cached headers credentials. When the request is
  * unsuccessful because of receiving either a 401 or 407 http response code
  * ProcessAuthentication MUST be called and the page MUST be requested again
  * with the new credentials that the user has provided. After a successful
  * request, checkForSuperfluousAuth MAY be called, and disconnect MUST be
  * called.
  */
 
-[scriptable, uuid(c68f3def-c7c8-4ee8-861c-eef49a48b702)]
+[scriptable, uuid(1b74d211-8980-42d4-b0ce-caafa73f4a0f)]
 interface nsIHttpChannelAuthProvider : nsICancelable
 {
   /**
    * Initializes the http authentication support for the channel.
    * Implementations must hold a weak reference of the channel.
    */
   void init(in nsIHttpAuthenticableChannel channel);
 
   /**
    * Upon receipt of a server challenge, this function is called to determine
    * the credentials to send.
    *
    * @param httpStatus
    *        the http status received.
    * @param sslConnectFailed
    *        if the last ssl tunnel connection attempt was or not successful.
-   * @param callback
-   *        the callback to be called when it returns NS_ERROR_IN_PROGRESS.
-   *        The implementation must hold a weak reference.
    *
    * @returns NS_OK if the credentials were got and set successfully.
    *          NS_ERROR_IN_PROGRESS if the credentials are going to be asked to
-   *                               the user. The channel reference must be
+   *                               the user or other blocking event such as DNS
+   *                               is incurred. The channel reference must be
    *                               alive until the feedback from
    *                               nsIHttpAuthenticableChannel's methods or
    *                               until disconnect be called.
    */
   void processAuthentication(in unsigned long httpStatus,
                              in boolean sslConnectFailed);
 
   /**
@@ -63,13 +61,18 @@ interface nsIHttpChannelAuthProvider : n
 
   /**
    * Check if an unnecessary(and maybe malicious) url authentication has been
    * provided.
    */
   void checkForSuperfluousAuth();
 
   /**
-   * Cancel pending user auth prompts and release the callback and channel
-   * weak references.
+   * Cancel pending user auth prompts and release the channel
+   * weak reference.
    */
   void disconnect(in nsresult status);
+
+  /**
+   * The host portion of the URI, possibly canonicalized
+   */
+  readonly attribute ACString asciiHostForAuth;
 };
--- a/security/manager/ssl/src/nsNTLMAuthModule.cpp
+++ b/security/manager/ssl/src/nsNTLMAuthModule.cpp
@@ -826,16 +826,23 @@ nsNTLMAuthModule::Wrap(const void *inTok
                        PRUint32    inTokenLen,
                        bool        confidential,
                        void      **outToken,
                        PRUint32   *outTokenLen)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+nsNTLMAuthModule::GetModuleProperties(PRUint32 *flags)
+{
+    *flags = 0;
+    return NS_OK;
+}
+
 //-----------------------------------------------------------------------------
 // DES support code
 
 // set odd parity bit (in least significant bit position)
 static PRUint8
 des_setkeyparity(PRUint8 x)
 {
   if ((((x >> 7) ^ (x >> 6) ^ (x >> 5) ^
--- a/toolkit/xre/nsWindowsDllBlocklist.cpp
+++ b/toolkit/xre/nsWindowsDllBlocklist.cpp
@@ -14,16 +14,17 @@
 #include "nsXULAppAPI.h"
 
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
 
 #include "prlog.h"
 
 #include "nsWindowsDllInterceptor.h"
+#include "nsWindowsHelpers.h"
 
 using namespace mozilla;
 
 #if defined(MOZ_CRASHREPORTER) && !defined(NO_BLOCKLIST_CRASHREPORTER)
 #include "nsExceptionHandler.h"
 #endif
 
 #define ALL_VERSIONS   ((unsigned long long)-1LL)
@@ -151,28 +152,16 @@ struct RVAMap {
   operator const T*() const { return mMappedView; }
   const T* operator->() const { return mMappedView; }
 private:
   const T* mMappedView;
   void* mRealView;
 };
 
 bool
-IsVistaOrLater()
-{
-  OSVERSIONINFO info;
-
-  ZeroMemory(&info, sizeof(OSVERSIONINFO));
-  info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-  GetVersionEx(&info);
-
-  return info.dwMajorVersion >= 6;
-}
-
-bool
 CheckASLR(const wchar_t* path)
 {
   bool retval = false;
 
   HANDLE file = ::CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
                               NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                               NULL);
   if (file != INVALID_HANDLE_VALUE) {
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -1944,59 +1944,59 @@ public:
     // respective functions in GCGraphBuilder.
     NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child);
     NS_IMETHOD_(void) NoteNativeChild(void *child,
                                       nsCycleCollectionParticipant *helper);
     NS_IMETHOD_(void) NoteJSChild(void *child);
 
     NS_IMETHOD_(void) DescribeRefCountedNode(nsrefcnt refcount,
                                              size_t objsz,
-                                             const char *objname) {};
+                                             const char *objname) {}
     NS_IMETHOD_(void) DescribeGCedNode(bool ismarked,
                                        size_t objsz,
-                                       const char *objname) {};
-    NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root) {};
-    NS_IMETHOD_(void) NoteJSRoot(void *root) {};
+                                       const char *objname) {}
+    NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root) {}
+    NS_IMETHOD_(void) NoteJSRoot(void *root) {}
     NS_IMETHOD_(void) NoteNativeRoot(void *root,
-                                     nsCycleCollectionParticipant *helper) {};
-    NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {};
-    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) {};
+                                     nsCycleCollectionParticipant *helper) {}
+    NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {}
+    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *val) {}
     bool MayHaveChild() {
         return mMayHaveChild;
-    };
+    }
 private:
     bool mMayHaveChild;
 };
 
 NS_IMETHODIMP_(void)
 ChildFinder::NoteXPCOMChild(nsISupports *child)
 {
     if (!child || !(child = canonicalize(child)))
         return; 
     nsXPCOMCycleCollectionParticipant *cp;
     ToParticipant(child, &cp);
     if (cp && !cp->CanSkip(child, true))
         mMayHaveChild = true;
-};
+}
 
 NS_IMETHODIMP_(void)
 ChildFinder::NoteNativeChild(void *child,
                              nsCycleCollectionParticipant *helper)
 {
     if (child)
         mMayHaveChild = true;
-};
+}
 
 NS_IMETHODIMP_(void)
 ChildFinder::NoteJSChild(void *child)
 {
     if (child && xpc_GCThingIsGrayCCThing(child)) {
         mMayHaveChild = true;
     }
-};
+}
 
 static bool
 AddPurpleRoot(GCGraphBuilder &builder, nsISupports *root)
 {
     root = canonicalize(root);
     NS_ASSERTION(root,
                  "Don't add objects that don't participate in collection!");
 
--- a/xpcom/base/nsWindowsHelpers.h
+++ b/xpcom/base/nsWindowsHelpers.h
@@ -1,15 +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/. */
 
 #ifndef nsWindowsHelpers_h
 #define nsWindowsHelpers_h
 
+#include <windows.h>
 #include "nsAutoRef.h"
 #include "nscore.h"
 
 template<>
 class nsAutoRefTraits<HKEY>
 {
 public:
   typedef HKEY RawRef;
@@ -77,9 +78,22 @@ public:
   }
   RawRef mRawRef;
 };
 
 typedef nsAutoRef<HKEY> nsAutoRegKey;
 typedef nsAutoRef<SC_HANDLE> nsAutoServiceHandle;
 typedef nsAutoRef<HANDLE> nsAutoHandle;
 
+namespace
+{
+  bool
+  IsVistaOrLater()
+  {
+    OSVERSIONINFO info;
+    ZeroMemory(&info, sizeof(OSVERSIONINFO));
+    info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx(&info);
+    return info.dwMajorVersion >= 6;
+  }
+}
+
 #endif
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -12,16 +12,19 @@
 #else
 # include "nsXPCOMCIDInternal.h"
 # include "nsIThreadManager.h"
 # include "nsServiceManagerUtils.h"
 #endif
 
 #ifdef XP_WIN
 #include <windows.h>
+#include "nsWindowsHelpers.h"
+#elif defined(XP_MACOSX)
+#include <sys/resource.h>
 #endif
 
 #include <pratom.h>
 #include <prthread.h>
 
 #ifndef XPCOM_GLUE_AVOID_NSPR
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsRunnable, nsIRunnable)
@@ -284,8 +287,41 @@ nsThreadPoolNaming::SetThreadPoolName(co
     // Set on the target thread
     NS_SetThreadName(aThread, name);
   }
   else {
     // Set on the current thread
     PR_SetCurrentThreadName(name.BeginReading());
   }
 }
+
+// nsAutoLowPriorityIO
+nsAutoLowPriorityIO::nsAutoLowPriorityIO()
+{
+#if defined(XP_WIN)
+  lowIOPrioritySet = IsVistaOrLater() &&
+                     SetThreadPriority(GetCurrentThread(),
+                                       THREAD_MODE_BACKGROUND_BEGIN);
+#elif defined(XP_MACOSX)
+  oldPriority = getiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD);
+  lowIOPrioritySet = oldPriority != -1 &&
+                     setiopolicy_np(IOPOL_TYPE_DISK,
+                                    IOPOL_SCOPE_THREAD,
+                                    IOPOL_THROTTLE) != -1;
+#else
+  lowIOPrioritySet = false;
+#endif
+}
+
+nsAutoLowPriorityIO::~nsAutoLowPriorityIO()
+{
+#if defined(XP_WIN)
+  if (NS_LIKELY(lowIOPrioritySet)) {
+    // On Windows the old thread priority is automatically restored
+    SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
+  }
+#elif defined(XP_MACOSX)
+  if (NS_LIKELY(lowIOPrioritySet)) {
+    setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD, oldPriority);
+  }
+#endif
+}
+
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -489,9 +489,30 @@ public:
 
 private:
   volatile PRUint32 mCounter;
 
   nsThreadPoolNaming(const nsThreadPoolNaming &) MOZ_DELETE;
   void operator=(const nsThreadPoolNaming &) MOZ_DELETE;
 };
 
+/**
+ * Thread priority in most operating systems affect scheduling, not IO.  This
+ * helper is used to set the current thread to low IO priority for the lifetime
+ * of the created object.  You can only use this low priority IO setting within
+ * the context of the current thread.
+ */
+class NS_STACK_CLASS nsAutoLowPriorityIO
+{
+public:
+  nsAutoLowPriorityIO();
+  ~nsAutoLowPriorityIO();
+
+private:
+  bool lowIOPrioritySet;
+#if defined(XP_MACOSX)
+  int oldPriority;
+#endif
+};
+
+
+
 #endif  // nsThreadUtils_h__