Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Fri, 27 Jul 2012 09:52:39 +0100
changeset 106160 399aff2fb74f9269ee72ac8cbd7d3913402244d8
parent 106052 8b96a33ecbd2cf60cb431616e977038c70a5c77c (current diff)
parent 106159 5fe4c57fb73eac2b217fd2c18a0315cb975c8ca6 (diff)
child 106181 3e673382bdf48edf4c5bf02b0f58f2d01fcbe3a7
child 106189 9d9d92bcab139ec083ffd175aabcdffad2086a11
push id1490
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 18:29:50 +0000
treeherdermozilla-beta@f335e7dacdc1 [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 PGO-green changeset of mozilla-inbound to mozilla-central
other-licenses/simplejson-2.1.1/CHANGES.txt
other-licenses/simplejson-2.1.1/LICENSE.txt
other-licenses/simplejson-2.1.1/PKG-INFO
other-licenses/simplejson-2.1.1/conf.py
other-licenses/simplejson-2.1.1/docs/_sources/index.txt
other-licenses/simplejson-2.1.1/docs/_static/contents.png
other-licenses/simplejson-2.1.1/docs/_static/default.css
other-licenses/simplejson-2.1.1/docs/_static/doctools.js
other-licenses/simplejson-2.1.1/docs/_static/file.png
other-licenses/simplejson-2.1.1/docs/_static/interface.js
other-licenses/simplejson-2.1.1/docs/_static/jquery.js
other-licenses/simplejson-2.1.1/docs/_static/minus.png
other-licenses/simplejson-2.1.1/docs/_static/navigation.png
other-licenses/simplejson-2.1.1/docs/_static/plus.png
other-licenses/simplejson-2.1.1/docs/_static/pygments.css
other-licenses/simplejson-2.1.1/docs/_static/rightsidebar.css
other-licenses/simplejson-2.1.1/docs/_static/searchtools.js
other-licenses/simplejson-2.1.1/docs/_static/sphinxdoc.css
other-licenses/simplejson-2.1.1/docs/_static/stickysidebar.css
other-licenses/simplejson-2.1.1/docs/_static/traditional.css
other-licenses/simplejson-2.1.1/docs/genindex.html
other-licenses/simplejson-2.1.1/docs/index.html
other-licenses/simplejson-2.1.1/docs/objects.inv
other-licenses/simplejson-2.1.1/docs/search.html
other-licenses/simplejson-2.1.1/docs/searchindex.js
other-licenses/simplejson-2.1.1/docs/searchindex.json
other-licenses/simplejson-2.1.1/ez_setup.py
other-licenses/simplejson-2.1.1/index.rst
other-licenses/simplejson-2.1.1/scripts/make_docs.py
other-licenses/simplejson-2.1.1/setup.cfg
other-licenses/simplejson-2.1.1/setup.py
other-licenses/simplejson-2.1.1/simplejson/__init__.py
other-licenses/simplejson-2.1.1/simplejson/_speedups.c
other-licenses/simplejson-2.1.1/simplejson/decoder.py
other-licenses/simplejson-2.1.1/simplejson/encoder.py
other-licenses/simplejson-2.1.1/simplejson/ordered_dict.py
other-licenses/simplejson-2.1.1/simplejson/scanner.py
other-licenses/simplejson-2.1.1/simplejson/tests/__init__.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_check_circular.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_decimal.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_decode.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_default.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_dump.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_encode_basestring_ascii.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_encode_for_html.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_fail.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_float.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_indent.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_pass1.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_pass2.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_pass3.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_recursion.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_scanstring.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_separators.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_speedups.py
other-licenses/simplejson-2.1.1/simplejson/tests/test_unicode.py
other-licenses/simplejson-2.1.1/simplejson/tool.py
other-licenses/virtualenv/AUTHORS.txt
other-licenses/virtualenv/LICENSE.txt
other-licenses/virtualenv/MANIFEST.in
other-licenses/virtualenv/PKG-INFO
other-licenses/virtualenv/docs/index.txt
other-licenses/virtualenv/docs/news.txt
other-licenses/virtualenv/scripts/virtualenv
other-licenses/virtualenv/setup.cfg
other-licenses/virtualenv/setup.py
other-licenses/virtualenv/virtualenv.py
other-licenses/virtualenv/virtualenv_embedded/activate.bat
other-licenses/virtualenv/virtualenv_embedded/activate.csh
other-licenses/virtualenv/virtualenv_embedded/activate.fish
other-licenses/virtualenv/virtualenv_embedded/activate.ps1
other-licenses/virtualenv/virtualenv_embedded/activate.sh
other-licenses/virtualenv/virtualenv_embedded/activate_this.py
other-licenses/virtualenv/virtualenv_embedded/deactivate.bat
other-licenses/virtualenv/virtualenv_embedded/distribute_setup.py
other-licenses/virtualenv/virtualenv_embedded/distutils-init.py
other-licenses/virtualenv/virtualenv_embedded/distutils.cfg
other-licenses/virtualenv/virtualenv_embedded/ez_setup.py
other-licenses/virtualenv/virtualenv_embedded/site.py
other-licenses/virtualenv/virtualenv_support/__init__.py
other-licenses/virtualenv/virtualenv_support/distribute-0.6.27.tar.gz
other-licenses/virtualenv/virtualenv_support/pip-1.1.tar.gz
other-licenses/virtualenv/virtualenv_support/setuptools-0.6c11-py2.4.egg
other-licenses/virtualenv/virtualenv_support/setuptools-0.6c11-py2.5.egg
other-licenses/virtualenv/virtualenv_support/setuptools-0.6c11-py2.6.egg
other-licenses/virtualenv/virtualenv_support/setuptools-0.6c11-py2.7.egg
toolkit/components/osfile/osfile_shared.jsm
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -343,17 +343,17 @@ var SocialToolbar = {
     panel.hidden = false;
 
     function sizePanelToContent() {
       // FIXME: bug 764787: Maybe we can use nsIDOMWindowUtils.getRootBounds() here?
       // Need to handle dynamic sizing
       let doc = notifBrowser.contentDocument;
       // "notif" is an implementation detail that we should get rid of
       // eventually
-      let body = doc.getElementById("notif") || doc.body.firstChild;
+      let body = doc.getElementById("notif") || (doc.body && doc.body.firstChild);
       if (!body)
         return;
       let h = body.scrollHeight > 0 ? body.scrollHeight : 300;
       notifBrowser.style.width = body.scrollWidth + "px";
       notifBrowser.style.height = h + "px";
     }
 
     notifBrowser.addEventListener("DOMContentLoaded", function onload() {
--- a/build/mobile/sutagent/android/CmdWorkerThread.java
+++ b/build/mobile/sutagent/android/CmdWorkerThread.java
@@ -3,19 +3,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package com.mozilla.SUTAgentAndroid.service;
 
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.FileWriter;
 import java.io.PrintWriter;
 import java.net.Socket;
 import java.net.SocketTimeoutException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import android.util.Log;
 
 // import com.mozilla.SUTAgentAndroid.DoCommand;
 
 public class CmdWorkerThread extends Thread
 {
     private RunCmdThread theParent = null;
     private Socket socket    = null;
     private String prompt = null;
@@ -123,16 +129,41 @@ public class CmdWorkerThread extends Thr
                         continue;
                         }
                     }
                 else
                     inputLine = "";
 
                 if ((inputLine += readLine(in)) != null)
                     {
+                    String datestamp = dc.GetSystemTime();
+                    String message = String.format("%s : %s : %s",
+                                     datestamp, socket.getInetAddress().getHostAddress(), inputLine);
+                    Log.i("SUTAgentAndroid", message);
+
+                    String fileDateStr = "00";
+                    try {
+                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
+                        Date dateStr = sdf.parse(datestamp);
+                        SimpleDateFormat sdf_file = new SimpleDateFormat("yyyy-MM-dd");
+                        fileDateStr = sdf_file.format(dateStr);
+                    } catch (ParseException pe) {}
+                    String logFile = dc.GetTestRoot() + "/" + fileDateStr + "-sutcommands.txt";
+                    PrintWriter pw = null;
+                    try {
+                        pw = new PrintWriter(new FileWriter(logFile, true));
+                        if (message != null) {
+                            pw.println(message);
+                        }
+                    } catch (IOException ioe) {
+                        Log.e("SUTAgentAndroid", "exception with file writer on: " + logFile);
+                    } finally {
+                        pw.close();
+                    }
+
                     outputLine = dc.processCommand(inputLine, out, in, cmdOut);
                     if (outputLine.length() > 0)
                         {
                         out.print(outputLine + "\n" + prompt);
                         }
                     else
                         out.print(prompt);
                     out.flush();
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -79,17 +79,16 @@ import android.content.pm.ServiceInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Debug;
 import android.os.Environment;
 import android.os.StatFs;
 import android.os.SystemClock;
-import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Surface;
 import android.view.WindowManager;
 
 public class DoCommand {
 
     String lineSep = System.getProperty("line.separator");
@@ -3520,17 +3519,17 @@ private void CancelNotification()
 
     public String StartPrg(String [] progArray, OutputStream out)
         {
         String sRet = "";
         int    lcv = 0;
 
         try
             {
-            pProc = Runtime.getRuntime().exec(this.getSuArgs(TextUtils.join(" ", progArray)));
+            pProc = Runtime.getRuntime().exec(progArray);
             RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
             outThrd.start();
             while (lcv < 30) {
                 try {
                     outThrd.join(10000);
                     int nRetCode = pProc.exitValue();
                     sRet = "return code [" + nRetCode + "]";
                     break;
--- a/build/mobile/sutagent/android/SUTAgentAndroid.java
+++ b/build/mobile/sutagent/android/SUTAgentAndroid.java
@@ -6,16 +6,19 @@ package com.mozilla.SUTAgentAndroid;
 
 import java.io.File;
 import java.io.PrintWriter;
 import java.net.InetAddress;
 import org.apache.http.conn.util.InetAddressUtils;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.net.UnknownHostException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.Enumeration;
 import java.util.Formatter;
 import java.util.List;
 import java.util.Timer;
 
 import com.mozilla.SUTAgentAndroid.service.ASMozStub;
 import com.mozilla.SUTAgentAndroid.service.DoCommand;
 import android.app.Activity;
@@ -93,16 +96,53 @@ public class SUTAgentAndroid extends Act
         return super.onMenuItemSelected(featureId, item);
         }
 
     public static String getRegSvrIPAddr()
         {
         return(RegSvrIPAddr);
         }
 
+    public void pruneCommandLog(String datestamp, String testroot)
+        {
+
+        String today = "";
+        String yesterday = "";
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS");
+            Date dateObj = sdf.parse(datestamp);
+            SimpleDateFormat sdf_file = new SimpleDateFormat("yyyy-MM-dd");
+
+            today     = sdf_file.format(dateObj);
+            yesterday = sdf_file.format(new Date(dateObj.getTime() - 1000*60*60*24));
+        } catch (ParseException pe) {}
+
+        File dir = new File(testroot);
+
+        if (!dir.isDirectory())
+            return;
+
+        File [] files = dir.listFiles();
+        if (files == null)
+            return;
+
+        for (int iter = 0; iter < files.length; iter++) {
+            String fName = files[iter].getName();
+            if (fName.endsWith("sutcommands.txt")) {
+                if (fName.endsWith(today + "-sutcommands.txt") || fName.endsWith(yesterday + "-sutcommands.txt"))
+                    continue;
+
+                if (files[iter].delete())
+                    Log.i("SUTAgentAndroid", "Deleted old command logfile: " + files[iter]);
+                else
+                    Log.e("SUTAgentAndroid", "Unable to delete old command logfile: " + files[iter]);
+            }
+        }
+        }
+
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState)
         {
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.main);
 
@@ -244,16 +284,18 @@ public class SUTAgentAndroid extends Act
         sRegString += "&BPP=8";
         sRegString += "&MEMORY=" + dc.GetMemoryConfig();
         sRegString += "&HARDWARE=" + HardwareID;
         sRegString += "&POOL=" + Pool;
 
         String sTemp = Uri.encode(sRegString,"=&");
         sRegString = "register " + sTemp;
 
+        pruneCommandLog(dc.GetSystemTime(), dc.GetTestRoot());
+
         if (!bNetworkingStarted)
             {
             Thread thread = new Thread(null, doStartService, "StartServiceBkgnd");
             thread.start();
             bNetworkingStarted = true;
 
             Thread thread2 = new Thread(null, doRegisterDevice, "RegisterDeviceBkgnd");
             thread2.start();
--- a/build/virtualenv/packages.txt
+++ b/build/virtualenv/packages.txt
@@ -1,9 +1,9 @@
-setup.py:other-licenses/simplejson-2.1.1:develop
+setup.py:python/simplejson-2.1.1:develop
 setup.py:testing/mozbase/manifestdestiny:develop
 setup.py:testing/mozbase/mozinfo:develop
 setup.py:testing/mozbase/mozinstall:develop
 setup.py:testing/mozbase/mozlog:develop
 setup.py:testing/mozbase/mozprocess:develop
 setup.py:testing/mozbase/mozprofile:develop
 setup.py:testing/mozbase/mozrunner:develop
 setup.py:python/blessings:develop
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -1154,33 +1154,33 @@ nsPrincipal::Read(nsIObjectInputStream* 
   }
 
   nsCOMPtr<nsIURI> codebase;
   rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(codebase));
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  nsCOMPtr<nsIURI> domain;
+  rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(domain));
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
   PRUint32 appId;
   rv = aStream->Read32(&appId);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool inMozBrowser;
   rv = aStream->ReadBoolean(&inMozBrowser);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = Init(fingerprint, subjectName, prettyName, cert, codebase, appId, inMozBrowser);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIURI> domain;
-  rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(domain));
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
   SetDomain(domain);
 
   rv = aStream->ReadBoolean(&mTrusted);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   return NS_OK;
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -55,16 +55,17 @@
 #include "nsCDefaultURIFixup.h"
 #include "nsIChromeRegistry.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/StandardInteger.h"
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/StaticPtr.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 nsIIOService    *nsScriptSecurityManager::sIOService = nsnull;
 nsIXPConnect    *nsScriptSecurityManager::sXPConnect = nsnull;
@@ -3052,17 +3053,17 @@ nsresult nsScriptSecurityManager::Init()
     JS_SetSecurityCallbacks(sRuntime, &securityCallbacks);
     JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy);
 
     JS_SetTrustedPrincipals(sRuntime, system);
 
     return NS_OK;
 }
 
-static nsRefPtr<nsScriptSecurityManager> gScriptSecMan;
+static StaticRefPtr<nsScriptSecurityManager> gScriptSecMan;
 
 jsid nsScriptSecurityManager::sEnabledID   = JSID_VOID;
 
 nsScriptSecurityManager::~nsScriptSecurityManager(void)
 {
     Preferences::RemoveObservers(this, kObservedPrefs);
     delete mOriginToPolicyMap;
     if(mDefaultPolicy)
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -219,17 +219,17 @@ MOZ_HUNSPELL_LIBS = @MOZ_HUNSPELL_LIBS@
 MOZ_HUNSPELL_CFLAGS = @MOZ_HUNSPELL_CFLAGS@
 
 MOZ_NATIVE_LIBEVENT = @MOZ_NATIVE_LIBEVENT@
 MOZ_LIBEVENT_LIBS = @MOZ_LIBEVENT_LIBS@
 MOZ_LIBEVENT_INCLUDES = @MOZ_LIBEVENT_INCLUDES@
 
 MOZ_NATIVE_LIBVPX = @MOZ_NATIVE_LIBVPX@
 MOZ_LIBVPX_LIBS = @MOZ_LIBVPX_LIBS@
-MOZ_LIBVPX_INCLUDES = @MOZ_LIBVPX_INCLUDES@
+MOZ_LIBVPX_CFLAGS = @MOZ_LIBVPX_CFLAGS@
 
 MOZ_NATIVE_ZLIB	= @MOZ_NATIVE_ZLIB@
 MOZ_NATIVE_BZ2	= @MOZ_NATIVE_BZ2@
 MOZ_NATIVE_JPEG	= @MOZ_NATIVE_JPEG@
 MOZ_NATIVE_PNG	= @MOZ_NATIVE_PNG@
 MOZ_TREE_CAIRO = @MOZ_TREE_CAIRO@
 MOZ_TREE_PIXMAN = @MOZ_TREE_PIXMAN@
 
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1741,16 +1741,23 @@ FREEZE_VARIABLES = \
   XPIDLSRCS \
   DIRS \
   LIBRARY \
   MODULE \
   SHORT_LIBNAME \
   TIERS \
   EXTRA_COMPONENTS \
   EXTRA_PP_COMPONENTS \
+  MOCHITEST_FILES \
+  MOCHITEST_FILES_PARTS \
+  MOCHITEST_CHROME_FILES \
+  MOCHITEST_BROWSER_FILES \
+  MOCHITEST_BROWSER_FILES_PARTS \
+  MOCHITEST_A11Y_FILES \
+  MOCHITEST_WEBAPPRT_CHROME_FILES \
   $(NULL)
 
 $(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
 
 CHECK_FROZEN_VARIABLES = $(foreach var,$(FREEZE_VARIABLES), \
   $(if $(subst $($(var)_FROZEN),,'$($(var))'),$(error Makefile variable '$(var)' changed value after including rules.mk. Was $($(var)_FROZEN), now $($(var)).)))
 
 libs export::
--- a/configure.in
+++ b/configure.in
@@ -5346,45 +5346,47 @@ if test -n "$MOZ_OMX_PLUGIN"; then
 fi
 
 dnl system libvpx Support
 dnl ========================================================
 MOZ_ARG_WITH_BOOL(system-libvpx,
 [  --with-system-libvpx    Use system libvpx (located with pkgconfig)],
     MOZ_NATIVE_LIBVPX=1)
 
-MOZ_LIBVPX_INCLUDES=
+MOZ_LIBVPX_CFLAGS=
 MOZ_LIBVPX_LIBS=
 
 if test -n "$MOZ_VP8"; then
     AC_DEFINE(MOZ_VP8)
     if test -n "$MOZ_VP8_ERROR_CONCEALMENT" ; then
         AC_DEFINE(MOZ_VP8_ERROR_CONCEALMENT)
     fi
     if test -n "$MOZ_VP8_ENCODER" ; then
         AC_DEFINE(MOZ_VP8_ENCODER)
     fi
 
     if test -n "$MOZ_NATIVE_LIBVPX"; then
         dnl ============================
         dnl === libvpx Version check ===
         dnl ============================
         dnl Check to see if we have a system libvpx package.
-        PKG_CHECK_MODULES(LIBVPX, vpx >= 1.0.0)
+        PKG_CHECK_MODULES(MOZ_LIBVPX, vpx >= 1.0.0)
 
         MOZ_CHECK_HEADER([vpx/vpx_decoder.h], [], 
          [AC_MSG_ERROR([Couldn't find vpx/vpx_decoder.h which is required for build with system libvpx. Use --without-system-libvpx to build with in-tree libvpx.])])
 
+        _SAVE_LIBS=$LIBS
         AC_CHECK_LIB(vpx, vpx_codec_dec_init_ver, [], 
          [AC_MSG_ERROR([--with-system-libvpx requested but symbol vpx_codec_dec_init_ver not found])])
+        LIBS=$_SAVE_LIBS
     fi
 fi
 
 AC_SUBST(MOZ_NATIVE_LIBVPX)
-AC_SUBST(MOZ_LIBVPX_INCLUDES)
+AC_SUBST(MOZ_LIBVPX_CFLAGS)
 AC_SUBST(MOZ_LIBVPX_LIBS)
 
 if test "$MOZ_WEBM"; then
     MOZ_SYDNEYAUDIO=1
     MOZ_CUBEB=1
     MOZ_MEDIA=1
     case "$target_cpu" in
     arm*)
@@ -8780,17 +8782,17 @@ ACDEFINES=$DEFS
 AC_SUBST(ACDEFINES)
 rm -f confdefs.h
 mv confdefs.h.save confdefs.h
 
 dnl Create a virtualenv where we can install local Python packages
 AC_MSG_RESULT([Creating Python virtualenv])
 rm -rf _virtualenv
 mkdir -p _virtualenv
-MACOSX_DEPLOYMENT_TARGET= PYTHONDONTWRITEBYTECODE= $PYTHON $_topsrcdir/other-licenses/virtualenv/virtualenv.py --system-site-packages ./_virtualenv
+MACOSX_DEPLOYMENT_TARGET= PYTHONDONTWRITEBYTECODE= $PYTHON $_topsrcdir/python/virtualenv/virtualenv.py --system-site-packages ./_virtualenv
 case "$host_os" in
 mingw*)
     PYTHON=$MOZ_BUILD_ROOT/_virtualenv/Scripts/python.exe
     ;;
 *)
     PYTHON=$MOZ_BUILD_ROOT/_virtualenv/bin/python
     ;;
 esac
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -2116,16 +2116,17 @@ class WebGLShader MOZ_FINAL
     friend class WebGLProgram;
 
 public:
     WebGLShader(WebGLContext *context, WebGLenum stype)
         : WebGLContextBoundObject(context)
         , mType(stype)
         , mNeedsTranslation(true)
         , mAttribMaxNameLength(0)
+        , mCompileStatus(false)
     {
         mContext->MakeContextCurrent();
         mGLName = mContext->gl->fCreateShader(mType);
         mContext->mShaders.insertBack(this);
     }
 
     ~WebGLShader() {
         DeleteOnce();
@@ -2153,16 +2154,24 @@ public:
         mSource.Assign(src);
     }
 
     const nsString& Source() const { return mSource; }
 
     void SetNeedsTranslation() { mNeedsTranslation = true; }
     bool NeedsTranslation() const { return mNeedsTranslation; }
 
+    void SetCompileStatus (bool status) {
+        mCompileStatus = status;
+    }
+
+    bool CompileStatus() const {
+        return mCompileStatus;
+    }
+
     void SetTranslationSuccess() {
         mTranslationLog.SetIsVoid(true);
         mNeedsTranslation = false;
     }
 
     void SetTranslationFailure(const nsCString& msg) {
         mTranslationLog.Assign(msg); 
     }
@@ -2178,16 +2187,17 @@ protected:
     WebGLenum mType;
     nsString mSource;
     nsCString mTranslationLog; // The translation log should contain only ASCII characters
     bool mNeedsTranslation;
     nsTArray<WebGLMappedIdentifier> mAttributes;
     nsTArray<WebGLMappedIdentifier> mUniforms;
     nsTArray<WebGLUniformInfo> mUniformInfos;
     int mAttribMaxNameLength;
+    bool mCompileStatus;
 };
 
 /** Takes an ASCII string like "foo[i]", turns it into "foo" and returns "[i]" in bracketPart
   * 
   * \param string input/output: the string to split, becomes the string without the bracket part
   * \param bracketPart output: gets the bracket part.
   * 
   * Notice that if there are multiple brackets like "foo[i].bar[j]", only the last bracket is split.
@@ -2299,16 +2309,25 @@ public:
     }
 
     bool HasBothShaderTypesAttached() {
         return
             HasAttachedShaderOfType(LOCAL_GL_VERTEX_SHADER) &&
             HasAttachedShaderOfType(LOCAL_GL_FRAGMENT_SHADER);
     }
 
+    bool HasBadShaderAttached() {
+        for (uint32_t i = 0; i < mAttachedShaders.Length(); ++i) {
+            if (mAttachedShaders[i] && !mAttachedShaders[i]->CompileStatus()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     bool NextGeneration()
     {
         if (!(mGeneration + 1).isValid())
             return false; // must exit without changing mGeneration
         ++mGeneration;
         return true;
     }
 
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -2841,16 +2841,21 @@ WebGLContext::GetRenderbufferParameter(W
     if (!IsContextStable())
         return JS::NullValue();
 
     if (target != LOCAL_GL_RENDERBUFFER) {
         ErrorInvalidEnumInfo("getRenderbufferParameter: target", target);
         return JS::NullValue();
     }
 
+    if (!mBoundRenderbuffer) {
+        ErrorInvalidOperation("getRenderbufferParameter: no render buffer is bound");
+        return JS::NullValue();
+    }
+
     MakeContextCurrent();
 
     switch (pname) {
         case LOCAL_GL_RENDERBUFFER_WIDTH:
         case LOCAL_GL_RENDERBUFFER_HEIGHT:
         case LOCAL_GL_RENDERBUFFER_RED_SIZE:
         case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
         case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
@@ -2859,23 +2864,17 @@ WebGLContext::GetRenderbufferParameter(W
         case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
         {
             GLint i = 0;
             gl->fGetRenderbufferParameteriv(target, pname, &i);
             return JS::Int32Value(i);
         }
         case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
         {
-            GLint i = 0;
-            gl->fGetRenderbufferParameteriv(target, pname, &i);
-            if (i == LOCAL_GL_DEPTH24_STENCIL8)
-            {
-                i = LOCAL_GL_DEPTH_STENCIL;
-            }
-            return JS::NumberValue(uint32_t(i));
+            return JS::NumberValue(mBoundRenderbuffer->InternalFormat());
         }
         default:
             ErrorInvalidEnumInfo("getRenderbufferParameter: parameter", pname);
     }
 
     return JS::NullValue();
 }
 
@@ -2962,19 +2961,17 @@ WebGLContext::GetProgramParameter(WebGLP
             GLint i = 0;
             gl->fGetProgramiv(progname, pname, &i);
             return JS::Int32Value(i);
         }
         case LOCAL_GL_DELETE_STATUS:
             return JS::BooleanValue(prog->IsDeleteRequested());
         case LOCAL_GL_LINK_STATUS:
         {
-            GLint i = 0;
-            gl->fGetProgramiv(progname, pname, &i);
-            return JS::BooleanValue(bool(i));
+            return JS::BooleanValue(prog->LinkStatus());
         }
         case LOCAL_GL_VALIDATE_STATUS:
         {
             GLint i = 0;
 #ifdef XP_MACOSX
             // See comment in ValidateProgram below.
             if (gl->WorkAroundDriverBugs())
                 i = 1;
@@ -3704,21 +3701,30 @@ WebGLContext::LinkProgram(WebGLProgram *
 
     if (!program->HasBothShaderTypesAttached()) {
         GenerateWarning("linkProgram: this program doesn't have both a vertex shader"
                         " and a fragment shader");
         program->SetLinkStatus(false);
         return;
     }
 
-    MakeContextCurrent();
-    gl->fLinkProgram(progname);
-
     GLint ok;
-    gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok);
+    if (gl->WorkAroundDriverBugs() &&
+        program->HasBadShaderAttached())
+    {
+        // it's a common driver bug, caught by program-test.html, that linkProgram doesn't
+        // correctly preserve the state of an in-use program that has been attached a bad shader
+        // see bug 777883
+        ok = false;
+    } else {
+        MakeContextCurrent();
+        gl->fLinkProgram(progname);
+        gl->fGetProgramiv(progname, LOCAL_GL_LINK_STATUS, &ok);
+    }
+
     if (ok) {
         bool updateInfoSucceeded = program->UpdateInfo();
         program->SetLinkStatus(updateInfoSucceeded);
 
         // Bug 750527
         if (gl->WorkAroundDriverBugs() &&
             updateInfoSucceeded &&
             gl->Vendor() == gl::GLContext::VendorNVIDIA)
@@ -3740,31 +3746,33 @@ WebGLContext::LinkProgram(WebGLProgram *
             ErrorResult rv;
             nsCAutoString log;
 
             bool alreadyReportedShaderInfoLog = false;
 
             for (size_t i = 0; i < program->AttachedShaders().Length(); i++) {
 
                 WebGLShader* shader = program->AttachedShaders()[i];
-                GetShaderInfoLog(shader, log, rv);
-                if (rv.Failed() || log.IsEmpty())
+                
+                if (shader->CompileStatus())
                     continue;
 
                 const char *shaderTypeName = nsnull;
                 if (shader->ShaderType() == LOCAL_GL_VERTEX_SHADER) {
                     shaderTypeName = "vertex";
                 } else if (shader->ShaderType() == LOCAL_GL_FRAGMENT_SHADER) {
                     shaderTypeName = "fragment";
                 } else {
                     // should have been validated earlier
                     NS_ABORT();
                     shaderTypeName = "<unknown>";
                 }
 
+                GetShaderInfoLog(shader, log, rv);
+
                 GenerateWarning("linkProgram: a %s shader used in this program failed to "
                                 "compile, with this log:\n%s\n",
                                 shaderTypeName,
                                 log.get());
                 alreadyReportedShaderInfoLog = true;
             }
 
             if (!alreadyReportedShaderInfoLog) {
@@ -4906,16 +4914,18 @@ WebGLContext::CompileShader(WebGLShader 
     if (!IsContextStable())
         return;
 
     if (!ValidateObject("compileShader", shader))
         return;
 
     WebGLuint shadername = shader->GLName();
 
+    shader->SetCompileStatus(false);
+
     MakeContextCurrent();
 
     ShShaderOutput targetShaderSourceLanguage = gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT;
     bool useShaderSourceTranslation = true;
 
 #if defined(USE_ANGLE)
     if (shader->NeedsTranslation() && mShaderValidation) {
         ShHandle compiler = 0;
@@ -4988,16 +4998,17 @@ WebGLContext::CompileShader(WebGLShader 
                 nsCAutoString info;
                 info.SetLength(len);
                 ShGetInfoLog(compiler, info.BeginWriting());
                 shader->SetTranslationFailure(info);
             } else {
                 shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
             }
             ShDestruct(compiler);
+            shader->SetCompileStatus(false);
             return;
         }
 
         int num_attributes = 0;
         ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTES, &num_attributes);
         int num_uniforms = 0;
         ShGetInfo(compiler, SH_ACTIVE_UNIFORMS, &num_uniforms);
         int attrib_max_length = 0;
@@ -5076,16 +5087,19 @@ WebGLContext::CompileShader(WebGLShader 
             gl->fShaderSource(shadername, 1, &s, NULL);
         }
 
         shader->SetTranslationSuccess();
 
         ShDestruct(compiler);
 
         gl->fCompileShader(shadername);
+        GLint ok;
+        gl->fGetShaderiv(shadername, LOCAL_GL_COMPILE_STATUS, &ok);
+        shader->SetCompileStatus(ok);
     }
 #endif
 }
 
 NS_IMETHODIMP
 WebGLContext::CompressedTexImage2D(WebGLenum target, WebGLint level, WebGLenum internalformat,
                                    WebGLsizei width, WebGLsizei height, WebGLint border,
                                    const JS::Value& pixels, JSContext *cx)
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -544,56 +544,32 @@ NS_INTERFACE_MAP_END
 // Initialize our static variables.
 PRUint32 nsCanvasRenderingContext2DAzure::sNumLivingContexts = 0;
 PRUint8 (*nsCanvasRenderingContext2DAzure::sUnpremultiplyTable)[256] = nsnull;
 PRUint8 (*nsCanvasRenderingContext2DAzure::sPremultiplyTable)[256] = nsnull;
 
 namespace mozilla {
 namespace dom {
 
-static bool
-AzureCanvasEnabledOnPlatform()
-{
-#ifdef XP_WIN
-  if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() !=
-      gfxWindowsPlatform::RENDER_DIRECT2D ||
-      !gfxWindowsPlatform::GetPlatform()->DWriteEnabled()) {
-    static bool checkedPref = false;
-    static bool preferSkia;
-    if (!checkedPref) {
-      preferSkia = Preferences::GetBool("gfx.canvas.azure.prefer-skia", false);
-      checkedPref = true;
-    }
-    return preferSkia;
-  }
-#elif !defined(XP_MACOSX) && !defined(ANDROID) && !defined(LINUX)
-  return false;
-#endif
-  return true;
-}
-
 bool
 AzureCanvasEnabled()
 {
-  static bool checkedPref = false;
-  static bool azureEnabled;
-  if (!checkedPref) {
-    azureEnabled = Preferences::GetBool("gfx.canvas.azure.enabled", false);
-    checkedPref = true;
-  }
-  return azureEnabled && AzureCanvasEnabledOnPlatform();
+  BackendType dontCare;
+  return gfxPlatform::GetPlatform()->SupportsAzureCanvas(dontCare);
 }
 
 }
 }
 
 nsresult
 NS_NewCanvasRenderingContext2DAzure(nsIDOMCanvasRenderingContext2D** aResult)
 {
-  if (!AzureCanvasEnabledOnPlatform()) {
+  // XXX[nrc] remove this check when Thebes canvas is removed
+  // (because we will always support Azure)
+  if (!AzureCanvasEnabled()) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsRefPtr<nsIDOMCanvasRenderingContext2D> ctx = new nsCanvasRenderingContext2DAzure();
   if (!ctx)
     return NS_ERROR_OUT_OF_MEMORY;
 
   *aResult = ctx.forget().get();
@@ -909,40 +885,22 @@ nsCanvasRenderingContext2DAzure::SetDime
       JS_updateMallocCounter(context, width * height * 4);
     }
   }
 
   return InitializeWithTarget(target, width, height);
 }
 
 nsresult
-nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt32 width, PRInt32 height)
+nsCanvasRenderingContext2DAzure::Initialize(PRInt32 width, PRInt32 height)
 {
-  Reset();
-
-  NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
-  mDocShell = nsnull;
-
   mWidth = width;
   mHeight = height;
 
-  // This first time this is called on this object is via
-  // nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
-  // non-null, otherwise we'll return an error here and GetContext won't
-  // return this context object and we'll never enter this code again.
-  // All other times this method is called, if target is null then
-  // mTarget won't be changed, i.e. it will remain non-null, or else it
-  // will be set to non-null.
-  // In all cases, any usable canvas context will have non-null mTarget.
-
-  if (target) {
-    mValid = true;
-    mTarget = target;
-  } else {
-    mValid = false;
+  if (!mValid) {
     // Create a dummy target in the hopes that it will help us deal with users
     // calling into us after having changed the size where the size resulted
     // in an inability to create a correct DrawTarget.
     mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
   }
 
   mResetLayer = true;
 
@@ -964,16 +922,55 @@ nsCanvasRenderingContext2DAzure::Initial
     // always force a redraw, because if the surface dimensions were reset
     // then the surface became cleared, and we need to redraw everything.
     Redraw();
   }
 
   return mValid ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
+nsresult
+nsCanvasRenderingContext2DAzure::InitializeWithTarget(DrawTarget *target, PRInt32 width, PRInt32 height)
+{
+  Reset();
+
+  NS_ASSERTION(mCanvasElement, "Must have a canvas element!");
+  mDocShell = nsnull;
+
+  // This first time this is called on this object is via
+  // nsHTMLCanvasElement::GetContext. If target was non-null then mTarget is
+  // non-null, otherwise we'll return an error here and GetContext won't
+  // return this context object and we'll never enter this code again.
+  // All other times this method is called, if target is null then
+  // mTarget won't be changed, i.e. it will remain non-null, or else it
+  // will be set to non-null.
+  // In all cases, any usable canvas context will have non-null mTarget.
+
+  if (target) {
+    mValid = true;
+    mTarget = target;
+  } else {
+    mValid = false;
+  }
+
+  return Initialize(width, height);
+}
+
+NS_IMETHODIMP
+nsCanvasRenderingContext2DAzure::InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
+{
+  mDocShell = shell;
+  mThebesSurface = surface;
+
+  mTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, IntSize(width, height));
+  mValid = mTarget != nsnull;
+
+  return Initialize(width, height);
+}
+
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::SetIsOpaque(bool isOpaque)
 {
   if (isOpaque == mOpaque)
     return NS_OK;
 
   mOpaque = isOpaque;
 
@@ -2488,67 +2485,73 @@ nsCanvasRenderingContext2DAzure::EnsureW
       mPath = nsnull;
       mPathBuilder = nsnull;
       mPathTransformWillUpdate = false;
     }
     return;
   }
 
   if (!mPath) {
+    NS_ASSERTION(!mPathTransformWillUpdate, "mPathTransformWillUpdate should be false, if all paths are null");
     mPathBuilder = mTarget->CreatePathBuilder(fillRule);
   } else if (!mPathTransformWillUpdate) {
     mPathBuilder = mPath->CopyToBuilder(fillRule);
   } else {
     mDSPathBuilder =
       mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
     mPathTransformWillUpdate = false;
   }
 }
 
 void
-nsCanvasRenderingContext2DAzure::EnsureUserSpacePath()
+nsCanvasRenderingContext2DAzure::EnsureUserSpacePath(bool aCommitTransform /* = true */)
 {
   FillRule fillRule = CurrentState().fillRule;
 
   if (!mPath && !mPathBuilder && !mDSPathBuilder) {
     mPathBuilder = mTarget->CreatePathBuilder(fillRule);
   }
 
   if (mPathBuilder) {
     mPath = mPathBuilder->Finish();
     mPathBuilder = nsnull;
   }
 
-  if (mPath && mPathTransformWillUpdate) {
+  if (aCommitTransform &&
+      mPath &&
+      mPathTransformWillUpdate) {
     mDSPathBuilder =
       mPath->TransformedCopyToBuilder(mPathToDS, fillRule);
     mPath = nsnull;
     mPathTransformWillUpdate = false;
   }
 
   if (mDSPathBuilder) {
     RefPtr<Path> dsPath;
     dsPath = mDSPathBuilder->Finish();
     mDSPathBuilder = nsnull;
 
     Matrix inverse = mTarget->GetTransform();
     if (!inverse.Invert()) {
+      NS_WARNING("Could not invert transform");
       return;
     }
 
     mPathBuilder =
       dsPath->TransformedCopyToBuilder(inverse, fillRule);
     mPath = mPathBuilder->Finish();
     mPathBuilder = nsnull;
   }
 
   if (mPath && mPath->GetFillRule() != fillRule) {
     mPathBuilder = mPath->CopyToBuilder(fillRule);
     mPath = mPathBuilder->Finish();
   }
+
+  NS_ASSERTION(mPath, "mPath should exist");
 }
 
 void
 nsCanvasRenderingContext2DAzure::TransformWillUpdate()
 {
   // Store the matrix that would transform the current path to device
   // space.
   if (mPath || mPathBuilder) {
@@ -3039,17 +3042,17 @@ struct NS_STACK_CLASS nsCanvasBidiProces
         endRun = runs[c + 1].mCharacterOffset;
       } else {
         endRun = mTextRun->GetLength();
       }
 
       const gfxTextRun::CompressedGlyph *glyphs = mTextRun->GetCharacterGlyphs();
 
       RefPtr<ScaledFont> scaledFont =
-        gfxPlatform::GetPlatform()->GetScaledFontForFont(font);
+        gfxPlatform::GetPlatform()->GetScaledFontForFont(mCtx->mTarget, font);
 
       if (!scaledFont) {
         // This can occur when something switched DirectWrite off.
         return;
       }
 
       GlyphBuffer buffer;
 
@@ -3099,31 +3102,31 @@ struct NS_STACK_CLASS nsCanvasBidiProces
 
       buffer.mGlyphs = &glyphBuf.front();
       buffer.mNumGlyphs = glyphBuf.size();
 
       if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_FILL) {
         AdjustedTarget(mCtx)->
           FillGlyphs(scaledFont, buffer,
                      CanvasGeneralPattern().
-                        ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
-                      DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
+                       ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
+                     DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
       } else if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_STROKE) {
         RefPtr<Path> path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget);
 
         const ContextState& state = *mState;
         AdjustedTarget(mCtx)->
           Stroke(path, CanvasGeneralPattern().
-                    ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
-                  StrokeOptions(state.lineWidth, state.lineJoin,
-                                state.lineCap, state.miterLimit,
-                                state.dash.Length(),
-                                state.dash.Elements(),
-                                state.dashOffset),
-                  DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
+                   ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
+                 StrokeOptions(state.lineWidth, state.lineJoin,
+                               state.lineCap, state.miterLimit,
+                               state.dash.Length(),
+                               state.dash.Elements(),
+                               state.dashOffset),
+                 DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
 
       }
     }
   }
 
   // current text run
   nsAutoPtr<gfxTextRun> mTextRun;
 
@@ -3602,19 +3605,24 @@ nsCanvasRenderingContext2DAzure::GetMozD
 
 bool
 nsCanvasRenderingContext2DAzure::IsPointInPath(double x, double y)
 {
   if (!FloatValidate(x,y)) {
     return false;
   }
 
-  EnsureUserSpacePath();
-
-  return mPath && mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
+  EnsureUserSpacePath(false);
+  if (!mPath) {
+    return false;
+  }
+  if (mPathTransformWillUpdate) {
+    return mPath->ContainsPoint(Point(x, y), mPathToDS);
+  }
+  return mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2DAzure::IsPointInPath(float x, float y, bool *retVal)
 {
   *retVal = IsPointInPath(x, y);
   return NS_OK;
 }
@@ -3663,22 +3671,24 @@ nsCanvasRenderingContext2DAzure::DrawIma
     if (srcCanvas == this) {
       // Self-copy.
       srcSurf = mTarget->Snapshot();
       imgSize = gfxIntSize(mWidth, mHeight);
     } else if (srcCanvas) {
       // This might not be an Azure canvas!
       srcSurf = srcCanvas->GetSurfaceSnapshot();
 
-      if (srcSurf && mCanvasElement) {
-        // Do security check here.
-        CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
-                                              element->NodePrincipal(),
-                                              canvas->IsWriteOnly(),
-                                              false);
+      if (srcSurf) {
+        if (mCanvasElement) {
+          // Do security check here.
+          CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
+                                                element->NodePrincipal(),
+                                               canvas->IsWriteOnly(),
+                                                false);
+        }
         imgSize = gfxIntSize(srcSurf->GetSize().width, srcSurf->GetSize().height);
       }
     }
   } else {
     if (image.IsHTMLImageElement()) {
       nsHTMLImageElement* img = image.GetAsHTMLImageElement();
       element = img;
     } else {
@@ -4250,28 +4260,31 @@ nsCanvasRenderingContext2DAzure::GetImag
   dstWriteRect.MoveBy(-aX, -aY);
 
   uint8_t* src = data;
   uint32_t srcStride = aWidth * 4;
   
   RefPtr<DataSourceSurface> readback;
   if (!srcReadRect.IsEmpty()) {
     RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
-
-    readback = snapshot->GetDataSurface();
-
-    srcStride = readback->Stride();
-    src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
+    if (snapshot) {
+      readback = snapshot->GetDataSurface();
+
+      srcStride = readback->Stride();
+      src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
+    }
   }
 
   // make sure sUnpremultiplyTable has been created
   EnsureUnpremultiplyTable();
 
   // NOTE! dst is the same as src, and this relies on reading
   // from src and advancing that ptr before writing to dst.
+  // NOTE! I'm not sure that it is, I think this comment might have been
+  // inherited from Thebes canvas and is no longer true
   uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
 
   for (int32_t j = 0; j < dstWriteRect.height; ++j) {
     for (int32_t i = 0; i < dstWriteRect.width; ++i) {
       // XXX Is there some useful swizzle MMX we can use here?
 #ifdef IS_LITTLE_ENDIAN
       PRUint8 b = *src++;
       PRUint8 g = *src++;
@@ -4593,18 +4606,18 @@ nsCanvasRenderingContext2DAzure::SetMozI
   SetImageSmoothingEnabled(val);
   return NS_OK;
 }
 
 static PRUint8 g2DContextLayerUserData;
 
 already_AddRefed<CanvasLayer>
 nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
-                                           CanvasLayer *aOldLayer,
-                                           LayerManager *aManager)
+                                                CanvasLayer *aOldLayer,
+                                                LayerManager *aManager)
 {
   if (!mValid) {
     return nsnull;
   }
 
   if (mTarget) {
     mTarget->Flush();
   }
@@ -4664,8 +4677,14 @@ nsCanvasRenderingContext2DAzure::MarkCon
 {
   if (mInvalidateCount > 0) {
     mPredictManyRedrawCalls = mInvalidateCount > kCanvasMaxInvalidateCount;
   }
   mIsEntireFrameInvalid = false;
   mInvalidateCount = 0;
 }
 
+
+bool
+nsCanvasRenderingContext2DAzure::ShouldForceInactiveLayer(LayerManager *aManager)
+{
+    return !aManager->CanUseCanvasLayerForSize(gfxIntSize(mWidth, mHeight));
+}
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.h
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.h
@@ -459,18 +459,17 @@ public:
   void AsyncDrawXULElement(nsIDOMXULElement* elem, double x, double y, double w,
                            double h, const nsAString& bgColor, uint32_t flags,
                            mozilla::ErrorResult& error);
 
   nsresult Redraw();
 
   // nsICanvasRenderingContextInternal
   NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
-  NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height)
-  { return NS_ERROR_NOT_IMPLEMENTED; }
+  NS_IMETHOD InitializeWithSurface(nsIDocShell *shell, gfxASurface *surface, PRInt32 width, PRInt32 height);
 
   NS_IMETHOD Render(gfxContext *ctx,
                     gfxPattern::GraphicsFilter aFilter,
                     PRUint32 aFlags = RenderFlagPremultAlpha);
   NS_IMETHOD GetInputStream(const char* aMimeType,
                             const PRUnichar* aEncoderOptions,
                             nsIInputStream **aStream);
   NS_IMETHOD GetThebesSurface(gfxASurface **surface);
@@ -478,16 +477,17 @@ public:
   mozilla::TemporaryRef<mozilla::gfx::SourceSurface> GetSurfaceSnapshot()
   { return mTarget ? mTarget->Snapshot() : nsnull; }
 
   NS_IMETHOD SetIsOpaque(bool isOpaque);
   NS_IMETHOD Reset();
   already_AddRefed<CanvasLayer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                                 CanvasLayer *aOldLayer,
                                                 LayerManager *aManager);
+  virtual bool ShouldForceInactiveLayer(LayerManager *aManager);
   void MarkContextClean();
   NS_IMETHOD SetIsIPC(bool isIPC);
   // this rect is in canvas device space
   void Redraw(const mozilla::gfx::Rect &r);
   NS_IMETHOD Redraw(const gfxRect &r) { Redraw(ToRect(r)); return NS_OK; }
 
   // this rect is in mTarget's current user space
   void RedrawUser(const gfxRect &r);
@@ -537,16 +537,21 @@ public:
 
   friend class CanvasRenderingContext2DUserDataAzure;
 
 protected:
   nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY,
                              uint32_t aWidth, uint32_t aHeight,
                              JSObject** aRetval);
 
+  /**
+   * Internal method to complete initialisation, expects mTarget to have been set
+   */
+  nsresult Initialize(PRInt32 width, PRInt32 height);
+
   nsresult InitializeWithTarget(mozilla::gfx::DrawTarget *surface,
                                 PRInt32 width, PRInt32 height);
 
   /**
     * The number of living nsCanvasRenderingContexts.  When this goes down to
     * 0, we free the premultiply and unpremultiply tables, if they exist.
     */
   static PRUint32 sNumLivingContexts;
@@ -591,21 +596,24 @@ protected:
   /**
     * Creates the premultiply lookup table, if it doesn't exist.
     */
   void EnsurePremultiplyTable();
 
   /* This function ensures there is a writable pathbuilder available, this
    * pathbuilder may be working in user space or in device space or
    * device space.
+   * After calling this function mPathTransformWillUpdate will be false
    */
   void EnsureWritablePath();
 
   // Ensures a path in UserSpace is available.
-  void EnsureUserSpacePath();
+  // If aCommitTransform is true, then any transform on the context will be
+  // used for the path.
+  void EnsureUserSpacePath(bool aCommitTransform = true);
 
   void TransformWillUpdate();
 
   // Report the fillRule has changed.
   void FillRuleChanged();
 
   /**
     * Returns the surface format this canvas should be allocated using. Takes
--- a/content/canvas/test/Makefile.in
+++ b/content/canvas/test/Makefile.in
@@ -50,16 +50,17 @@ MOCHITEST_FILES = \
 	test_2d.strokeRect.zero.5.html \
 	test_toDataURL_alpha.html \
 	test_toDataURL_lowercase_ascii.html \
 	test_toDataURL_parameters.html \
 	test_mozGetAsFile.html \
 	test_canvas_strokeStyle_getter.html \
 	test_bug613794.html \
 	test_bug753758.html \
+	test_bug764125.html \
 	test_drawImage_edge_cases.html \
 	$(NULL)
 
 ifneq (1_Linux,$(MOZ_SUITE)_$(OS_ARCH))
 # This test fails in Suite on Linux for some reason, disable it there
 MOCHITEST_FILES += test_2d.composite.uncovered.image.destination-atop.html
 endif
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/test_bug764125.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=764125
+
+Test the correct behaviour for isPointInPath in the presence of multiple transforms,
+where only one tranform ought to be applied.
+-->
+<head>
+  <title>Test for Bug 764125</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=764125">Mozilla Bug 764125</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script>
+/** Test for Bug 764125 **/
+
+var c = document.createElement("canvas");
+
+var ctx = c.getContext("2d");
+ctx.translate(50, 0);
+ctx.rect(50, 0, 20, 20);
+ctx.translate(0, 50);
+ok(ctx.isPointInPath(60, 10) === false, "ctx.isPointInPath(60, 10) === false");
+ok(ctx.isPointInPath(110, 10) === true, "ctx.isPointInPath(110, 10) === true");
+ok(ctx.isPointInPath(110, 60) === false, "ctx.isPointInPath(110, 60) === false");
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -13,16 +13,20 @@ function IsD2DEnabled() {
     try {
         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
         enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled;
     } catch(e) {}
     
     return enabled;
 }
 
+function IsLinux() {
+    return navigator.platform.indexOf("Linux") == 0;
+}
+
 function IsMacOSX10_5orOlder() {
     var is105orOlder = false;
 
     if (navigator.platform.indexOf("Mac") == 0) {
         netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
         var version = Components.classes["@mozilla.org/system-info;1"]
                             .getService(Components.interfaces.nsIPropertyBag2)
                             .getProperty("version");
@@ -35,17 +39,18 @@ function IsMacOSX10_5orOlder() {
 }
 
 
 function IsAzureEnabled() {
   var enabled = false;
 
   try {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).AzureEnabled;
+    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
+    enabled = (backend != "none");
   } catch (e) { }
 
   return enabled;
 }
 
 function IsAzureSkia() {
   var enabled = false;
   
@@ -53,16 +58,28 @@ function IsAzureSkia() {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
     enabled = (backend == "skia");
   } catch (e) { }
 
   return enabled;
 }
 
+function IsAzureCairo() {
+  var enabled = false;
+  
+  try {
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureBackend;
+    enabled = (backend == "cairo");
+  } catch (e) { }
+
+  return enabled;
+}
+
 </script>
 <!-- Includes all the tests in the content/canvas/tests except for test_bug397524.html -->
 
 <!-- [[[ test_2d.canvas.readonly.html ]]] -->
 
 <p>Canvas test: 2d.canvas.readonly</p>
 <!-- Testing: CanvasRenderingContext2D.canvas is readonly -->
 <canvas id="c1" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
@@ -11290,19 +11307,33 @@ ctx.lineWidth = 50;
 ctx.strokeStyle = '#f00';
 ctx.beginPath();
 ctx.arc(50, 50, 50, 0, Math.PI, false);
 ctx.stroke();
 isPixel(ctx, 50,25, 0,255,0,255, 0);
 isPixel(ctx, 1,1, 0,255,0,255, 0);
 isPixel(ctx, 98,1, 0,255,0,255, 0);
 isPixel(ctx, 1,48, 0,255,0,255, 0);
-isPixel(ctx, 20,48, 0,255,0,255, 0);
-isPixel(ctx, 98,48, 0,255,0,255, 0);
-
+// Fails on Linux with Azure/Cairo only
+// The arc is drawn badly due to Cairo limitations, the error only becomes
+// apparent on Linux because of anti-aliasing, probably due to X.
+// The limitation is that Cairo draws arcs by stroking perpendicular to the arc,
+// and at very large stroke thicknesses, this becomes a fan. Where exactly the
+// 'blades' of the fan appear seems to depend on exactly how the arc is defined
+// and the platform. So if the blades of the fan are where pixels are tested it
+// passes the test, if the testing pixels fall in between the blades, then we fail.
+// With Thebes/Cairo, we were rendering wrong, but got lucky with the test, now
+// we are not so lucky.
+// Bug 764125
+if (IsAzureCairo() && IsLinux()) {
+    todo_isPixel(ctx, 20,48, 0,255,0,255, 0);
+} else {
+    isPixel(ctx, 20,48, 0,255,0,255, 0);
+}
+isPixel(ctx, 98,48, 0,255,0,255, 0);
 
 }
 </script>
 
 <!-- [[[ test_2d.path.arc.shape.2.html ]]] -->
 
 <p>Canvas test: 2d.path.arc.shape.2</p>
 <!-- Testing: arc() from 0 to pi draws stuff in the right half -->
@@ -14652,19 +14683,24 @@ ctx.restore();
 
 isPixel(ctx, 0,0, 0,255,0,255, 0);
 isPixel(ctx, 50,0, 0,255,0,255, 0);
 isPixel(ctx, 99,0, 0,255,0,255, 0);
 isPixel(ctx, 0,25, 0,255,0,255, 0);
 isPixel(ctx, 50,25, 0,255,0,255, 0);
 isPixel(ctx, 99,25, 0,255,0,255, 0);
 isPixel(ctx, 0,49, 0,255,0,255, 0);
-isPixel(ctx, 50,49, 0,255,0,255, 0);
-isPixel(ctx, 99,49, 0,255,0,255, 0);
-
+if (IsAzureEnabled() && IsAzureCairo()) {
+  // Bug 764108
+  todo_isPixel(ctx, 50,49, 0,255,0,255, 0);
+  todo_isPixel(ctx, 99,49, 0,255,0,255, 0);
+} else {
+  isPixel(ctx, 50,49, 0,255,0,255, 0);
+  isPixel(ctx, 99,49, 0,255,0,255, 0);
+}
 
 }
 </script>
 
 <!-- [[[ test_2d.path.stroke.unaffected.html ]]] -->
 
 <p>Canvas test: 2d.path.stroke.unaffected</p>
 <!-- Testing: Stroking does not start a new path or subpath -->
--- a/content/canvas/test/webgl/failing_tests_mac.txt
+++ b/content/canvas/test/webgl/failing_tests_mac.txt
@@ -1,2 +1,1 @@
 conformance/glsl/misc/glsl-function-nodes.html
-conformance/programs/program-test.html
--- a/content/media/webm/Makefile.in
+++ b/content/media/webm/Makefile.in
@@ -25,10 +25,10 @@ CPPSRCS		= \
 		nsWebMReader.cpp \
 		$(NULL)
 
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
-		$(MOZ_LIBVPX_INCLUDES) \
+		$(MOZ_LIBVPX_CFLAGS) \
 		$(NULL)
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -282,18 +282,18 @@ MediaEngineWebRTCVideoSource::Snapshot(P
   // Create a temporary file on the main thread and put the snapshot in it.
   // See Run() in MediaEngineWebRTCVideo.h (sets mSnapshotPath).
   NS_DispatchToMainThread(this, NS_DISPATCH_SYNC);
 
   if (!mSnapshotPath) {
     return NS_ERROR_FAILURE;
   }
 
-  const char* path = NS_ConvertUTF16toUTF8(*mSnapshotPath).get();
-  if (vieFile->GetCaptureDeviceSnapshot(mCapIndex, path) < 0) {
+  NS_ConvertUTF16toUTF8 path(*mSnapshotPath);
+  if (vieFile->GetCaptureDeviceSnapshot(mCapIndex, path.get()) < 0) {
     delete mSnapshotPath;
     mSnapshotPath = NULL;
     return NS_ERROR_FAILURE;
   }
 
   // Stop the camera.
   mViERender->StopRender(mCapIndex);
   mViERender->RemoveRenderer(mCapIndex);
--- a/content/xslt/src/xslt/txFormatNumberFunctionCall.cpp
+++ b/content/xslt/src/xslt/txFormatNumberFunctionCall.cpp
@@ -291,17 +291,17 @@ txFormatNumberFunctionCall::evaluate(txI
     // XXX We shouldn't use SetLength.
     res.SetLength(res.Length() +
                   intDigits +               // integer digits
                   1 +                       // decimal separator
                   maxFractionSize +         // fractions
                   (intDigits-1)/groupSize); // group separators
 
     PRInt32 i = bufIntDigits + maxFractionSize - 1;
-    bool carry = (i+1 < buflen) && (buf[i+1] >= '5');
+    bool carry = (0 <= i+1) && (i+1 < buflen) && (buf[i+1] >= '5');
     bool hasFraction = false;
 
     PRUint32 resPos = res.Length()-1;
 
     // Fractions
     for (; i >= bufIntDigits; --i) {
         int digit;
         if (i >= buflen || i < 0) {
--- a/dom/alarm/AlarmHalService.cpp
+++ b/dom/alarm/AlarmHalService.cpp
@@ -20,17 +20,17 @@ AlarmHalService::Init()
 
 /* virtual */ AlarmHalService::~AlarmHalService() 
 {
   if (mAlarmEnabled) {
     UnregisterTheOneAlarmObserver();
   }
 }
 
-/* static */ nsRefPtr<AlarmHalService> AlarmHalService::sSingleton;
+/* static */ StaticRefPtr<AlarmHalService> AlarmHalService::sSingleton;
 
 /* static */ already_AddRefed<nsIAlarmHalService>
 AlarmHalService::GetInstance()
 {
   if (!sSingleton) {
     sSingleton = new AlarmHalService();
     sSingleton->Init(); 
     ClearOnShutdown(&sSingleton);
--- a/dom/alarm/AlarmHalService.h
+++ b/dom/alarm/AlarmHalService.h
@@ -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/. */
  
 #ifndef mozilla_dom_alarm_AlarmHalService_h
 #define mozilla_dom_alarm_AlarmHalService_h
 
 #include "base/basictypes.h"
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/StaticPtr.h"
 #include "mozilla/Hal.h"
 #include "mozilla/Services.h"
 #include "nsIAlarmHalService.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "prtime.h"
 
 namespace mozilla {
@@ -23,25 +24,25 @@ class AlarmHalService : public nsIAlarmH
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIALARMHALSERVICE
 
   void Init();
   virtual ~AlarmHalService();
 
-  static nsRefPtr<AlarmHalService> sSingleton;
   static already_AddRefed<nsIAlarmHalService> GetInstance();
 
   // Implementing hal::AlarmObserver
   void Notify(const mozilla::void_t& aVoid);
 
 private:
   bool mAlarmEnabled;
   nsCOMPtr<nsIAlarmFiredCb> mAlarmFiredCb;
+  static StaticRefPtr<AlarmHalService> sSingleton;
 
   // TODO The mTimezoneChangedCb would be called 
   // when a timezone-changed event is detected 
   // at run-time. To do so, we can register a 
   // timezone-changed observer, see bug 714358.
   // We need to adjust the alarm time respect to
   // the correct timezone where user is located.
   nsCOMPtr<nsITimezoneChangedCb> mTimezoneChangedCb;
--- a/dom/alarm/AlarmService.jsm
+++ b/dom/alarm/AlarmService.jsm
@@ -70,26 +70,27 @@ let AlarmService = {
 
     if (!this._alarmHalService.setAlarm(this._getAlarmTime(aAlarm) / 1000, 0))
       throw Components.results.NS_ERROR_FAILURE;
   },
 
   receiveMessage: function receiveMessage(aMessage) {
     debug("receiveMessage(): " + aMessage.name);
 
+    let mm = aMessage.target.QueryInterface(Ci.nsIFrameMessageManager);
     let json = aMessage.json;
     switch (aMessage.name) {
       case "AlarmsManager:GetAll":
         this._db.getAll(
           function getAllSuccessCb(aAlarms) {
             debug("Callback after getting alarms from database: " + JSON.stringify(aAlarms));
-            this._sendAsyncMessage("GetAll:Return:OK", json.requestId, aAlarms);
+            this._sendAsyncMessage(mm, "GetAll", true, json.requestId, aAlarms);
           }.bind(this),
           function getAllErrorCb(aErrorMsg) {
-            this._sendAsyncMessage("GetAll:Return:KO", json.requestId, aErrorMsg);
+            this._sendAsyncMessage(mm, "GetAll", false, json.requestId, aErrorMsg);
           }.bind(this)
         );
         break;
 
       case "AlarmsManager:Add":
         // prepare a record for the new alarm to be added
         let newAlarm = {
           date: json.date, 
@@ -105,48 +106,48 @@ let AlarmService = {
             debug("Callback after adding alarm in database.");
 
             newAlarm['id'] = aNewId;
             let newAlarmTime = this._getAlarmTime(newAlarm);
 
             if (newAlarmTime <= Date.now()) {
               debug("Adding a alarm that has past time. Don't set it in system.");
               this._debugCurrentAlarm();
-              this._sendAsyncMessage("Add:Return:OK", json.requestId, aNewId);
+              this._sendAsyncMessage(mm, "Add", true, json.requestId, aNewId);
               return;
             }
 
             // if there is no alarm being set in system, set the new alarm
             if (this._currentAlarm == null) {
               this._currentAlarm = newAlarm;
               this._debugCurrentAlarm();
-              this._sendAsyncMessage("Add:Return:OK", json.requestId, aNewId);
+              this._sendAsyncMessage(mm, "Add", true, json.requestId, aNewId);
               return;
             }
 
             // if the new alarm is earlier than the current alarm
             // swap them and push the previous alarm back to queue
             let alarmQueue = this._alarmQueue;
             let currentAlarmTime = this._getAlarmTime(this._currentAlarm);
             if (newAlarmTime < currentAlarmTime) {
               alarmQueue.unshift(this._currentAlarm);
               this._currentAlarm = newAlarm;
               this._debugCurrentAlarm();
-              this._sendAsyncMessage("Add:Return:OK", json.requestId, aNewId);
+              this._sendAsyncMessage(mm, "Add", true, json.requestId, aNewId);
               return;
             }
 
             //push the new alarm in the queue
             alarmQueue.push(newAlarm);
             alarmQueue.sort(this._sortAlarmByTimeStamps.bind(this));
             this._debugCurrentAlarm();
-            this._sendAsyncMessage("Add:Return:OK", json.requestId, aNewId);
+            this._sendAsyncMessage(mm, "Add", true, json.requestId, aNewId);
           }.bind(this),
           function addErrorCb(aErrorMsg) {
-            this._sendAsyncMessage("Add:Return:KO", json.requestId, aErrorMsg);
+            this._sendAsyncMessage(mm, "Add", false, json.requestId, aErrorMsg);
           }.bind(this)
         );
         break;
 
       case "AlarmsManager:Remove":
         this._db.remove(
           json.id,
           function removeSuccessCb() {
@@ -190,42 +191,45 @@ let AlarmService = {
         break;
 
       default:
         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
         break;
     }
   },
 
-  _sendAsyncMessage: function _sendAsyncMessage(aMessageName, aRequestId, aData) {
+  _sendAsyncMessage: function _sendAsyncMessage(aMessageManager, aMessageName, aSuccess, aRequestId, aData) {
     debug("_sendAsyncMessage()");
 
+    if (!aMessageManager) {
+      debug("Invalid message manager: null");
+      throw Components.results.NS_ERROR_FAILURE;
+    }
+
     let json = null;
     switch (aMessageName)
     {
-      case "Add:Return:OK":
-        json = { requestId: aRequestId, id: aData };
+      case "Add":
+          json = aSuccess ? 
+            { requestId: aRequestId, id: aData } : 
+            { requestId: aRequestId, errorMsg: aData };
         break;
 
-      case "GetAll:Return:OK":
-        json = { requestId: aRequestId, alarms: aData };
-        break;
-
-      case "Add:Return:KO":
-      case "GetAll:Return:KO":
-        json = { requestId: aRequestId, errorMsg: aData };
+      case "GetAll":
+          json = aSuccess ? 
+            { requestId: aRequestId, alarms: aData } : 
+            { requestId: aRequestId, errorMsg: aData };
         break;
 
       default:
         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
         break;
     }
 
-    if (aMessageName && json)
-      ppmm.sendAsyncMessage("AlarmsManager:" + aMessageName, json);
+    aMessageManager.sendAsyncMessage("AlarmsManager:" + aMessageName + ":Return:" + (aSuccess ? "OK" : "KO"), json);
   },
 
   _onAlarmFired: function _onAlarmFired() {
     debug("_onAlarmFired()");
 
     if (this._currentAlarm) {
       debug("Fire system intent: " + JSON.stringify(this._currentAlarm));
       let manifestURI = Services.io.newURI(this._currentAlarm.manifestURL, null, null);
--- a/dom/apps/src/AppsService.js
+++ b/dom/apps/src/AppsService.js
@@ -3,37 +3,58 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict"
 
 function debug(s) {
   //dump("-*- AppsService: " + s + "\n");
 }
 
+const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Webapps.jsm");
 
-const APPS_SERVICE_CID        = Components.ID("{05072afa-92fe-45bf-ae22-39b69c117058}");
+const APPS_SERVICE_CID = Components.ID("{05072afa-92fe-45bf-ae22-39b69c117058}");
 
 function AppsService()
 {
   debug("AppsService Constructor");
+  this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
+                  .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+  debug("inParent: " + this.inParent);
+  if (this.inParent) {
+    Cu.import("resource://gre/modules/Webapps.jsm");
+  } else {
+    this.cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
+                .getService(Ci.nsIFrameMessageManager)
+                .QueryInterface(Ci.nsISyncMessageSender);
+  }
 }
 
 AppsService.prototype = {
   getAppByManifestURL: function getAppByManifestURL(aManifestURL) {
     debug("GetAppByManifestURL( " + aManifestURL + " )");
-    return DOMApplicationRegistry.getAppByManifestURL(aManifestURL)
+    if (this.inParent) {
+      return DOMApplicationRegistry.getAppByManifestURL(aManifestURL);
+    } else {
+      return this.cpmm.sendSyncMessage("WebApps:GetAppByManifestURL",
+                                       { url: aManifestURL })[0];
+    }
   },
 
   getAppLocalIdByManifestURL: function getAppLocalIdByManifestURL(aManifestURL) {
     debug("getAppLocalIdByManifestURL( " + aManifestURL + " )");
-    return DOMApplicationRegistry.getAppLocalIdByManifestURL(aManifestURL);
+    if (this.inParent) {
+      return DOMApplicationRegistry.getAppLocalIdByManifestURL(aManifestURL);
+    } else {
+      let res = this.cpmm.sendSyncMessage("WebApps:GetAppLocalIdByManifestURL",
+                                          { url: aManifestURL })[0];
+      return res.id;
+    }
   },
 
   classID : APPS_SERVICE_CID,
-  QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService]),
+  QueryInterface : XPCOMUtils.generateQI([Ci.nsIAppsService])
 }
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([AppsService])
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -51,17 +51,18 @@ let DOMApplicationRegistry = {
   webapps: { },
   allAppsLaunchable: false,
 
   init: function() {
     this.messages = ["Webapps:Install", "Webapps:Uninstall",
                     "Webapps:GetSelf",
                     "Webapps:GetInstalled", "Webapps:GetNotInstalled",
                     "Webapps:Launch", "Webapps:GetAll",
-                    "Webapps:InstallPackage", "Webapps:GetBasePath"];
+                    "Webapps:InstallPackage", "Webapps:GetBasePath",
+                    "WebApps:GetAppByManifestURL", "WebApps:GetAppLocalIdByManifestURL"];
 
     this.messages.forEach((function(msgName) {
       ppmm.addMessageListener(msgName, this);
     }).bind(this));
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
 
     this.appsFile = FileUtils.getFile(DIRECTORY_NAME,
@@ -232,16 +233,22 @@ let DOMApplicationRegistry = {
           ppmm.sendAsyncMessage("Webapps:GetAll:Return:KO", msg);
         break;
       case "Webapps:InstallPackage":
         this.installPackage(msg);
         break;
       case "Webapps:GetBasePath":
         return FileUtils.getFile(DIRECTORY_NAME, ["webapps"], true).path;
         break;
+      case "WebApps:GetAppByManifestURL":
+        return this.getAppByManifestURL(msg.url);
+        break;
+      case "WebApps:GetAppLocalIdByManifestURL":
+        return { id: this.getAppLocalIdByManifestURL(msg.url) };
+        break;
     }
   },
 
   _writeFile: function ss_writeFile(aFile, aData, aCallbak) {
     // Initialize the file output stream.
     let ostream = FileUtils.openSafeFileOutputStream(aFile);
 
     // Obtain a converter to convert our data to a UTF-8 encoded input stream.
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -30,16 +30,17 @@
 #include "PowerManager.h"
 #include "nsIDOMWakeLock.h"
 #include "nsIPowerManagerService.h"
 #include "SmsManager.h"
 #include "nsISmsService.h"
 #include "mozilla/Hal.h"
 #include "nsIWebNavigation.h"
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/StaticPtr.h"
 #include "Connection.h"
 #include "MobileConnection.h"
 #include "nsIIdleObserver.h"
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "MediaManager.h"
 #endif
 #ifdef MOZ_B2G_RIL
@@ -603,17 +604,17 @@ public:
 
 private:
   nsWeakPtr mWindow;
   nsWeakPtr mDocument;
 };
 
 NS_IMPL_ISUPPORTS1(VibrateWindowListener, nsIDOMEventListener)
 
-nsRefPtr<VibrateWindowListener> gVibrateWindowListener;
+StaticRefPtr<VibrateWindowListener> gVibrateWindowListener;
 
 NS_IMETHODIMP
 VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsCOMPtr<nsIDOMEventTarget> target;
   aEvent->GetTarget(getter_AddRefs(target));
   nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(target);
 
--- a/dom/bindings/test/Makefile.in
+++ b/dom/bindings/test/Makefile.in
@@ -44,37 +44,36 @@ bindinggen_dependencies := \
   ../Configuration.py \
   ../Codegen.py \
   ../parser/WebIDL.py \
   ../ParserResults.pkl \
   ../Makefile \
   $(GLOBAL_DEPS) \
   $(NULL)
 
-# Include rules.mk before any of our targets so our first target is coming from
-# rules.mk and running make with no target in this dir does the right thing.
-include $(topsrcdir)/config/rules.mk
-
-$(CPPSRCS): ../%Binding.cpp: $(bindinggen_dependencies) \
-                             ../%.webidl \
-                             $(NULL)
-	$(MAKE) -C .. $*Binding.h
-	$(MAKE) -C .. $*Binding.cpp
-
 MOCHITEST_FILES = \
   test_enums.html \
   test_integers.html \
   test_interfaceToString.html \
   test_lookupGetter.html \
   test_InstanceOf.html \
   test_traceProtos.html \
   test_forOf.html \
   forOf_iframe.html \
   $(NULL)
 
+# Include rules.mk before any of our targets so our first target is coming from
+# rules.mk and running make with no target in this dir does the right thing.
+include $(topsrcdir)/config/rules.mk
+
+$(CPPSRCS): ../%Binding.cpp: $(bindinggen_dependencies) \
+                             ../%.webidl \
+                             $(NULL)
+	$(MAKE) -C .. $*Binding.h
+	$(MAKE) -C .. $*Binding.cpp
 
 check::
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py
 
 check-interactive:
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py -q
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -543,22 +543,22 @@ BluetoothDBusService::SendDiscoveryMessa
   if (!mConnection) {
     NS_WARNING("Bluetooth service not started yet!");
     return NS_ERROR_FAILURE;
   }
   NS_ASSERTION(NS_IsMainThread(), "Must be called from main thread!");
 
   nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
 
-  const char* s = NS_ConvertUTF16toUTF8(aAdapterPath).get();
+  NS_ConvertUTF16toUTF8 s(aAdapterPath);
   if (!dbus_func_args_async(mConnection,
                             1000,
                             GetVoidCallback,
                             (void*)aRunnable,
-                            s,
+                            s.get(),
                             DBUS_ADAPTER_IFACE,
                             aMessageName,
                             DBUS_TYPE_INVALID)) {
     NS_WARNING("Could not start async function!");
     return NS_ERROR_FAILURE;
   }
   runnable.forget();
   return NS_OK;
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -108,17 +108,17 @@ public:
 
   NS_IMETHOD
   Run()
   {
     // Create a media stream.
     nsCOMPtr<nsDOMMediaStream> stream = nsDOMMediaStream::CreateInputStream();
 
     nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
-      (nsGlobalWindow::GetOuterWindowWithId(mWindowID));
+      (nsGlobalWindow::GetInnerWindowWithId(mWindowID));
 
     if (window && window->GetExtantDoc()) {
       stream->CombineWithPrincipal(window->GetExtantDoc()->NodePrincipal());
     }
 
     // Add our listener. We'll call Start() on the source when get a callback
     // that the MediaStream has started consuming. The listener is freed
     // when the page is invalidated (on navigation or close).
--- a/dom/plugins/base/PluginPRLibrary.cpp
+++ b/dom/plugins/base/PluginPRLibrary.cpp
@@ -43,17 +43,16 @@ PluginPRLibrary::NP_Initialize(NPNetscap
       PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
     if (!pfNP_Initialize)
       return NS_ERROR_FAILURE;
     *error = pfNP_Initialize(bFuncs, pFuncs, env);
   }
 
   // Save pointers to functions that get called through PluginLibrary itself.
   mNPP_New = pFuncs->newp;
-  mNPP_GetValue = pFuncs->getvalue;
   mNPP_ClearSiteData = pFuncs->clearsitedata;
   mNPP_GetSitesWithData = pFuncs->getsiteswithdata;
   return NS_OK;
 }
 #elif defined(MOZ_WIDGET_GONK)
 nsresult
 PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
 {
--- a/dom/plugins/base/PluginPRLibrary.h
+++ b/dom/plugins/base/PluginPRLibrary.h
@@ -26,17 +26,16 @@ public:
         mNP_GetMIMEDescription(nsnull),
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
         mNP_GetValue(nsnull),
 #endif
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2)
         mNP_GetEntryPoints(nsnull),
 #endif
         mNPP_New(nsnull),
-        mNPP_GetValue(nsnull),
         mNPP_ClearSiteData(nsnull),
         mNPP_GetSitesWithData(nsnull),
         mLibrary(aLibrary),
         mFilePath(aFilePath)
     {
         NS_ASSERTION(mLibrary, "need non-null lib");
         // addref here??
     }
@@ -134,17 +133,16 @@ private:
     NP_GetMIMEDescriptionFunc mNP_GetMIMEDescription;
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
     NP_GetValueFunc mNP_GetValue;
 #endif
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2)
     NP_GetEntryPointsFunc mNP_GetEntryPoints;
 #endif
     NPP_NewProcPtr mNPP_New;
-    NPP_GetValueProcPtr mNPP_GetValue;
     NPP_ClearSiteDataPtr mNPP_ClearSiteData;
     NPP_GetSitesWithDataPtr mNPP_GetSitesWithData;
     PRLibrary* mLibrary;
     nsCString mFilePath;
 };
 
 
 } // namespace mozilla
--- a/dom/power/PowerManagerService.cpp
+++ b/dom/power/PowerManagerService.cpp
@@ -12,17 +12,17 @@
 #include "WakeLock.h"
 
 namespace mozilla {
 namespace dom {
 namespace power {
 
 NS_IMPL_ISUPPORTS1(PowerManagerService, nsIPowerManagerService)
 
-/* static */ nsRefPtr<PowerManagerService> PowerManagerService::sSingleton;
+/* static */ StaticRefPtr<PowerManagerService> PowerManagerService::sSingleton;
 
 /* static */ already_AddRefed<nsIPowerManagerService>
 PowerManagerService::GetInstance()
 {
   if (!sSingleton) {
     sSingleton = new PowerManagerService();
     sSingleton->Init();
     ClearOnShutdown(&sSingleton);
--- a/dom/power/PowerManagerService.h
+++ b/dom/power/PowerManagerService.h
@@ -7,16 +7,17 @@
 
 #include "nsCOMPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsTArray.h"
 #include "nsIPowerManagerService.h"
 #include "mozilla/Observer.h"
 #include "Types.h"
+#include "mozilla/StaticPtr.h"
 
 namespace mozilla {
 namespace dom {
 namespace power {
 
 class PowerManagerService
   : public nsIPowerManagerService
   , public WakeLockObserver
@@ -34,17 +35,17 @@ public:
 
 private:
 
   ~PowerManagerService();
 
   void ComputeWakeLockState(const hal::WakeLockInformation& aWakeLockInfo,
                             nsAString &aState);
 
-  static nsRefPtr<PowerManagerService> sSingleton;
+  static StaticRefPtr<PowerManagerService> sSingleton;
 
   nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mWakeLockListeners;
 };
 
 } // namespace power
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/settings/SettingsManager.js
+++ b/dom/settings/SettingsManager.js
@@ -55,17 +55,17 @@ SettingsLock.prototype = {
           break;
         case "set":
           for (let key in info.settings) {
             debug("key: " + key + ", val: " + JSON.stringify(info.settings[key]) + ", type: " + typeof(info.settings[key]));
 
             let checkKeyRequest = store.get(key);
             checkKeyRequest.onsuccess = function (event) {
               if (!event.target.result) {
-                dump("MOZSETTINGS-SET-WARNING: " + key + " is not in the database. Please add it to build/settings.js\n");
+                debug("MOZSETTINGS-SET-WARNING: " + key + " is not in the database. Please add it to build/settings.js\n");
               }
             }
 
             if(typeof(info.settings[key]) != 'object') {
               req = store.put({settingName: key, settingValue: info.settings[key]});
             } else {
               //Workaround for cloning issues
               let obj = JSON.parse(JSON.stringify(info.settings[key]));
@@ -89,17 +89,17 @@ SettingsLock.prototype = {
                                     : store.mozGetAll(info.name);
 
           req.onsuccess = function(event) {
             debug("Request for '" + info.name + "' successful. " + 
                   "Record count: " + event.target.result.length);
             debug("result: " + JSON.stringify(event.target.result));
 
             if (event.target.result.length == 0) {
-              dump("MOZSETTINGS-GET-WARNING: " + info.name + " is not in the database. Please add it to build/settings.js\n");
+              debug("MOZSETTINGS-GET-WARNING: " + info.name + " is not in the database. Please add it to build/settings.js\n");
             }
 
             let results = {
               __exposedProps__: {
               }
             };
 
             for (var i in event.target.result) {
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -83,16 +83,18 @@ GonkGPSGeolocationProvider::LocationCall
         callback->Update(mPosition);
       }
       return NS_OK;
     }
   private:
     nsRefPtr<nsGeoPosition> mPosition;
   };
 
+  MOZ_ASSERT(location);
+
   nsRefPtr<nsGeoPosition> somewhere = new nsGeoPosition(location->latitude,
                                                         location->longitude,
                                                         location->altitude,
                                                         location->accuracy,
                                                         location->accuracy,
                                                         location->bearing,
                                                         location->speed,
                                                         location->timestamp);
@@ -238,17 +240,17 @@ GonkGPSGeolocationProvider::GonkGPSGeolo
   , mSupportsTimeInjection(false)
   , mGpsInterface(nsnull)
 {
 }
 
 GonkGPSGeolocationProvider::~GonkGPSGeolocationProvider()
 {
   ShutdownNow();
-  sSingleton = NULL;
+  sSingleton = nsnull;
 }
 
 already_AddRefed<GonkGPSGeolocationProvider>
 GonkGPSGeolocationProvider::GetSingleton()
 {
   if (!sSingleton)
     sSingleton = new GonkGPSGeolocationProvider();
 
@@ -257,58 +259,75 @@ GonkGPSGeolocationProvider::GetSingleton
 }
 
 const GpsInterface*
 GonkGPSGeolocationProvider::GetGPSInterface()
 {
   hw_module_t* module;
 
   if (hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module))
-    return NULL;
+    return nsnull;
 
   hw_device_t* device;
   if (module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device))
-    return NULL;
+    return nsnull;
 
   gps_device_t* gps_device = (gps_device_t *)device;
   const GpsInterface* result = gps_device->get_gps_interface(gps_device);
 
   if (result->size != sizeof(GpsInterface)) {
     return nsnull;
   }
   return result;
 }
 
 void
 GonkGPSGeolocationProvider::RequestDataConnection()
 {
+  if (!mRIL) {
+    return;
+  }
+
   // TODO: Bug 772747 - We should ask NetworkManager or RIL to open
   // SUPL type connection for us.
   const nsAdoptingString& apnName = Preferences::GetString("geo.gps.apn.name");
   const nsAdoptingString& apnUser = Preferences::GetString("geo.gps.apn.user");
   const nsAdoptingString& apnPass = Preferences::GetString("geo.gps.apn.password");
   if (apnName && apnUser && apnPass) {
+    mCid.Truncate();
     mRIL->SetupDataCall(1 /* DATACALL_RADIOTECHNOLOGY_GSM */,
                         apnName, apnUser, apnPass,
                         3 /* DATACALL_AUTH_PAP_OR_CHAP */,
                         NS_LITERAL_STRING("IP") /* pdptype */);
   }
 }
 
 void
 GonkGPSGeolocationProvider::ReleaseDataConnection()
 {
+  if (!mRIL) {
+    return;
+  }
+
+  if (mCid.IsEmpty()) {
+    // We didn't request data call or the data call failed, bail out.
+    return;
+  }
   mRIL->DeactivateDataCall(mCid, NS_LITERAL_STRING("Close SUPL session"));
 }
 
 void
 GonkGPSGeolocationProvider::RequestSetID(uint32_t flags)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  if (!mRIL) {
+    return;
+  }
+
   AGpsSetIDType type = AGPS_SETID_TYPE_NONE;
 
   nsCOMPtr<nsIRilContext> rilCtx;
   mRIL->GetRilContext(getter_AddRefs(rilCtx));
 
   if (rilCtx) {
     nsCOMPtr<nsIICCRecords> icc;
     rilCtx->GetIcc(getter_AddRefs(icc));
@@ -328,16 +347,20 @@ GonkGPSGeolocationProvider::RequestSetID
   }
 }
 
 void
 GonkGPSGeolocationProvider::SetReferenceLocation()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  if (!mRIL) {
+    return;
+  }
+
   nsCOMPtr<nsIRilContext> rilCtx;
   mRIL->GetRilContext(getter_AddRefs(rilCtx));
 
   AGpsRefLocation location;
 
   // TODO: Bug 772750 - get mobile connection technology from rilcontext
   location.type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
 
@@ -349,17 +372,19 @@ GonkGPSGeolocationProvider::SetReference
       icc->GetMnc(&location.u.cellID.mnc);
     }
     nsCOMPtr<nsICellLocation> cell;
     rilCtx->GetCell(getter_AddRefs(cell));
     if (cell) {
       cell->GetLac(&location.u.cellID.lac);
       cell->GetCid(&location.u.cellID.cid);
     }
-    mAGpsRilInterface->set_ref_location(&location, sizeof(location));
+    if (mAGpsRilInterface) {
+      mAGpsRilInterface->set_ref_location(&location, sizeof(location));
+    }
   }
 }
 
 void
 GonkGPSGeolocationProvider::Init()
 {
   // Must not be main thread. Some GPS driver's first init takes very long.
   MOZ_ASSERT(!NS_IsMainThread());
@@ -386,16 +411,18 @@ GonkGPSGeolocationProvider::Init()
   }
 
   NS_DispatchToMainThread(NS_NewRunnableMethod(this, &GonkGPSGeolocationProvider::StartGPS));
 }
 
 void
 GonkGPSGeolocationProvider::StartGPS()
 {
+  MOZ_ASSERT(mGpsInterface);
+
   PRInt32 update = Preferences::GetInt("geo.default.update", kDefaultPeriod);
 
   if (mSupportsMSA || mSupportsMSB) {
     SetupAGPS();
   }
 
   int positionMode = GPS_POSITION_MODE_STANDALONE;
   bool singleShot = false;
@@ -420,30 +447,35 @@ GonkGPSGeolocationProvider::StartGPS()
 
   mGpsInterface->start();
 }
 
 void
 GonkGPSGeolocationProvider::SetupAGPS()
 {
   MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mAGpsRilInterface);
 
   const nsAdoptingCString& suplServer = Preferences::GetCString("geo.gps.supl_server");
   PRInt32 suplPort = Preferences::GetInt("geo.gps.supl_port", -1);
   if (!suplServer.IsEmpty() && suplPort > 0) {
     mAGpsInterface->set_server(AGPS_TYPE_SUPL, suplServer.get(), suplPort);
   } else {
     NS_WARNING("Cannot get SUPL server settings");
     return;
   }
 
   // Setup network state listener
   nsIInterfaceRequestor* ireq = dom::gonk::SystemWorkerManager::GetInterfaceRequestor();
-  mRIL = do_GetInterface(ireq);
-  mRIL->RegisterDataCallCallback(this);
+  if (ireq) {
+    mRIL = do_GetInterface(ireq);
+    if (mRIL) {
+      mRIL->RegisterDataCallCallback(this);
+    }
+  }
 
   return;
 }
 
 NS_IMETHODIMP
 GonkGPSGeolocationProvider::Startup()
 {
   if (mStarted) {
@@ -467,55 +499,61 @@ GonkGPSGeolocationProvider::Watch(nsIGeo
 {
   mLocationCallback = aCallback;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GonkGPSGeolocationProvider::Shutdown()
 {
+  MOZ_ASSERT(mInitThread);
+
   if (!mStarted) {
     return NS_OK;
   }
 
   mInitThread->Dispatch(NS_NewRunnableMethod(this, &GonkGPSGeolocationProvider::ShutdownNow),
                         NS_DISPATCH_NORMAL);
 
   return NS_OK;
 }
 
 void
 GonkGPSGeolocationProvider::ShutdownNow()
 {
-  if (!mGpsInterface) {
+  if (!mStarted) {
     return;
   }
+  mStarted = false;
 
   if (mRIL) {
     mRIL->UnregisterDataCallCallback(this);
   }
 
-  mGpsInterface->stop();
-  mGpsInterface->cleanup();
-  mStarted = false;
+  if (mGpsInterface) {
+    mGpsInterface->stop();
+    mGpsInterface->cleanup();
+  }
+
   mInitThread = nsnull;
 }
 
 NS_IMETHODIMP
 GonkGPSGeolocationProvider::SetHighAccuracy(bool)
 {
   return NS_OK;
 }
 
 /** nsIRILDataCallback interface **/
 
 NS_IMETHODIMP
 GonkGPSGeolocationProvider::DataCallStateChanged(nsIRILDataCallInfo* aDataCall)
 {
   MOZ_ASSERT(aDataCall);
+  MOZ_ASSERT(mAGpsInterface);
   nsCOMPtr<nsIRILDataCallInfo> datacall = aDataCall;
 
   PRUint32 callState;
   nsresult rv = datacall->GetState(&callState);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString apn;
   rv = datacall->GetApn(apn);
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1836,17 +1836,17 @@ let RIL = {
    *        One of DATACALL_DEACTIVATE_* constants.
    */
   deactivateDataCall: function deactivateDataCall(options) {
     let datacall = this.currentDataCalls[options.cid];
     if (!datacall) {
       return;
     }
 
-    let token = Buf.newParcel(REQUEST_DEACTIVATE_DATA_CALL);
+    let token = Buf.newParcel(REQUEST_DEACTIVATE_DATA_CALL, options);
     Buf.writeUint32(2);
     Buf.writeString(options.cid);
     Buf.writeString(options.reason || DATACALL_DEACTIVATE_NO_REASON);
     Buf.sendParcel();
 
     datacall.state = GECKO_NETWORK_STATE_DISCONNECTING;
     this.sendDOMMessage(datacall);
   },
--- a/editor/Makefile.in
+++ b/editor/Makefile.in
@@ -1,18 +1,18 @@
 #
 # 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/.
 
-DEPTH		= ..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-FAIL_ON_WARNINGS = 1
+DEPTH            := ..
+topsrcdir        := @top_srcdir@
+srcdir           := @srcdir@
+VPATH            := @srcdir@
+FAIL_ON_WARNINGS := 1
 
 include $(DEPTH)/config/autoconf.mk
 
-MODULE		= editor
-DIRS		= public idl txtsvc libeditor txmgr composer
+MODULE           := editor
+PARALLEL_DIRS    := public idl txtsvc libeditor txmgr composer
 
 include $(topsrcdir)/config/rules.mk
 
--- a/editor/composer/Makefile.in
+++ b/editor/composer/Makefile.in
@@ -1,23 +1,23 @@
 #
 # 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/.
 
-DEPTH		= ../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
+DEPTH           := ../..
+topsrcdir       := @top_srcdir@
+srcdir          := @srcdir@
+VPATH           := @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS		= public src
+PARALLEL_DIRS   := public src
 
-TEST_DIRS += test
+TEST_DIRS       += test
 
 # Enable Editor API Logging!
 ENABLE_EDITOR_API_LOG=1
 
 ifdef ENABLE_EDITOR_API_LOG
 DEFINES += -DENABLE_EDITOR_API_LOG
 endif
 
--- a/editor/idl/Makefile.in
+++ b/editor/idl/Makefile.in
@@ -1,39 +1,39 @@
 #
 # 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/.
 
-DEPTH		= ../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
+DEPTH           := ../..
+topsrcdir       := @top_srcdir@
+srcdir          := @srcdir@
+VPATH           := @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-MODULE		= editor
-GRE_MODULE	= 1
+MODULE          := editor
+GRE_MODULE      := 1
 
-XPIDLSRCS	= \
-		nsIDocumentStateListener.idl \
-		nsIEditActionListener.idl \
-		nsIEditor.idl \
-		nsIEditorIMESupport.idl \
-		nsIEditorLogging.idl \
-		nsIEditorMailSupport.idl \
-		nsIEditorObserver.idl \
-		nsIEditorSpellCheck.idl \
-		nsIEditorStyleSheets.idl \
-		nsIHTMLEditor.idl \
-		nsIHTMLObjectResizer.idl \
-		nsIHTMLAbsPosEditor.idl \
-		nsIHTMLObjectResizeListener.idl \
-		nsIHTMLInlineTableEditor.idl \
-		nsIPlaintextEditor.idl \
-		nsITableEditor.idl \
-		nsIURIRefObject.idl \
-		nsIContentFilter.idl \
-		nsPIEditorTransaction.idl \
-		$(NULL)
+XPIDLSRCS       := \
+                nsIDocumentStateListener.idl \
+                nsIEditActionListener.idl \
+                nsIEditor.idl \
+                nsIEditorIMESupport.idl \
+                nsIEditorLogging.idl \
+                nsIEditorMailSupport.idl \
+                nsIEditorObserver.idl \
+                nsIEditorSpellCheck.idl \
+                nsIEditorStyleSheets.idl \
+                nsIHTMLEditor.idl \
+                nsIHTMLObjectResizer.idl \
+                nsIHTMLAbsPosEditor.idl \
+                nsIHTMLObjectResizeListener.idl \
+                nsIHTMLInlineTableEditor.idl \
+                nsIPlaintextEditor.idl \
+                nsITableEditor.idl \
+                nsIURIRefObject.idl \
+                nsIContentFilter.idl \
+                nsPIEditorTransaction.idl \
+                $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/editor/libeditor/Makefile.in
+++ b/editor/libeditor/Makefile.in
@@ -1,17 +1,17 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-DEPTH		= ../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
+DEPTH           := ../..
+topsrcdir       := @top_srcdir@
+srcdir          := @srcdir@
+VPATH           := @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS		= base text html
+PARALLEL_DIRS   := base text html
 
 
 include $(topsrcdir)/config/rules.mk
 
--- a/editor/public/Makefile.in
+++ b/editor/public/Makefile.in
@@ -1,22 +1,20 @@
 #
 # 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/.
 
-DEPTH		= ../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
+DEPTH           := ../..
+topsrcdir       := @top_srcdir@
+srcdir          := @srcdir@
+VPATH           := @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-MODULE		= editor
+MODULE          := editor
 
-EXPORTS		= \
-		nsEditorCID.h \
-		$(NULL)
-
-EXPORTS		:= $(addprefix $(srcdir)/, $(EXPORTS))
+EXPORTS         := \
+                nsEditorCID.h \
+                $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/editor/txmgr/Makefile.in
+++ b/editor/txmgr/Makefile.in
@@ -1,21 +1,21 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-DEPTH		= ../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
+DEPTH           := ../..
+topsrcdir       := @top_srcdir@
+srcdir          := @srcdir@
+VPATH           := @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-MODULE		= txmgr
-DIRS		= public src idl
+MODULE          := txmgr
+PARALLEL_DIRS   := public src idl
 
 ifdef ENABLE_TESTS
-TOOL_DIRS	+= tests
+TOOL_DIRS       += tests
 endif
 
 include $(topsrcdir)/config/rules.mk
 
--- a/editor/txtsvc/Makefile.in
+++ b/editor/txtsvc/Makefile.in
@@ -1,17 +1,17 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-DEPTH		= ../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
+DEPTH           := ../..
+topsrcdir       := @top_srcdir@
+srcdir          := @srcdir@
+VPATH           := @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-MODULE		= txtsvc
-DIRS		= public src
+MODULE          := txtsvc
+PARALLEL_DIRS   := public src
 
 include $(topsrcdir)/config/rules.mk
 
--- a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -14,16 +14,19 @@
 #include "nsCOMPtr.h"
 #include "nsIServiceManager.h"
 #include "nsIComponentManager.h"
 #include "nsString.h"
 #include "nsIPrefService.h"
 #include "nsIJSContextStack.h"
 #include "nspr.h"
 #include "mozilla/Attributes.h"
+#include "nsContentUtils.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsJSPrincipals.h"
 
 extern PRLogModuleInfo *MCD;
 
 // Security Manager for new XPCONNECT enabled JS Context
 // Right now it allows all access
 
 class AutoConfigSecMan MOZ_FINAL : public nsIXPCSecurityManager
 {
@@ -187,18 +190,21 @@ nsresult EvaluateAdminConfigScript(const
         do_GetService("@mozilla.org/js/xpc/ContextStack;1");
     rv = cxstack->Push(autoconfig_cx);
     if (NS_FAILED(rv)) {
         NS_ERROR("coudn't push the context on the stack");
         return rv;
     }
 
     JS_BeginRequest(autoconfig_cx);
-    ok = JS_EvaluateScript(autoconfig_cx, autoconfig_glob,
-                           js_buffer, length, filename, 0, nsnull);
+    nsCOMPtr<nsIPrincipal> principal;
+    nsContentUtils::GetSecurityManager()->GetSystemPrincipal(getter_AddRefs(principal));
+    ok = JS_EvaluateScriptForPrincipals(autoconfig_cx, autoconfig_glob, 
+                                        nsJSPrincipals::get(principal),
+                                        js_buffer, length, filename, 0, nsnull);
     JS_EndRequest(autoconfig_cx);
 
     JS_MaybeGC(autoconfig_cx);
 
     JSContext *cx;
     cxstack->Pop(&cx);
     NS_ASSERTION(cx == autoconfig_cx, "AutoConfig JS contexts didn't match");
 
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -797,17 +797,17 @@ protected:
   SurfaceFormat mFormat;
 };
 
 class GFX2D_API Factory
 {
 public:
   static bool HasSSE2();
 
-  static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface);
+  static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize);
 
   static TemporaryRef<DrawTarget>
     CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
   
   static TemporaryRef<DrawTarget>
     CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
 
   static TemporaryRef<ScaledFont>
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -8,16 +8,18 @@
 #include "SourceSurfaceCairo.h"
 #include "PathCairo.h"
 #include "HelpersCairo.h"
 #include "ScaledFontBase.h"
 
 #include "cairo.h"
 
 #include "Blur.h"
+#include "Logging.h"
+#include "Tools.h"
 
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
 #include "cairo-quartz.h"
 #include <ApplicationServices/ApplicationServices.h>
 #endif
 
 #ifdef CAIRO_HAS_XLIB_SURFACE
 #include "cairo-xlib.h"
@@ -111,16 +113,61 @@ PatternIsCompatible(const Pattern& aPatt
       const RadialGradientPattern& pattern = static_cast<const RadialGradientPattern&>(aPattern);
       return pattern.mStops->GetBackendType() == BACKEND_CAIRO;
     }
     default:
       return true;
   }
 }
 
+static cairo_user_data_key_t surfaceDataKey;
+
+void
+ReleaseData(void* aData)
+{
+  static_cast<DataSourceSurface*>(aData)->Release();
+}
+
+/**
+ * Returns cairo surface for the given SourceSurface.
+ * If possible, it will use the cairo_surface associated with aSurface,
+ * otherwise, it will create a new cairo_surface.
+ * In either case, the caller must call cairo_surface_destroy on the
+ * result when it is done with it.
+ */
+cairo_surface_t*
+GetCairoSurfaceForSourceSurface(SourceSurface *aSurface)
+{
+  if (aSurface->GetType() == SURFACE_CAIRO) {
+    cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
+    cairo_surface_reference(surf);
+    return surf;
+  }
+
+  if (aSurface->GetType() == SURFACE_CAIRO_IMAGE) {
+    cairo_surface_t* surf =
+      static_cast<const DataSourceSurfaceCairo*>(aSurface)->GetSurface();
+    cairo_surface_reference(surf);
+    return surf;
+  }
+
+  RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
+  cairo_surface_t* surf =
+    cairo_image_surface_create_for_data(data->GetData(),
+                                        GfxFormatToCairoFormat(data->GetFormat()),
+                                        data->GetSize().width,
+                                        data->GetSize().height,
+                                        data->Stride());
+  cairo_surface_set_user_data(surf,
+ 				                      &surfaceDataKey,
+ 				                      data.forget().drop(),
+ 				                      ReleaseData);
+  return surf;
+}
+
 // Never returns NULL. As such, you must always pass in Cairo-compatible
 // patterns, most notably gradients with a GradientStopCairo.
 // The pattern returned must have cairo_pattern_destroy() called on it by the
 // caller.
 // As the cairo_pattern_t returned may depend on the Pattern passed in, the
 // lifetime of the cairo_pattern_t returned must not exceed the lifetime of the
 // Pattern passed in.
 static cairo_pattern_t*
@@ -135,38 +182,17 @@ GfxPatternToCairoPattern(const Pattern& 
       Color color = static_cast<const ColorPattern&>(aPattern).mColor;
       pat = cairo_pattern_create_rgba(color.r, color.g, color.b, color.a * aAlpha);
       break;
     }
 
     case PATTERN_SURFACE:
     {
       const SurfacePattern& pattern = static_cast<const SurfacePattern&>(aPattern);
-      cairo_surface_t* surf;
-
-      // After this block, |surf| always has an extra cairo reference to be
-      // destroyed. This makes creating new surfaces or reusing old ones more
-      // uniform.
-      if (pattern.mSurface->GetType() == SURFACE_CAIRO) {
-        const SourceSurfaceCairo* source = static_cast<const SourceSurfaceCairo*>(pattern.mSurface.get());
-        surf = source->GetSurface();
-        cairo_surface_reference(surf);
-      } else if (pattern.mSurface->GetType() == SURFACE_CAIRO_IMAGE) {
-        const DataSourceSurfaceCairo* source =
-          static_cast<const DataSourceSurfaceCairo*>(pattern.mSurface.get());
-        surf = source->GetSurface();
-        cairo_surface_reference(surf);
-      } else {
-        RefPtr<DataSourceSurface> source = pattern.mSurface->GetDataSurface();
-        surf = cairo_image_surface_create_for_data(source->GetData(),
-                                                   GfxFormatToCairoFormat(source->GetFormat()),
-                                                   source->GetSize().width,
-                                                   source->GetSize().height,
-                                                   source->Stride());
-      }
+      cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(pattern.mSurface);
 
       pat = cairo_pattern_create_for_surface(surf);
       cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(pattern.mFilter));
       cairo_pattern_set_extend(pat, GfxExtendToCairoExtend(pattern.mExtendMode));
 
       cairo_surface_destroy(surf);
 
       break;
@@ -213,16 +239,31 @@ GfxPatternToCairoPattern(const Pattern& 
       // We should support all pattern types!
       MOZ_ASSERT(false);
     }
   }
 
   return pat;
 }
 
+/**
+ * Returns true iff the the given operator should affect areas of the
+ * destination where the source is transparent. Among other things, this
+ * implies that a fully transparent source would still affect the canvas.
+ */
+static bool
+OperatorAffectsUncoveredAreas(CompositionOp op)
+{
+  return op == OP_IN ||
+         op == OP_OUT ||
+         op == OP_DEST_IN ||
+         op == OP_DEST_ATOP ||
+         op == OP_DEST_OUT;
+}
+
 static bool
 NeedIntermediateSurface(const Pattern& aPattern, const DrawOptions& aOptions)
 {
   // We pre-multiply colours' alpha by the global alpha, so we don't need to
   // use an intermediate surface for them.
   if (aPattern.GetType() == PATTERN_COLOR)
     return false;
 
@@ -239,39 +280,38 @@ DrawTargetCairo::DrawTargetCairo()
 
 DrawTargetCairo::~DrawTargetCairo()
 {
   MarkSnapshotsIndependent();
   if (mPathObserver) {
     mPathObserver->ForgetDrawTarget();
   }
   cairo_destroy(mContext);
+  if (mSurface) {
+    cairo_surface_destroy(mSurface);
+  }
 }
 
 IntSize
 DrawTargetCairo::GetSize()
 {
-  return IntSize();
+  return mSize;
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCairo::Snapshot()
 {
-  cairo_surface_t* csurf = cairo_get_target(mContext);
-  IntSize size;
-  if (GetCairoSurfaceSize(csurf, size)) {
-    cairo_content_t content = cairo_surface_get_content(csurf);
-    RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(csurf, size,
-                                                             CairoContentToGfxFormat(content),
-                                                             this);
-    AppendSnapshot(surf);
-    return surf;
-  }
+  IntSize size = GetSize();
 
-  return NULL;
+  cairo_content_t content = cairo_surface_get_content(mSurface);
+  RefPtr<SourceSurfaceCairo> surf = new SourceSurfaceCairo(mSurface, size,
+                                                           CairoContentToGfxFormat(content),
+                                                           this);
+  AppendSnapshot(surf);
+  return surf;
 }
 
 void
 DrawTargetCairo::Flush()
 {
   cairo_surface_t* surf = cairo_get_target(mContext);
   cairo_surface_flush(surf);
 }
@@ -290,120 +330,145 @@ DrawTargetCairo::DrawSurface(SourceSurfa
                              const DrawOptions &aOptions)
 {
   AutoPrepareForDrawing prep(this, mContext);
 
   float sx = aSource.Width() / aDest.Width();
   float sy = aSource.Height() / aDest.Height();
 
   cairo_matrix_t src_mat;
-  cairo_matrix_init_scale(&src_mat, sx, sy);
-  cairo_matrix_translate(&src_mat, aSource.X(), aSource.Y());
+  cairo_matrix_init_translate(&src_mat, aSource.X(), aSource.Y());
+  cairo_matrix_scale(&src_mat, sx, sy);
 
-  cairo_surface_t* surf = NULL;
-  if (aSurface->GetType() == SURFACE_CAIRO) {
-    surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
-  }
+  cairo_surface_t* surf = GetCairoSurfaceForSourceSurface(aSurface);
+  cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
+  cairo_surface_destroy(surf);
 
-  cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
   cairo_pattern_set_matrix(pat, &src_mat);
   cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter));
+  cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
 
   cairo_save(mContext);
+  cairo_translate(mContext, aDest.X(), aDest.Y());
+
+  if (OperatorAffectsUncoveredAreas(aOptions.mCompositionOp) ||
+      aOptions.mCompositionOp == OP_SOURCE) {
+    cairo_push_group(mContext);
+      cairo_new_path(mContext);
+      cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
+      //TODO[nrc] remove comments if test ok
+      //cairo_clip(mContext);
+      cairo_set_source(mContext, pat);
+      //cairo_paint(mContext);
+      cairo_fill(mContext);
+    cairo_pop_group_to_source(mContext);
+  } else {
+    cairo_new_path(mContext);
+    cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
+    cairo_clip(mContext);
+    cairo_set_source(mContext, pat);
+  }
 
   cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
 
-  cairo_translate(mContext, aDest.X(), aDest.Y());
-
-  cairo_set_source(mContext, pat);
-
-  cairo_new_path(mContext);
-  cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
-  cairo_clip(mContext);
   cairo_paint_with_alpha(mContext, aOptions.mAlpha);
 
   cairo_restore(mContext);
 
   cairo_pattern_destroy(pat);
 }
 
 void
 DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
                                        const Point &aDest,
                                        const Color &aColor,
                                        const Point &aOffset,
                                        Float aSigma,
                                        CompositionOp aOperator)
 {
-  WillChange();
-
   if (aSurface->GetType() != SURFACE_CAIRO) {
     return;
   }
 
-  SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
+  WillChange();
 
   Float width = aSurface->GetSize().width;
   Float height = aSurface->GetSize().height;
   Rect extents(0, 0, width, height);
 
   AlphaBoxBlur blur(extents, IntSize(0, 0),
                     AlphaBoxBlur::CalculateBlurRadius(Point(aSigma, aSigma)),
                     NULL, NULL);
   if (!blur.GetData()) {
     return;
   }
 
   IntSize blursize = blur.GetSize();
-
   cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(),
                                                                   CAIRO_FORMAT_A8,
                                                                   blursize.width,
                                                                   blursize.height,
                                                                   blur.GetStride());
 
+  ClearSurfaceForUnboundedSource(aOperator);
+  
   // Draw the source surface into the surface we're going to blur.
+  SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
   cairo_surface_t* surf = source->GetSurface();
   cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
+  cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
 
   cairo_t* ctx = cairo_create(blursurf);
 
   cairo_set_source(ctx, pat);
 
   IntRect blurrect = blur.GetRect();
   cairo_new_path(ctx);
   cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height);
   cairo_clip(ctx);
   cairo_paint(ctx);
 
   cairo_destroy(ctx);
 
   // Blur the result, then use that blurred result as a mask to draw the shadow
   // colour to the surface.
   blur.Blur();
-
   cairo_save(mContext);
-
-  cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
-  cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
-
+  cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
   cairo_identity_matrix(mContext);
   cairo_translate(mContext, aDest.x, aDest.y);
 
-  cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
-
-  // Now that the shadow has been drawn, we can draw the surface on top.
-
-  cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
+  if (OperatorAffectsUncoveredAreas(aOperator) ||
+      aOperator == OP_SOURCE){
+    cairo_push_group(mContext);
+      cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
+      cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
+    cairo_pop_group_to_source(mContext);
+    cairo_paint(mContext);
 
-  cairo_set_source(mContext, pat);
+    // Now that the shadow has been drawn, we can draw the surface on top.
+    cairo_push_group(mContext);
+      cairo_new_path(mContext);
+      cairo_rectangle(mContext, 0, 0, width, height);
+      //TODO[nrc] remove comments if test ok
+      //cairo_clip(mContext);
+      cairo_set_source(mContext, pat);
+      //cairo_paint(mContext);
+      cairo_fill(mContext);
+    cairo_pop_group_to_source(mContext);
+  } else {
+    cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
+    cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
 
-  cairo_new_path(mContext);
-  cairo_rectangle(mContext, 0, 0, width, height);
-  cairo_clip(mContext);
+    // Now that the shadow has been drawn, we can draw the surface on top.
+    cairo_set_source(mContext, pat);
+    cairo_new_path(mContext);
+    cairo_rectangle(mContext, 0, 0, width, height);
+    cairo_clip(mContext);
+  }
 
   cairo_paint(mContext);
 
   cairo_restore(mContext);
 
   cairo_pattern_destroy(pat);
 }
 
@@ -415,35 +480,39 @@ DrawTargetCairo::DrawPattern(const Patte
 {
   if (!PatternIsCompatible(aPattern)) {
     return;
   }
 
   cairo_pattern_t* pat = GfxPatternToCairoPattern(aPattern, aOptions.mAlpha);
   cairo_set_source(mContext, pat);
 
-  if (NeedIntermediateSurface(aPattern, aOptions)) {
+  if (NeedIntermediateSurface(aPattern, aOptions) ||
+      OperatorAffectsUncoveredAreas(aOptions.mCompositionOp)) {
     cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
 
+    ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
+
     // Don't want operators to be applied twice
     cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
 
     if (aDrawType == DRAW_STROKE) {
       SetCairoStrokeOptions(mContext, aStrokeOptions);
       cairo_stroke_preserve(mContext);
     } else {
       cairo_fill_preserve(mContext);
     }
 
     cairo_pop_group_to_source(mContext);
 
     // Now draw the content using the desired operator
     cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
     cairo_paint_with_alpha(mContext, aOptions.mAlpha);
   } else {
+    ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
     cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
 
     if (aDrawType == DRAW_STROKE) {
       SetCairoStrokeOptions(mContext, aStrokeOptions);
       cairo_stroke_preserve(mContext);
     } else {
       cairo_fill_preserve(mContext);
     }
@@ -462,20 +531,41 @@ DrawTargetCairo::FillRect(const Rect &aR
   cairo_new_path(mContext);
   cairo_rectangle(mContext, aRect.x, aRect.y, aRect.Width(), aRect.Height());
 
   DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL);
 }
 
 void
 DrawTargetCairo::CopySurface(SourceSurface *aSurface,
-                             const IntRect &aSourceRect,
-                             const IntPoint &aDestination)
+                             const IntRect &aSource,
+                             const IntPoint &aDest)
 {
   AutoPrepareForDrawing prep(this, mContext);
+
+  if (!aSurface || aSurface->GetType() != SURFACE_CAIRO) {
+    gfxWarning() << "Unsupported surface type specified";
+    return;
+  }
+
+  cairo_surface_t* surf = static_cast<SourceSurfaceCairo*>(aSurface)->GetSurface();
+
+  cairo_save(mContext);
+
+  cairo_identity_matrix(mContext);
+
+  cairo_set_source_surface(mContext, surf, aDest.x - aSource.x, aDest.y - aSource.y);
+  cairo_set_operator(mContext, CAIRO_OPERATOR_SOURCE);
+
+  cairo_reset_clip(mContext);
+  cairo_new_path(mContext);
+  cairo_rectangle(mContext, aDest.x, aDest.y, aSource.width, aSource.height);
+  cairo_fill(mContext);
+
+  cairo_restore(mContext);
 }
 
 void
 DrawTargetCairo::ClearRect(const Rect& aRect)
 {
   AutoPrepareForDrawing prep(this, mContext);
 
   cairo_save(mContext);
@@ -631,36 +721,70 @@ DrawTargetCairo::CreatePathBuilder(FillR
   // Creating a PathBuilder implicitly resets our mPathObserver, as it calls
   // SetPathObserver() on us. Since this guarantees our old path is saved off,
   // it's safe to reset the path here.
   cairo_new_path(mContext);
 
   return builder;
 }
 
+void
+DrawTargetCairo::ClearSurfaceForUnboundedSource(const CompositionOp &aOperator)
+{
+  if (aOperator != OP_SOURCE)
+    return;
+  cairo_set_operator(mContext, CAIRO_OPERATOR_CLEAR);
+  // It doesn't really matter what the source is here, since Paint
+  // isn't bounded by the source and the mask covers the entire clip
+  // region.
+  cairo_paint(mContext);
+}
+
+
 TemporaryRef<GradientStops>
 DrawTargetCairo::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
 {
   RefPtr<GradientStopsCairo> stops = new GradientStopsCairo(aStops, aNumStops);
   return stops;
 }
 
+/**
+ * Copies pixel data from aData into aSurface; aData must have the dimensions
+ * given in aSize, with a stride of aStride bytes and aPixelWidth bytes per pixel
+ */
+static void
+CopyDataToCairoSurface(cairo_surface_t* aSurface,
+                       unsigned char *aData,
+                       const IntSize &aSize,
+                       int32_t aStride,
+                       int32_t aPixelWidth)
+{
+  unsigned char* surfData = cairo_image_surface_get_data(aSurface);
+  for (int32_t y = 0; y < aSize.height; ++y) {
+    memcpy(surfData + y * aSize.width * aPixelWidth,
+           aData + y * aStride,
+           aSize.width * aPixelWidth);
+  }
+  cairo_surface_mark_dirty(aSurface);
+}
+
 TemporaryRef<SourceSurface>
 DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
                                              const IntSize &aSize,
                                              int32_t aStride,
                                              SurfaceFormat aFormat) const
 {
-  cairo_surface_t* surf = cairo_image_surface_create_for_data(aData,
-                                                              GfxFormatToCairoFormat(aFormat),
-                                                              aSize.width,
-                                                              aSize.height,
-                                                              aStride);
+  cairo_surface_t* surf = cairo_image_surface_create(GfxFormatToCairoFormat(aFormat),
+                                                     aSize.width,
+                                                     aSize.height);
+  CopyDataToCairoSurface(surf, aData, aSize, aStride, BytesPerPixel(aFormat));
+    
   RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
   cairo_surface_destroy(surf);
+
   return source_surf;
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCairo::OptimizeSourceSurface(SourceSurface *aSurface) const
 {
   return aSurface;
 }
@@ -685,27 +809,31 @@ TemporaryRef<DrawTarget>
 DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
 {
   cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext),
                                                           GfxFormatToCairoContent(aFormat),
                                                           aSize.width, aSize.height);
 
   if (!cairo_surface_status(similar)) {
     RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
-    target->Init(similar);
+    target->Init(similar, aSize);
     return target;
   }
 
   return NULL;
 }
 
 bool
-DrawTargetCairo::Init(cairo_surface_t* aSurface)
+DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize)
 {
   mContext = cairo_create(aSurface);
+  mSurface = aSurface;
+  cairo_surface_reference(mSurface);
+  mSize = aSize;
+  mFormat = CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
 
   return true;
 }
 
 void *
 DrawTargetCairo::GetNativeSurface(NativeSurfaceType aType)
 {
   if (aType == NATIVE_SURFACE_CAIRO_SURFACE) {
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -118,17 +118,17 @@ public:
 
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
                         ExtendMode aExtendMode = EXTEND_CLAMP) const;
 
   virtual void *GetNativeSurface(NativeSurfaceType aType);
 
-  bool Init(cairo_surface_t* aSurface);
+  bool Init(cairo_surface_t* aSurface, const IntSize& aSize);
 
   void SetPathObserver(CairoPathContext* aPathObserver);
 
   virtual void SetTransform(const Matrix& aTransform);
 
   // Call to set up aContext for drawing (with the current transform, etc).
   // Pass the path you're going to be using if you have one.
   // Implicitly calls WillChange(aPath).
@@ -150,18 +150,23 @@ private: // methods
   // context is associated. Pass the path you're going to be using if you have
   // one.
   void WillChange(const Path* aPath = NULL);
 
   // Call if there is any reason to disassociate all snapshots from this draw
   // target; for example, because we're going to be destroyed.
   void MarkSnapshotsIndependent();
 
+  // If the current operator is "source" then clear the destination before we
+  // draw into it, to simulate the effect of an unbounded source operator.
+  void ClearSurfaceForUnboundedSource(const CompositionOp &aOperator);
 private: // data
   cairo_t* mContext;
+  cairo_surface_t* mSurface;
+  IntSize mSize;
   std::vector<SourceSurfaceCairo*> mSnapshots;
   mutable RefPtr<CairoPathContext> mPathObserver;
 };
 
 }
 }
 
 #endif // _MOZILLA_GFX_DRAWTARGET_CAIRO_H_
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -234,41 +234,41 @@ TemporaryRef<ScaledFont>
 Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize)
 {
   switch (aNativeFont.mType) {
 #ifdef WIN32
   case NATIVE_FONT_DWRITE_FONT_FACE:
     {
       return new ScaledFontDWrite(static_cast<IDWriteFontFace*>(aNativeFont.mFont), aSize);
     }
+  case NATIVE_FONT_GDI_FONT_FACE:
+    {
+      return new ScaledFontWin(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
+    }
 #endif
 #ifdef XP_MACOSX
   case NATIVE_FONT_MAC_FONT_FACE:
     {
       return new ScaledFontMac(static_cast<CGFontRef>(aNativeFont.mFont), aSize);
     }
 #endif
 #ifdef USE_SKIA
-#ifdef WIN32
-  case NATIVE_FONT_GDI_FONT_FACE:
-    {
-      return new ScaledFontWin(static_cast<LOGFONT*>(aNativeFont.mFont), aSize);
-    }
-#endif
 #ifdef MOZ_ENABLE_FREETYPE
   case NATIVE_FONT_SKIA_FONT_FACE:
     {
       return new ScaledFontFreetype(static_cast<FontOptions*>(aNativeFont.mFont), aSize);
     }
 #endif
 #endif
 #ifdef USE_CAIRO
   case NATIVE_FONT_CAIRO_FONT_FACE:
     {
-      return new ScaledFontBase(aSize);
+      ScaledFontBase* fontBase = new ScaledFontBase(aSize);
+      fontBase->SetCairoScaledFont(static_cast<cairo_scaled_font_t*>(aNativeFont.mFont));
+      return fontBase;
     }
 #endif
   default:
     gfxWarning() << "Invalid native font type specified.";
     return NULL;
   }
 }
 
@@ -362,21 +362,21 @@ uint64_t
 Factory::GetD2DVRAMUsageSourceSurface()
 {
   return DrawTargetD2D::mVRAMUsageSS;
 }
 
 #endif // XP_WIN
 
 TemporaryRef<DrawTarget>
-Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface)
+Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize)
 {
 #ifdef USE_CAIRO
   RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo();
-  if (newTarget->Init(aSurface)) {
+  if (newTarget->Init(aSurface, aSize)) {
     return newTarget;
   }
 
 #endif
   return NULL;
 }
 
 TemporaryRef<DataSourceSurface>
--- a/gfx/2d/HelpersSkia.h
+++ b/gfx/2d/HelpersSkia.h
@@ -71,17 +71,17 @@ JoinStyleToSkiaJoin(JoinStyle aJoin)
       return SkPaint::kMiter_Join;
   }
   return SkPaint::kDefault_Join;
 }
 
 static inline bool
 StrokeOptionsToPaint(SkPaint& aPaint, const StrokeOptions &aOptions)
 {
-  // Skia rendewrs 0 width strokes with a width of 1 (and in black),
+  // Skia renders 0 width strokes with a width of 1 (and in black),
   // so we should just skip the draw call entirely.
   if (!aOptions.mLineWidth) {
     return false;
   }
   aPaint.setStrokeWidth(SkFloatToScalar(aOptions.mLineWidth));
   aPaint.setStrokeMiter(SkFloatToScalar(aOptions.mMiterLimit));
   aPaint.setStrokeCap(CapStyleToSkiaCap(aOptions.mLineCap));
   aPaint.setStrokeJoin(JoinStyleToSkiaJoin(aOptions.mLineJoin));
--- a/gfx/2d/PathCairo.cpp
+++ b/gfx/2d/PathCairo.cpp
@@ -40,16 +40,38 @@ CairoPathContext::~CairoPathContext()
 {
   if (mDrawTarget) {
     mDrawTarget->SetPathObserver(NULL);
   }
   cairo_destroy(mContext);
 }
 
 void
+CairoPathContext::ObserveTarget(DrawTargetCairo* aDrawTarget)
+{
+  if (!aDrawTarget) {
+    return;
+  }
+
+  if (mDrawTarget) {
+    mDrawTarget->SetPathObserver(NULL);
+  }
+  mDrawTarget = aDrawTarget;
+
+  // If there is a transform on the path, then we must have a separate context
+  // from the draw target, so we cannot be its observer
+  if (!mTransform.IsIdentity()) {
+    ForgetDrawTarget();
+    return;
+  }
+
+  mDrawTarget->SetPathObserver(this);
+}
+
+void
 CairoPathContext::DuplicateContextAndPath(const Matrix& aMatrix /* = Matrix() */)
 {
   // Duplicate the path.
   cairo_path_t* path = cairo_copy_path(mContext);
   cairo_fill_rule_t rule = cairo_get_fill_rule(mContext);
 
   // Duplicate the context.
   cairo_surface_t* surf = cairo_get_target(mContext);
@@ -315,18 +337,14 @@ PathCairo::GetPathContext()
 void
 PathCairo::CopyPathTo(cairo_t* aContext, DrawTargetCairo* aDrawTarget)
 {
   if (mPathContext->GetContext() != aContext) {
     mPathContext->CopyPathTo(aContext);
 
     // Since aDrawTarget wants us to be the current path on its context, we
     // should also listen to it for updates to that path (as an optimization).
-    // The easiest way to do this is to just recreate mPathContext, since it
-    // registers with aDrawTarget for updates.
-    mPathContext = new CairoPathContext(aContext, aDrawTarget,
-                                        mPathContext->GetFillRule(),
-                                        mPathContext->GetTransform());
+    mPathContext->ObserveTarget(aDrawTarget);
   }
 }
 
 }
 }
--- a/gfx/2d/PathCairo.h
+++ b/gfx/2d/PathCairo.h
@@ -63,16 +63,20 @@ public:
 
   // Create a duplicate context, and copy this path to that context. Optionally,
   // the new context can be transformed.
   void DuplicateContextAndPath(const Matrix& aMatrix = Matrix());
 
   // Returns true if this CairoPathContext represents path.
   bool ContainsPath(const Path* path);
 
+  // add ourselves as an observer of aDrawTarget, if possible
+  // if we succeed, then mDrawTarget is set to aDrawTarget
+  void ObserveTarget(DrawTargetCairo* aDrawTarget);
+
   cairo_t* GetContext() const { return mContext; }
   DrawTargetCairo* GetDrawTarget() const { return mDrawTarget; }
   Matrix GetTransform() const { return mTransform; }
   FillRule GetFillRule() const { return mFillRule; }
 
   operator cairo_t* () const { return mContext; }
 
 private: // methods
--- a/gfx/2d/SourceSurfaceCairo.cpp
+++ b/gfx/2d/SourceSurfaceCairo.cpp
@@ -98,16 +98,17 @@ SourceSurfaceCairo::DrawTargetWillChange
     cairo_surface_t* surface = cairo_surface_create_similar(mSurface,
                                                             GfxFormatToCairoContent(mFormat),
                                                             mSize.width, mSize.height);
     cairo_t* ctx = cairo_create(surface);
     cairo_pattern_t* pat = cairo_pattern_create_for_surface(mSurface);
     cairo_set_source(ctx, pat);
     cairo_paint(ctx);
     cairo_destroy(ctx);
+    cairo_pattern_destroy(pat);
 
     // Swap in this new surface.
     cairo_surface_destroy(mSurface);
     mSurface = surface;
   }
 }
 
 void
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -33,17 +33,17 @@ enum SurfaceFormat
   FORMAT_B8G8R8A8,
   FORMAT_B8G8R8X8,
   FORMAT_R5G6B5,
   FORMAT_A8
 };
 
 enum BackendType
 {
-  BACKEND_NONE,
+  BACKEND_NONE = 0,
   BACKEND_DIRECT2D,
   BACKEND_COREGRAPHICS,
   BACKEND_CAIRO,
   BACKEND_SKIA
 };
 
 enum FontType
 {
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -818,23 +818,24 @@ public:
     }
 
     bool WaitSync() {
         if (!mSyncObject) {
             // if we have no sync object, then we did a Finish() earlier
             return true;
         }
 
-        EGLint result = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSyncObject, 0, LOCAL_EGL_FOREVER);
+        // wait at most 1 second; this should really be never/rarely hit
+        const uint64_t ns_per_ms = 1000 * 1000;
+        EGLTime timeout = 1000 * ns_per_ms;
+
+        EGLint result = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSyncObject, 0, timeout);
         sEGLLibrary.fDestroySync(EGL_DISPLAY(), mSyncObject);
         mSyncObject = nsnull;
 
-        // we should never expire a 'forever' timeout
-        MOZ_ASSERT(result != LOCAL_EGL_TIMEOUT_EXPIRED);
-
         return result == LOCAL_EGL_CONDITION_SATISFIED;
     }
 
     bool OwnsTexture() {
         return mOwnsTexture;
     }
 
 private:
@@ -874,19 +875,20 @@ GLContextEGL::UpdateSharedHandle(Texture
     // but render with draw quads require complex and hard to maintain context save/restore code
     fCopyTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0, 0, 0,
                        0, 0, mOffscreenActualSize.width,
                        mOffscreenActualSize.height);
 
     fBindTexture(LOCAL_GL_TEXTURE_2D, oldtex);
     BindUserReadFBO(prevRead);
 
-    // Make Shared Handle fully resolved in order to
-    // guarantee content ready to draw in different thread GLContext
-    GuaranteeResolve();
+    // Make sure our copy is finished, so that we can be ready to draw
+    // in different thread GLContext.  If we have KHR_fence_sync, then
+    // we insert a sync object, otherwise we have to do a GuaranteeResolve.
+    wrap->MakeSync();
 }
 
 SharedTextureHandle
 GLContextEGL::CreateSharedHandle(TextureImage::TextureShareType aType)
 {
     if (aType != TextureImage::ThreadShared)
         return 0;
 
@@ -1275,16 +1277,19 @@ public:
                 break;
             case gfxASurface::ImageFormatRGB24:
                 mUpdateFormat = gfxASurface::ImageFormatARGB32;
                 mShaderType = BGRXLayerProgramType;
                 break;
             case gfxASurface::ImageFormatRGB16_565:
                 mShaderType = RGBXLayerProgramType;
                 break;
+            case gfxASurface::ImageFormatA8:
+                mShaderType = RGBALayerProgramType;
+                break;
             default:
                 MOZ_NOT_REACHED("Unknown update format");
             }
 #else
             if (mUpdateFormat != gfxASurface::ImageFormatARGB32) {
                 mShaderType = RGBXLayerProgramType;
             } else {
                 mShaderType = RGBALayerProgramType;
@@ -1830,23 +1835,25 @@ public:
                 const int eglImageAttributes[] = { LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
                                                    LOCAL_EGL_NONE, LOCAL_EGL_NONE };
                 mEGLImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(),
                                                         EGL_NO_CONTEXT,
                                                         EGL_NATIVE_BUFFER_ANDROID,
                                                         (EGLClientBuffer) mGraphicBuffer->getNativeBuffer(),
                                                         eglImageAttributes);
                 if (!mEGLImage) {
+                    mGraphicBuffer = nsnull;
                     LOG("Could not create EGL images: ERROR (0x%04x)", sEGLLibrary.fGetError());
                     return false;
                 }
 
                 return true;
             }
 
+            mGraphicBuffer = nsnull;
             LOG("GraphicBufferAllocator::alloc failed");
             return false;
         }
 #endif
         return mBackingSurface != nsnull;
     }
 
 protected:
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -479,18 +479,21 @@ LayerManagerD3D10::CreateOptimalMaskSurf
   return CreateOptimalSurface(aSize, gfxASurface::ImageFormatARGB32);
 }
 
 
 TemporaryRef<DrawTarget>
 LayerManagerD3D10::CreateDrawTarget(const IntSize &aSize,
                                     SurfaceFormat aFormat)
 {
+  BackendType backend;
   if ((aFormat != FORMAT_B8G8R8A8 &&
-       aFormat != FORMAT_B8G8R8X8)) {
+       aFormat != FORMAT_B8G8R8X8) ||
+       !gfxPlatform::GetPlatform()->SupportsAzureCanvas(backend) ||
+       backend != BACKEND_DIRECT2D) {
     return LayerManager::CreateDrawTarget(aSize, aFormat);
   }
 
   nsRefPtr<ID3D10Texture2D> texture;
   
   CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
   desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
   
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -27,16 +27,17 @@ CanvasLayerD3D9::~CanvasLayerD3D9()
 
 void
 CanvasLayerD3D9::Initialize(const Data& aData)
 {
   NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
 
   if (aData.mDrawTarget) {
     mDrawTarget = aData.mDrawTarget;
+    mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
     mNeedsYFlip = false;
     mDataIsPremultiplied = true;
   } else if (aData.mSurface) {
     mSurface = aData.mSurface;
     NS_ASSERTION(aData.mGLContext == nsnull,
                  "CanvasLayer can't have both surface and GLContext");
     mNeedsYFlip = false;
     mDataIsPremultiplied = true;
@@ -134,39 +135,32 @@ CanvasLayerD3D9::UpdateSurface()
     if (!textureLock.HasLock()) {
       NS_WARNING("Failed to lock CanvasLayer texture.");
       return;
     }
 
     D3DLOCKED_RECT lockedRect = textureLock.GetLockRect();
 
     nsRefPtr<gfxImageSurface> sourceSurface;
-    nsRefPtr<gfxASurface> tempSurface;
-    if (mDrawTarget) {
-      tempSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
-    }
-    else {
-      tempSurface = mSurface;
-    }
 
-    if (tempSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
-      sourceSurface = tempSurface->GetAsImageSurface();
-    } else if (tempSurface->GetType() == gfxASurface::SurfaceTypeImage) {
-      sourceSurface = static_cast<gfxImageSurface*>(tempSurface.get());
+    if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
+      sourceSurface = mSurface->GetAsImageSurface();
+    } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
+      sourceSurface = static_cast<gfxImageSurface*>(mSurface.get());
       if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
           sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
       {
         return;
       }
     } else {
       sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
                                           gfxASurface::ImageFormatARGB32);
       nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
-      ctx->SetSource(tempSurface);
+      ctx->SetSource(mSurface);
       ctx->Paint();
     }
 
     PRUint8 *startBits = sourceSurface->Data();
     PRUint32 sourceStride = sourceSurface->Stride();
 
     if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32) {
       mHasAlpha = false;
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -70,16 +70,17 @@ CanvasLayerOGL::Initialize(const Data& a
     NS_WARNING("CanvasLayerOGL can't have both surface and GLContext");
     return;
   }
 
   mOGLManager->MakeCurrent();
 
   if (aData.mDrawTarget) {
     mDrawTarget = aData.mDrawTarget;
+    mCanvasSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
     mNeedsYFlip = false;
   } else if (aData.mSurface) {
     mCanvasSurface = aData.mSurface;
     mNeedsYFlip = false;
 #if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
     if (aData.mSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
         gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(aData.mSurface);
         mPixmap = xsurf->GetGLXPixmap();
@@ -157,21 +158,17 @@ CanvasLayerOGL::UpdateSurface()
         mTexture == 0)
     {
       mOGLManager->MakeCurrent();
       MakeTextureIfNeeded(gl(), mTexture);
     }
   } else {
     nsRefPtr<gfxASurface> updatedAreaSurface;
 
-    if (mDrawTarget) {
-      // TODO: This is suboptimal - We should have direct handling for the surface types instead of
-      // going via a gfxASurface.
-      updatedAreaSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
-    } else if (mCanvasSurface) {
+    if (mCanvasSurface) {
       updatedAreaSurface = mCanvasSurface;
     } else if (mCanvasGLContext) {
       gfxIntSize size(mBounds.width, mBounds.height);
       nsRefPtr<gfxImageSurface> updatedAreaImageSurface =
         GetTempSurface(size, gfxASurface::ImageFormatARGB32);
 
       mCanvasGLContext->ReadPixelsIntoImageSurface(0, 0,
                                                    mBounds.width,
@@ -221,23 +218,18 @@ CanvasLayerOGL::RenderLayer(int aPreviou
     program = mOGLManager->GetBasicLayerProgram(CanUseOpaqueSurface(),
                                                 true,
                                                 GetMaskLayer() ? Mask2d : MaskNone);
   } else if (mDelayedUpdates) {
     NS_ABORT_IF_FALSE(mCanvasSurface || mDrawTarget, "WebGL canvases should always be using full texture upload");
     
     drawRect.IntersectRect(drawRect, GetEffectiveVisibleRegion().GetBounds());
 
-    nsRefPtr<gfxASurface> surf = mCanvasSurface;
-    if (mDrawTarget) {
-      surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
-    }
-
     mLayerProgram =
-      gl()->UploadSurfaceToTexture(surf,
+      gl()->UploadSurfaceToTexture(mCanvasSurface,
                                    nsIntRect(0, 0, drawRect.width, drawRect.height),
                                    mTexture,
                                    true,
                                    drawRect.TopLeft());
   }
 
   if (!program) {
     program = mOGLManager->GetProgram(mLayerProgram, GetMaskLayer());
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -156,26 +156,29 @@ gfxAndroidPlatform::MakePlatformFont(con
                                      const PRUint8 *aFontData, PRUint32 aLength)
 {
     return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry,
                                                                      aFontData,
                                                                      aLength);
 }
 
 RefPtr<ScaledFont>
-gfxAndroidPlatform::GetScaledFontForFont(gfxFont *aFont)
+gfxAndroidPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
+    NativeFont nativeFont;
+    if (aTarget->GetType() == BACKEND_CAIRO) {
+        nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
+        nativeFont.mFont = NULL;
+        return Factory::CreateScaledFontWithCairo(nativeFont, aFont->GetAdjustedSize(), aFont->GetCairoScaledFont());
+    }
+ 
     NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
-    NativeFont nativeFont;
     nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
     nativeFont.mFont = static_cast<gfxFT2FontBase*>(aFont)->GetFontOptions();
-    RefPtr<ScaledFont> scaledFont =
-      Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
-
-    return scaledFont;
+    return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
 }
 
 bool
 gfxAndroidPlatform::FontHintingEnabled()
 {
     // In "mobile" builds, we sometimes use non-reflow-zoom, so we
     // might not want hinting.  Let's see.
 #ifdef MOZ_USING_ANDROID_JAVA_WIDGETS
--- a/gfx/thebes/gfxAndroidPlatform.h
+++ b/gfx/thebes/gfxAndroidPlatform.h
@@ -28,22 +28,20 @@ public:
     static gfxAndroidPlatform *GetPlatform() {
         return (gfxAndroidPlatform*) gfxPlatform::GetPlatform();
     }
 
     virtual already_AddRefed<gfxASurface>
     CreateOffscreenSurface(const gfxIntSize& size,
                            gfxASurface::gfxContentType contentType);
     
-    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { aBackend = mozilla::gfx::BACKEND_SKIA; return true; }
-
     virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
     
     mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(gfxFont *aFont);
+      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
 
     // to support IPC font list (sharing between chrome and content)
     void GetFontList(InfallibleTArray<FontListEntry>* retValue);
 
     // platform implementations of font functions
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags);
     virtual gfxPlatformFontList* CreatePlatformFontList();
     virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1778,17 +1778,17 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUi
                                                     glyphs.mNumGlyphs);
       }
 
       // draw any remaining glyphs
       glyphs.Flush(cr, strokePattern, aDrawMode, isRTL, true);
 
     } else {
       RefPtr<ScaledFont> scaledFont =
-        gfxPlatform::GetPlatform()->GetScaledFontForFont(this);
+        gfxPlatform::GetPlatform()->GetScaledFontForFont(dt, this);
       
       if (!scaledFont) {
         return;
       }
 
       bool oldSubpixelAA = dt->GetPermitSubpixelAA();
 
       if (!AllowSubpixelAA()) {
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -1542,17 +1542,18 @@ public:
     virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
                                      FontCacheSizes*   aSizes) const;
 
     typedef enum {
         FONT_TYPE_DWRITE,
         FONT_TYPE_GDI,
         FONT_TYPE_FT2,
         FONT_TYPE_MAC,
-        FONT_TYPE_OS2
+        FONT_TYPE_OS2,
+        FONT_TYPE_CAIRO
     } FontType;
 
     virtual FontType GetType() const = 0;
 
 protected:
     // Call the appropriate shaper to generate glyphs for aText and store
     // them into aShapedWord.
     // The length of the text is aShapedWord->Length().
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -43,16 +43,17 @@
 #include "gfxGraphiteShaper.h"
 #endif
 
 #include "nsUnicodeRange.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsILocaleService.h"
+#include "nsReadableUtils.h"
 
 #include "nsWeakReference.h"
 
 #include "cairo.h"
 #include "qcms.h"
 
 #include "plstr.h"
 #include "nsCRT.h"
@@ -70,16 +71,17 @@
 
 #include "nsIGfxInfo.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 
 gfxPlatform *gPlatform = nsnull;
 static bool gEverInitialized = false;
+static nsTArray<nsCString>* gBackendList = nsnull;
 
 // These two may point to the same profile
 static qcms_profile *gCMSOutputProfile = nsnull;
 static qcms_profile *gCMSsRGBProfile = nsnull;
 
 static qcms_transform *gCMSRGBTransform = nsnull;
 static qcms_transform *gCMSInverseRGBTransform = nsnull;
 static qcms_transform *gCMSRGBATransform = nsnull;
@@ -206,33 +208,30 @@ static const char *gPrefLangNames[] = {
     "x-knda",
     "x-sinh",
     "x-tibt",
     "x-unicode",
     "x-user-def"
 };
 
 gfxPlatform::gfxPlatform()
-  : mAzureBackendCollector(this, &gfxPlatform::GetAzureBackendInfo)
+  : mAzureCanvasBackendCollector(this, &gfxPlatform::GetAzureCanvasBackendInfo)
 {
     mUseHarfBuzzScripts = UNINITIALIZED_VALUE;
     mAllowDownloadableFonts = UNINITIALIZED_VALUE;
     mDownloadableFontsSanitize = UNINITIALIZED_VALUE;
     mFallbackUsesCmaps = UNINITIALIZED_VALUE;
 
 #ifdef MOZ_GRAPHITE
     mGraphiteShapingEnabled = UNINITIALIZED_VALUE;
 #endif
     mBidiNumeralOption = UNINITIALIZED_VALUE;
 
-    if (Preferences::GetBool("gfx.canvas.azure.prefer-skia", false)) {
-        mPreferredDrawTargetBackend = BACKEND_SKIA;
-    } else {
-        mPreferredDrawTargetBackend = BACKEND_NONE;
-    }
+    PRUint32 backendMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA);
+    InitCanvasBackend(backendMask);
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
     if (!gPlatform) {
         Init();
     }
@@ -402,16 +401,19 @@ gfxPlatform::Shutdown()
 #endif
 
     // This will block this thread untill the ImageBridge protocol is completely
     // deleted.
     ImageBridgeChild::ShutDown();
 
     CompositorParent::ShutDown();
 
+    delete gBackendList;
+    gBackendList = nsnull;
+
     delete gPlatform;
     gPlatform = nsnull;
 }
 
 gfxPlatform::~gfxPlatform()
 {
     mScreenReferenceSurface = nsnull;
 
@@ -468,19 +470,19 @@ gfxPlatform::OptimizeImage(gfxImageSurfa
     gfxASurface *ret = optSurface;
     NS_ADDREF(ret);
     return ret;
 }
 
 cairo_user_data_key_t kDrawTarget;
 
 RefPtr<DrawTarget>
-gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface)
+gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aSize)
 {
-  RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface());
+  RefPtr<DrawTarget> drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize);
   aSurface->SetData(&kDrawTarget, drawTarget, NULL);
   return drawTarget;
 }
 
 cairo_user_data_key_t kSourceSurface;
 
 void SourceBufferDestroy(void *srcBuffer)
 {
@@ -527,21 +529,18 @@ gfxPlatform::GetSourceSurfaceForSurface(
     }
     srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
   }
 #endif
 
   if (!srcBuffer) {
     nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
 
-    bool isWin32ImageSurf = false;
-
-    if (imgSurface && aSurface->GetType() != gfxASurface::SurfaceTypeWin32) {
-      isWin32ImageSurf = true;
-    }
+    bool isWin32ImageSurf = imgSurface &&
+                            aSurface->GetType() == gfxASurface::SurfaceTypeWin32;
 
     if (!imgSurface) {
       imgSurface = new gfxImageSurface(aSurface->GetSize(), OptimalFormatForContent(aSurface->GetContentType()));
       nsRefPtr<gfxContext> ctx = new gfxContext(imgSurface);
       ctx->SetSource(aSurface);
       ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
       ctx->Paint();
     }
@@ -567,18 +566,18 @@ gfxPlatform::GetSourceSurfaceForSurface(
     IntSize size = IntSize(imgSurface->GetSize().width, imgSurface->GetSize().height);
     srcBuffer = aTarget->CreateSourceSurfaceFromData(imgSurface->Data(),
                                                      size,
                                                      imgSurface->Stride(),
                                                      format);
 
     if (!srcBuffer) {
       // We need to check if our gfxASurface will keep the underlying data
-      // alive! This is true if gfxASurface actually -is- an ImageSurface or
-      // if it is a gfxWindowsSurface which supportes GetAsImageSurface.
+      // alive. This is true if gfxASurface actually -is- an ImageSurface or
+      // if it is a gfxWindowsSurface which supports GetAsImageSurface.
       if (imgSurface != aSurface && !isWin32ImageSurf) {
         // This shouldn't happen for now, it can be easily supported by making
         // a copy. For now let's just abort.
         NS_RUNTIMEABORT("Attempt to create unsupported SourceSurface from"
             "non-image surface.");
         return nsnull;
       }
 
@@ -600,118 +599,158 @@ gfxPlatform::GetSourceSurfaceForSurface(
 
   srcBuffer->AddRef();
   aSurface->SetData(&kSourceSurface, srcBuffer, SourceBufferDestroy);
 
   return srcBuffer;
 }
 
 RefPtr<ScaledFont>
-gfxPlatform::GetScaledFontForFont(gfxFont *aFont)
+gfxPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
   NativeFont nativeFont;
   nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
-  nativeFont.mFont = aFont;
+  nativeFont.mFont = aFont->GetCairoScaledFont();
   RefPtr<ScaledFont> scaledFont =
     Factory::CreateScaledFontForNativeFont(nativeFont,
                                            aFont->GetAdjustedSize());
   return scaledFont;
 }
 
-UserDataKey kThebesSurfaceKey;
-void
-DestroyThebesSurface(void *data)
+cairo_user_data_key_t kDrawSourceSurface;
+static void
+DataSourceSurfaceDestroy(void *dataSourceSurface)
 {
-  gfxASurface *surface = static_cast<gfxASurface*>(data);
-  surface->Release();
+  static_cast<DataSourceSurface*>(dataSourceSurface)->Release();
+}
+
+cairo_user_data_key_t kDrawTargetForSurface;
+static void
+DataDrawTargetDestroy(void *aTarget)
+{
+  static_cast<DrawTarget*>(aTarget)->Release();
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
-  // If we have already created a thebes surface, we can just return it.
-  void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
-  if (surface) {
-    nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
-    return surf.forget();
-  }
-
-  nsRefPtr<gfxASurface> surf;
   if (aTarget->GetType() == BACKEND_CAIRO) {
     cairo_surface_t* csurf =
       static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
-    surf = gfxASurface::Wrap(csurf);
-  } else {
-    // The semantics of this part of the function are sort of weird. If we
-    // don't have direct support for the backend, we snapshot the first time
-    // and then return the snapshotted surface for the lifetime of the draw
-    // target. Sometimes it seems like this works out, but it seems like it
-    // might result in no updates ever.
-    RefPtr<SourceSurface> source = aTarget->Snapshot();
-    RefPtr<DataSourceSurface> data = source->GetDataSurface();
-
-    if (!data) {
-      return NULL;
-    }
-
-    IntSize size = data->GetSize();
-    gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
-
-    // We need to make a copy here because data might change its data under us
-    nsRefPtr<gfxImageSurface> imageSurf = new gfxImageSurface(gfxIntSize(size.width, size.height), format, false);
- 
-    bool resultOfCopy = imageSurf->CopyFrom(source);
-    NS_ASSERTION(resultOfCopy, "Failed to copy surface.");
-    surf = imageSurf;
+    return gfxASurface::Wrap(csurf);
   }
 
-  // add a reference to be held by the drawTarget
-  // careful, the reference graph is getting complicated here
-  surf->AddRef();
-  aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
+  // The semantics of this part of the function are sort of weird. If we
+  // don't have direct support for the backend, we snapshot the first time
+  // and then return the snapshotted surface for the lifetime of the draw
+  // target. Sometimes it seems like this works out, but it seems like it
+  // might result in no updates ever.
+  RefPtr<SourceSurface> source = aTarget->Snapshot();
+  RefPtr<DataSourceSurface> data = source->GetDataSurface();
+
+  if (!data) {
+    return NULL;
+  }
+
+  IntSize size = data->GetSize();
+  gfxASurface::gfxImageFormat format = OptimalFormatForContent(ContentForFormat(data->GetFormat()));
+
+
+  nsRefPtr<gfxASurface> surf =
+    new gfxImageSurface(data->GetData(), gfxIntSize(size.width, size.height),
+                        data->Stride(), format);
+
+  surf->SetData(&kDrawSourceSurface, data.forget().drop(), DataSourceSurfaceDestroy);
+  // keep the draw target alive as long as we need its data
+  aTarget->AddRef();
+  surf->SetData(&kDrawTargetForSurface, aTarget, DataDrawTargetDestroy);
 
   return surf.forget();
 }
 
 RefPtr<DrawTarget>
-gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
+gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
 {
   BackendType backend;
-  if (!SupportsAzure(backend)) {
+  if (!SupportsAzureCanvas(backend)) {
     return NULL;
   }
 
   // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
   // create the best offscreen surface for the current system and situation. We
   // can easily take advantage of this for the Cairo backend, so that's what we
   // do.
   // mozilla::gfx::Factory can get away without having all this knowledge for
   // now, but this might need to change in the future (using
   // CreateOffscreenSurface() and CreateDrawTargetForSurface() for all
   // backends).
-  if (backend == BACKEND_CAIRO) {
+  if (aBackend == BACKEND_CAIRO) {
     nsRefPtr<gfxASurface> surf = CreateOffscreenSurface(ThebesIntSize(aSize),
                                                         ContentForFormat(aFormat));
+    if (!surf) {
+      return NULL;
+    }
 
-    return CreateDrawTargetForSurface(surf);
+    return CreateDrawTargetForSurface(surf, aSize);
   } else {
-    return Factory::CreateDrawTarget(backend, aSize, aFormat);
+    return Factory::CreateDrawTarget(aBackend, aSize, aFormat);
   }
 }
 
 RefPtr<DrawTarget>
+gfxPlatform::CreateOffscreenDrawTarget(const IntSize& aSize, SurfaceFormat aFormat)
+{
+  BackendType backend;
+  if (!SupportsAzureCanvas(backend)) {
+    return NULL;
+  }
+
+  RefPtr<DrawTarget> target = CreateDrawTargetForBackend(backend, aSize, aFormat);
+  if (target ||
+      mFallbackCanvasBackend == BACKEND_NONE) {
+    return target;
+  }
+
+  return CreateDrawTargetForBackend(mFallbackCanvasBackend, aSize, aFormat);
+}
+
+
+RefPtr<DrawTarget>
 gfxPlatform::CreateDrawTargetForData(unsigned char* aData, const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat)
 {
   BackendType backend;
-  if (!SupportsAzure(backend)) {
+  if (!SupportsAzureCanvas(backend)) {
     return NULL;
   }
   return Factory::CreateDrawTargetForData(backend, aData, aSize, aStride, aFormat); 
 }
 
+bool
+gfxPlatform::SupportsAzureCanvas(BackendType& aBackend)
+{
+  NS_ASSERTION(mFallbackCanvasBackend == BACKEND_NONE || mPreferredCanvasBackend != BACKEND_NONE,
+               "fallback backend with no preferred backend");
+  aBackend = mPreferredCanvasBackend;
+  return mPreferredCanvasBackend != BACKEND_NONE;
+}
+
+/* static */ BackendType
+gfxPlatform::BackendTypeForName(const nsCString& aName)
+{
+  if (aName.EqualsLiteral("cairo"))
+    return BACKEND_CAIRO;
+  if (aName.EqualsLiteral("skia"))
+    return BACKEND_SKIA;
+  if (aName.EqualsLiteral("direct2d"))
+    return BACKEND_DIRECT2D;
+  if (aName.EqualsLiteral("cg"))
+    return BACKEND_COREGRAPHICS;
+  return BACKEND_NONE;
+}
+
 nsresult
 gfxPlatform::GetFontList(nsIAtom *aLangGroup,
                          const nsACString& aGenericFamily,
                          nsTArray<nsString>& aListOfFonts)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
@@ -1122,30 +1161,63 @@ gfxPlatform::AppendPrefLang(eFontPrefLan
     }
     
     if (i == aLen) {
         aPrefLangs[aLen] = aAddLang;
         aLen++;
     }
 }
 
+void
+gfxPlatform::InitCanvasBackend(PRUint32 aBackendBitmask)
+{
+    if (!Preferences::GetBool("gfx.canvas.azure.enabled", false)) {
+        mPreferredCanvasBackend = BACKEND_NONE;
+        mFallbackCanvasBackend = BACKEND_NONE;
+        return;
+    }
+
+    mPreferredCanvasBackend = GetCanvasBackendPref(aBackendBitmask);
+    mFallbackCanvasBackend = GetCanvasBackendPref(aBackendBitmask & ~(1 << mPreferredCanvasBackend));
+}
+
+/* static */ BackendType
+gfxPlatform::GetCanvasBackendPref(PRUint32 aBackendBitmask)
+{
+    if (!gBackendList) {
+        gBackendList = new nsTArray<nsCString>();
+        nsCString prefString;
+        if (NS_SUCCEEDED(Preferences::GetCString("gfx.canvas.azure.backends", &prefString))) {
+            ParseString(prefString, ',', *gBackendList);
+        }
+    }
+
+    for (PRUint32 i = 0; i < gBackendList->Length(); ++i) {
+        BackendType result = BackendTypeForName((*gBackendList)[i]);
+        if ((1 << result) & aBackendBitmask) {
+            return result;
+        }
+    }
+    return BACKEND_NONE;
+}
+
 bool
 gfxPlatform::UseProgressiveTilePainting()
 {
-  static bool sUseProgressiveTilePainting;
-  static bool sUseProgressiveTilePaintingPrefCached = false;
+    static bool sUseProgressiveTilePainting;
+    static bool sUseProgressiveTilePaintingPrefCached = false;
 
-  if (!sUseProgressiveTilePaintingPrefCached) {
-    sUseProgressiveTilePaintingPrefCached = true;
-    mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
-                                          "layers.progressive-paint",
-                                          false);
-  }
+    if (!sUseProgressiveTilePaintingPrefCached) {
+        sUseProgressiveTilePaintingPrefCached = true;
+        mozilla::Preferences::AddBoolVarCache(&sUseProgressiveTilePainting,
+                                              "layers.progressive-paint",
+                                              false);
+    }
 
-  return sUseProgressiveTilePainting;
+    return sUseProgressiveTilePainting;
 }
 
 bool
 gfxPlatform::UseAzureContentDrawing()
 {
   static bool sAzureContentDrawingEnabled;
   static bool sAzureContentDrawingPrefCached = false;
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -33,19 +33,16 @@ struct gfxFontStyle;
 class gfxUserFontSet;
 class gfxFontEntry;
 class gfxProxyFontEntry;
 class gfxPlatformFontList;
 class gfxTextRun;
 class nsIURI;
 class nsIAtom;
 
-extern mozilla::gfx::UserDataKey kThebesSurfaceKey;
-void DestroyThebesSurface(void *data);
-
 extern cairo_user_data_key_t kDrawTarget;
 
 // pref lang id's for font prefs
 // !!! needs to match the list of pref font.default.xx entries listed in all.js !!!
 // !!! don't use as bit mask, this may grow larger !!!
 
 enum eFontPrefLang {
     eFontPrefLang_Western     =  0,
@@ -125,17 +122,17 @@ GetBackendName(mozilla::gfx::BackendType
         return "quartz";
       case mozilla::gfx::BACKEND_CAIRO:
         return "cairo";
       case mozilla::gfx::BACKEND_SKIA:
         return "skia";
       case mozilla::gfx::BACKEND_NONE:
         return "none";
   }
-  MOZ_NOT_REACHED("Incomplet switch");
+  MOZ_NOT_REACHED("Incomplete switch");
 }
 
 class THEBES_API gfxPlatform {
 public:
     /**
      * Return a pointer to the current active platform.
      * This is a singleton; it contains mostly convenience
      * functions to obtain platform-specific objects.
@@ -167,46 +164,48 @@ public:
     virtual already_AddRefed<gfxASurface>
       CreateOffscreenImageSurface(const gfxIntSize& aSize,
                                   gfxASurface::gfxContentType aContentType);
 
     virtual already_AddRefed<gfxASurface> OptimizeImage(gfxImageSurface *aSurface,
                                                         gfxASurface::gfxImageFormat format);
 
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
-      CreateDrawTargetForSurface(gfxASurface *aSurface);
+      CreateDrawTargetForSurface(gfxASurface *aSurface, const mozilla::gfx::IntSize& aSize);
 
     /*
-     * Creates a SourceSurface for a gfxASurface. This surface should -not- be
-     * held around by the user after the underlying gfxASurface has been
-     * destroyed as a copy of the data is not guaranteed.
+     * Creates a SourceSurface for a gfxASurface. This function does no caching,
+     * so the caller should cache the gfxASurface if it will be used frequently.
+     * The returned surface keeps a reference to aTarget, so it is OK to keep the
+     * surface, even if aTarget changes.
+     * aTarget should not keep a reference to the returned surface because that
+     * will cause a cycle.
      */
     virtual mozilla::RefPtr<mozilla::gfx::SourceSurface>
       GetSourceSurfaceForSurface(mozilla::gfx::DrawTarget *aTarget, gfxASurface *aSurface);
 
     virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(gfxFont *aFont);
+      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
 
     virtual already_AddRefed<gfxASurface>
       GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
 
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
       CreateOffscreenDrawTarget(const mozilla::gfx::IntSize& aSize, mozilla::gfx::SurfaceFormat aFormat);
 
     virtual mozilla::RefPtr<mozilla::gfx::DrawTarget>
       CreateDrawTargetForData(unsigned char* aData, const mozilla::gfx::IntSize& aSize, 
                               int32_t aStride, mozilla::gfx::SurfaceFormat aFormat);
 
-    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend) { return false; }
+    // aBackend will be set to the preferred backend for Azure canvas
+    bool SupportsAzureCanvas(mozilla::gfx::BackendType& aBackend);
 
-    void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
-      mozilla::gfx::BackendType backend;
-      if (SupportsAzure(backend)) {
-        aObj.DefineProperty("AzureBackend", GetBackendName(backend)); 
-      }
+    // aObj will contain the preferred backend for Azure canvas
+    void GetAzureCanvasBackendInfo(mozilla::widget::InfoObject &aObj) {
+      aObj.DefineProperty("AzureBackend", GetBackendName(mPreferredCanvasBackend));
     }
 
     /*
      * Font bits
      */
 
     virtual void SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString);
 
@@ -450,44 +449,70 @@ public:
     virtual int GetScreenDepth() const;
 
 protected:
     gfxPlatform();
     virtual ~gfxPlatform();
 
     void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, 
                             eFontPrefLang aCharLang, eFontPrefLang aPageLang);
-                                               
+
+    /**
+     * Helper method, creates a draw target for a specific Azure backend.
+     * Used by CreateOffscreenDrawTarget.
+     */
+    mozilla::RefPtr<mozilla::gfx::DrawTarget>
+      CreateDrawTargetForBackend(mozilla::gfx::BackendType aBackend,
+                                 const mozilla::gfx::IntSize& aSize,
+                                 mozilla::gfx::SurfaceFormat aFormat);
+
+    /**
+     * Initialise the preferred and fallback canvas backends
+     * aBackendBitmask specifies the backends which are acceptable to the caller.
+     * The backend used is determined by aBackendBitmask and the order specified
+     * by the gfx.canvas.azure.backends pref.
+     */
+    void InitCanvasBackend(PRUint32 aBackendBitmask);
+    /**
+     * returns the first backend named in the pref gfx.canvas.azure.backends
+     * which is a component of aBackendBitmask, a bitmask of backend types
+     */
+    static mozilla::gfx::BackendType GetCanvasBackendPref(PRUint32 aBackendBitmask);
+    static mozilla::gfx::BackendType BackendTypeForName(const nsCString& aName);
+
     PRInt8  mAllowDownloadableFonts;
     PRInt8  mDownloadableFontsSanitize;
 #ifdef MOZ_GRAPHITE
     PRInt8  mGraphiteShapingEnabled;
 #endif
 
     PRInt8  mBidiNumeralOption;
 
     // whether to always search font cmaps globally 
     // when doing system font fallback
     PRInt8  mFallbackUsesCmaps;
 
     // which scripts should be shaped with harfbuzz
     PRInt32 mUseHarfBuzzScripts;
 
-    // The preferred draw target backend to use
-    mozilla::gfx::BackendType mPreferredDrawTargetBackend;
-
 private:
     /**
      * Start up Thebes.
      */
     static void Init();
 
     virtual qcms_profile* GetPlatformCMSOutputProfile();
 
     nsRefPtr<gfxASurface> mScreenReferenceSurface;
     nsTArray<PRUint32> mCJKPrefLangs;
     nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
     nsCOMPtr<nsIObserver> mFontPrefsObserver;
-    mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureBackendCollector;
+
+    // The preferred draw target backend to use for canvas
+    mozilla::gfx::BackendType mPreferredCanvasBackend;
+    // The fallback draw target backend to use for canvas, if the preferred backend fails
+    mozilla::gfx::BackendType mFallbackCanvasBackend;
+
+    mozilla::widget::GfxInfoCollector<gfxPlatform> mAzureCanvasBackendCollector;
     bool mWorkAroundDriverBugs;
 };
 
 #endif /* GFX_PLATFORM_H */
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -725,27 +725,21 @@ gfxPlatformGtk::GetGdkDrawable(gfxASurfa
     }
 #endif
 
     return NULL;
 }
 #endif
 
 RefPtr<ScaledFont>
-gfxPlatformGtk::GetScaledFontForFont(gfxFont *aFont)
+gfxPlatformGtk::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
+    NativeFont nativeFont;
+    if (aTarget->GetType() == BACKEND_CAIRO) {
+        nativeFont.mType = NATIVE_FONT_CAIRO_FONT_FACE;
+        nativeFont.mFont = NULL;
+        return Factory::CreateScaledFontWithCairo(nativeFont, aFont->GetAdjustedSize(), aFont->GetCairoScaledFont());
+    }
     NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_FT2, "Expecting Freetype font");
-    NativeFont nativeFont;
     nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
     nativeFont.mFont = static_cast<gfxFT2FontBase*>(aFont)->GetFontOptions();
-    RefPtr<ScaledFont> scaledFont =
-      Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
-
-    return scaledFont;
+    return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
 }
-
-bool
-gfxPlatformGtk::SupportsAzure(BackendType& aBackend)
-{
-    aBackend = BACKEND_SKIA;
-    return true;
-}
-
--- a/gfx/thebes/gfxPlatformGtk.h
+++ b/gfx/thebes/gfxPlatformGtk.h
@@ -31,19 +31,17 @@ public:
     static gfxPlatformGtk *GetPlatform() {
         return (gfxPlatformGtk*) gfxPlatform::GetPlatform();
     }
 
     already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                          gfxASurface::gfxContentType contentType);
 
     mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(gfxFont *aFont);
-
-    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
+      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
 
     nsresult GetFontList(nsIAtom *aLangGroup,
                          const nsACString& aGenericFamily,
                          nsTArray<nsString>& aListOfFonts);
 
     nsresult UpdateFontList();
 
     nsresult ResolveFontName(const nsAString& aFontName,
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -64,16 +64,19 @@ DisableFontActivation()
 gfxPlatformMac::gfxPlatformMac()
 {
     mOSXVersion = 0;
     OSXVersion();
     if (mOSXVersion >= MAC_OS_X_VERSION_10_6_HEX) {
         DisableFontActivation();
     }
     mFontAntiAliasingThreshold = ReadAntiAliasingThreshold();
+
+    PRUint32 backendMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA) | (1 << BACKEND_COREGRAPHICS);
+    InitCanvasBackend(backendMask);
 }
 
 gfxPlatformMac::~gfxPlatformMac()
 {
     gfxCoreTextShaper::Shutdown();
 }
 
 gfxPlatformFontList*
@@ -128,34 +131,22 @@ gfxPlatformMac::OptimizeImage(gfxImageSu
         }
     }
 
     nsRefPtr<gfxASurface> ret = new gfxQuartzImageSurface(isurf);
     return ret.forget();
 }
 
 RefPtr<ScaledFont>
-gfxPlatformMac::GetScaledFontForFont(gfxFont *aFont)
+gfxPlatformMac::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
     gfxMacFont *font = static_cast<gfxMacFont*>(aFont);
     return font->GetScaledFont();
 }
 
-bool
-gfxPlatformMac::SupportsAzure(BackendType& aBackend)
-{
-  if (mPreferredDrawTargetBackend != BACKEND_NONE) {
-    aBackend = mPreferredDrawTargetBackend;
-  } else {
-    aBackend = BACKEND_COREGRAPHICS;
-  }
-
-  return true;
-}
-
 nsresult
 gfxPlatformMac::ResolveFontName(const nsAString& aFontName,
                                 FontResolverCallback aCallback,
                                 void *aClosure, bool& aAborted)
 {
     nsAutoString resolvedName;
     if (!gfxPlatformFontList::PlatformFontList()->
              ResolveFontName(aFontName, resolvedName)) {
@@ -384,36 +375,26 @@ gfxPlatformMac::ReadAntiAliasingThreshol
 
     return threshold;
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
   if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
-    void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
-    if (surface) {
-      nsRefPtr<gfxASurface> surf = static_cast<gfxQuartzSurface*>(surface);
-      return surf.forget();
-    } else {
-      CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
+    CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
 
-      //XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
-      IntSize intSize = aTarget->GetSize();
-      gfxIntSize size(intSize.width, intSize.height);
-
-      nsRefPtr<gfxASurface> surf =
-        new gfxQuartzSurface(cg, size);
+    //XXX: it would be nice to have an implicit conversion from IntSize to gfxIntSize
+    IntSize intSize = aTarget->GetSize();
+    gfxIntSize size(intSize.width, intSize.height);
 
-      // add a reference to be held by the drawTarget
-      surf->AddRef();
-      aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
+    nsRefPtr<gfxASurface> surf =
+      new gfxQuartzSurface(cg, size);
 
-      return surf.forget();
-    }
+    return surf.forget();
   }
 
   return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
 }
 
 
 qcms_profile *
 gfxPlatformMac::GetPlatformCMSOutputProfile()
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -34,19 +34,17 @@ public:
     virtual already_AddRefed<gfxASurface>
       CreateOffscreenImageSurface(const gfxIntSize& aSize,
                                   gfxASurface::gfxContentType aContentType);
     
     already_AddRefed<gfxASurface> OptimizeImage(gfxImageSurface *aSurface,
                                                 gfxASurface::gfxImageFormat format);
     
     mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(gfxFont *aFont);
-
-    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
+      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
 
     nsresult ResolveFontName(const nsAString& aFontName,
                              FontResolverCallback aCallback,
                              void *aClosure, bool& aAborted);
 
     nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
 
     gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
--- a/gfx/thebes/gfxQtPlatform.cpp
+++ b/gfx/thebes/gfxQtPlatform.cpp
@@ -601,15 +601,8 @@ gfxQtPlatform::GetDPI()
 }
 
 gfxImageFormat
 gfxQtPlatform::GetOffscreenFormat()
 {
     return sOffscreenFormat;
 }
 
-bool
-gfxQtPlatform::SupportsAzure(BackendType& aBackend)
-{
-  aBackend = BACKEND_SKIA;
-  return true;
-}
-
--- a/gfx/thebes/gfxQtPlatform.h
+++ b/gfx/thebes/gfxQtPlatform.h
@@ -42,18 +42,16 @@ public:
 
     static gfxQtPlatform *GetPlatform() {
         return (gfxQtPlatform*) gfxPlatform::GetPlatform();
     }
 
     already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                          gfxASurface::gfxContentType contentType);
 
-    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
-
     nsresult GetFontList(nsIAtom *aLangGroup,
                          const nsACString& aGenericFamily,
                          nsTArray<nsString>& aListOfFonts);
 
     nsresult UpdateFontList();
 
     nsresult ResolveFontName(const nsAString& aFontName,
                              FontResolverCallback aCallback,
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -510,16 +510,24 @@ gfxWindowsPlatform::UpdateRenderMode()
 
             SetupClearTypeParams();
 
             if (hr == S_OK)
               reporter.SetSuccessful();
         }
     }
 #endif
+
+    PRUint32 backendMask = 1 << BACKEND_CAIRO;
+    if (mRenderMode == RENDER_DIRECT2D) {
+      backendMask |= 1 << BACKEND_DIRECT2D;
+    } else {
+      backendMask |= 1 << BACKEND_SKIA;
+    }
+    InitCanvasBackend(backendMask);
 }
 
 void
 gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce)
 {
 #ifdef CAIRO_HAS_D2D_SURFACE
     if (mD2DDevice) {
         ID3D10Device1 *device = cairo_d2d_device_get_device(mD2DDevice);
@@ -759,17 +767,17 @@ gfxWindowsPlatform::CreateOffscreenImage
 #ifdef DEBUG
     nsRefPtr<gfxImageSurface> imageSurface = surface->GetAsImageSurface();
     NS_ASSERTION(imageSurface, "Surface cannot be converted to a gfxImageSurface");
 #endif
     return surface.forget();
 }
 
 RefPtr<ScaledFont>
-gfxWindowsPlatform::GetScaledFontForFont(gfxFont *aFont)
+gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
 {
     if (aFont->GetType() == gfxFont::FONT_TYPE_DWRITE) {
         gfxDWriteFont *font = static_cast<gfxDWriteFont*>(aFont);
 
         NativeFont nativeFont;
         nativeFont.mType = NATIVE_FONT_DWRITE_FONT_FACE;
         nativeFont.mFont = font->GetFontFace();
         RefPtr<ScaledFont> scaledFont =
@@ -781,85 +789,57 @@ gfxWindowsPlatform::GetScaledFontForFont
     NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_GDI,
         "Fonts on windows should be GDI or DWrite!");
 
     NativeFont nativeFont;
     nativeFont.mType = NATIVE_FONT_GDI_FONT_FACE;
     LOGFONT lf;
     GetObject(static_cast<gfxGDIFont*>(aFont)->GetHFONT(), sizeof(LOGFONT), &lf);
     nativeFont.mFont = &lf;
-    RefPtr<ScaledFont> scaledFont =
-    Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
 
-    return scaledFont;
+    if (aTarget->GetType() == BACKEND_CAIRO) {
+      return Factory::CreateScaledFontWithCairo(nativeFont,
+                                                aFont->GetAdjustedSize(),
+                                                aFont->GetCairoScaledFont());
+    }
+
+    return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
 }
 
 already_AddRefed<gfxASurface>
 gfxWindowsPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
 #ifdef XP_WIN
   if (aTarget->GetType() == BACKEND_DIRECT2D) {
-    void *surface = aTarget->GetUserData(&kThebesSurfaceKey);
-    if (surface) {
-      nsRefPtr<gfxASurface> surf = static_cast<gfxASurface*>(surface);
-      return surf.forget();
-    } else {
-      if (!GetD2DDevice()) {
-        // We no longer have a D2D device, can't do this.
-        return NULL;
-      }
+    if (!GetD2DDevice()) {
+      // We no longer have a D2D device, can't do this.
+      return NULL;
+    }
 
-      RefPtr<ID3D10Texture2D> texture =
-        static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
-
-      if (!texture) {
-        return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
-      }
+    RefPtr<ID3D10Texture2D> texture =
+      static_cast<ID3D10Texture2D*>(aTarget->GetNativeSurface(NATIVE_SURFACE_D3D10_TEXTURE));
 
-      aTarget->Flush();
+    if (!texture) {
+      return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
+    }
 
-      nsRefPtr<gfxASurface> surf =
-        new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
+    aTarget->Flush();
 
-      // add a reference to be held by the drawTarget
-      surf->AddRef();
-      aTarget->AddUserData(&kThebesSurfaceKey, surf.get(), DestroyThebesSurface);
-      /* "It might be worth it to clear cairo surfaces associated with a drawtarget.
-	  The strong reference means for example for D2D that cairo's scratch surface
-	  will be kept alive (well after a user being done) and consume extra VRAM.
-	  We can deal with this in a follow-up though." */
+    nsRefPtr<gfxASurface> surf =
+      new gfxD2DSurface(texture, ContentForFormat(aTarget->GetFormat()));
 
-      // shouldn't this hold a reference?
-      surf->SetData(&kDrawTarget, aTarget, NULL);
-      return surf.forget();
-    }
+    // shouldn't this hold a reference?
+    surf->SetData(&kDrawTarget, aTarget, NULL);
+    return surf.forget();
   }
 #endif
 
   return gfxPlatform::GetThebesSurfaceForDrawTarget(aTarget);
 }
 
-bool
-gfxWindowsPlatform::SupportsAzure(BackendType& aBackend)
-{
-#ifdef CAIRO_HAS_D2D_SURFACE
-  if (mRenderMode == RENDER_DIRECT2D) {
-      aBackend = BACKEND_DIRECT2D;
-      return true;
-  }
-#endif
-  
-  if (mPreferredDrawTargetBackend != BACKEND_NONE) {
-    aBackend = mPreferredDrawTargetBackend;
-    return true;
-  }
-
-  return false;
-}
-
 nsresult
 gfxWindowsPlatform::GetFontList(nsIAtom *aLangGroup,
                                 const nsACString& aGenericFamily,
                                 nsTArray<nsString>& aListOfFonts)
 {
     gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts);
 
     return NS_OK;
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -103,21 +103,19 @@ public:
 
     already_AddRefed<gfxASurface> CreateOffscreenSurface(const gfxIntSize& size,
                                                          gfxASurface::gfxContentType contentType);
     virtual already_AddRefed<gfxASurface>
       CreateOffscreenImageSurface(const gfxIntSize& aSize,
                                   gfxASurface::gfxContentType aContentType);
 
     virtual mozilla::RefPtr<mozilla::gfx::ScaledFont>
-      GetScaledFontForFont(gfxFont *aFont);
+      GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
     virtual already_AddRefed<gfxASurface>
       GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
-    
-    virtual bool SupportsAzure(mozilla::gfx::BackendType& aBackend);
 
     enum RenderMode {
         /* Use GDI and windows surfaces */
         RENDER_GDI = 0,
 
         /* Use 32bpp image surfaces and call StretchDIBits */
         RENDER_IMAGE_STRETCH32,
 
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -12,16 +12,17 @@
 #include "nsXULAppAPI.h"
 #include "mozilla/Observer.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMWindow.h"
 #include "mozilla/Services.h"
 #include "nsIWebNavigation.h"
 #include "nsITabChild.h"
 #include "nsIDocShell.h"
+#include "mozilla/StaticPtr.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "WindowIdentifier.h"
 #include "mozilla/dom/ScreenOrientation.h"
 
 using namespace mozilla::services;
 
 #define PROXY_IF_SANDBOXED(_call)                 \
   do {                                            \
@@ -69,17 +70,17 @@ WindowIsActive(nsIDOMWindow *window)
   window->GetDocument(getter_AddRefs(doc));
   NS_ENSURE_TRUE(doc, false);
 
   bool hidden = true;
   doc->GetMozHidden(&hidden);
   return !hidden;
 }
 
-nsAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate;
+StaticAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate;
 
 void InitLastIDToVibrate()
 {
   gLastIDToVibrate = new WindowIdentifier::IDArrayType();
   ClearOnShutdown(&gLastIDToVibrate);
 }
 
 } // anonymous namespace
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -133,17 +133,17 @@ DiscardingEnabled()
   }
 
   return enabled;
 }
 
 namespace mozilla {
 namespace image {
 
-/* static */ nsRefPtr<RasterImage::DecodeWorker> RasterImage::DecodeWorker::sSingleton;
+/* static */ StaticRefPtr<RasterImage::DecodeWorker> RasterImage::DecodeWorker::sSingleton;
 
 #ifndef DEBUG
 NS_IMPL_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
                    nsISupportsWeakReference)
 #else
 NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsIProperties,
                    imgIContainerDebug, nsISupportsWeakReference)
 #endif
@@ -1446,20 +1446,26 @@ RasterImage::AddSourceData(const char *a
 
   // We should not call this if we're already finished adding source data
   NS_ABORT_IF_FALSE(!mHasSourceData, "Calling AddSourceData() after calling "
                                      "sourceDataComplete()!");
 
   // This call should come straight from necko - no reentrancy allowed
   NS_ABORT_IF_FALSE(!mInDecoder, "Re-entrant call to AddSourceData!");
 
+  // Image is already decoded, we shouldn't be getting data, but it could
+  // be extra garbage data at the end of a file.
+  if (mDecoded) {
+    return NS_OK;
+  }
+
   // Starting a new part's frames, let's clean up before we add any
   // This needs to happen just before we start getting EnsureFrame() call(s),
   // so that there's no gap for anything to miss us.
-  if (mBytesDecoded == 0) {
+  if (mMultipart && mBytesDecoded == 0) {
     // Our previous state may have been animated, so let's clean up
     if (mAnimating) {
       StopAnimation();
       mAnimating = false;
     }
     mAnimationFinished = false;
     if (mAnim) {
       delete mAnim;
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -26,16 +26,17 @@
 #include "nsWeakReference.h"
 #include "nsTArray.h"
 #include "imgFrame.h"
 #include "nsThreadUtils.h"
 #include "DiscardTracker.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/LinkedList.h"
+#include "mozilla/StaticPtr.h"
 #ifdef DEBUG
   #include "imgIContainerDebug.h"
 #endif
 
 class imgIDecoder;
 class imgIContainerObserver;
 class nsIInputStream;
 
@@ -420,17 +421,17 @@ private:
      * @return NS_ERROR if an error is encountered, and NS_OK otherwise.  (Note
      *         that we return NS_OK even when the size was not found.)
      */
     nsresult DecodeUntilSizeAvailable(RasterImage* aImg);
 
     NS_IMETHOD Run();
 
   private: /* statics */
-    static nsRefPtr<DecodeWorker> sSingleton;
+    static StaticRefPtr<DecodeWorker> sSingleton;
 
   private: /* methods */
     DecodeWorker()
       : mPendingInEventLoop(false)
     {}
 
     /* Post ourselves to the event loop if we're not currently pending. */
     void EnsurePendingInEventLoop();
--- a/image/test/mochitest/Makefile.in
+++ b/image/test/mochitest/Makefile.in
@@ -7,16 +7,17 @@ DEPTH		= ../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = image/test/mochitest
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_FILES =   imgutils.js \
+                animationPolling.js \
                 lime100x100.svg \
                 test_bug399925.html \
                 bug399925.gif \
                 schrep.png \
                 bug468160.sjs \
                 test_bug468160.html \
                 red.png \
                 test_bug466586.html \
@@ -52,16 +53,19 @@ MOCHITEST_FILES =   imgutils.js \
                 bug552605.sjs \
                 bug671906-iframe.html \
                 bug671906.sjs \
                 test_bug671906.html \
                 test_bug733553.html \
                 bug733553-iframe.html \
                 bug733553.sjs \
                 animated-gif2.gif \
+                test_bug767779.html \
+                bug767779.sjs \
+                animated-gif_trailing-garbage.gif \
 		test_error_events.html \
 		error-early.png \
 		test_drawDiscardedImage.html \
                 $(NULL)
 
 # Tests disabled due to intermittent orange
 # test_bug435296.html disabled - See bug 578591
 # test_bug478398.html disabled - See bug 579139
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..02f4de2e31f379d9c6fac2324065a1980ab8e49c
GIT binary patch
literal 4030
zc${<hbhEHb)L_tHIK;y6pMl|j9fQPwhClxq{v!d!pDdiL49pBV3_t)<%fPJ3vFpx1
zgHxWX_gcI@yZe8FMqf(iyo^=ra$fH%&^cd{d%t4c`<nOv9o(20u<4c{Q8yEcZVQrh
zr=Z!bL9}k`?97~^{7QxL#A1bv)S}c;{wRNxKgu8FkMc+Pqx@0+D1Vec${*#A@&|+u
E03p}<Z2$lO
new file mode 100644
--- /dev/null
+++ b/image/test/mochitest/bug767779.sjs
@@ -0,0 +1,56 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var timer = Components.classes["@mozilla.org/timer;1"];
+var partTimer = timer.createInstance(Components.interfaces.nsITimer);
+
+function getFileAsInputStream(aFilename) {
+  var file = Components.classes["@mozilla.org/file/directory_service;1"]
+             .getService(Components.interfaces.nsIProperties)
+             .get("CurWorkD", Components.interfaces.nsIFile);
+
+  file.append("tests");
+  file.append("image");
+  file.append("test");
+  file.append("mochitest");
+  file.append(aFilename);
+
+  var fileStream = Components.classes['@mozilla.org/network/file-input-stream;1']
+                   .createInstance(Components.interfaces.nsIFileInputStream);
+  fileStream.init(file, 1, 0, false);
+  return fileStream;
+}
+
+function handleRequest(request, response)
+{
+  response.setHeader("Content-Type", "image/gif", false);
+  response.setHeader("Cache-Control", "no-cache", false);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  // We're sending data off in a delayed fashion
+  response.processAsync();
+  var inputStream = getFileAsInputStream("animated-gif_trailing-garbage.gif");
+  var available = inputStream.available(); // = 4029 bytes
+  // Send the good data at once
+  response.bodyOutputStream.writeFrom(inputStream, 285);
+  sendParts(inputStream, response);
+}
+
+function sendParts(inputStream, response) {
+  // 3744 left, send in 8 chunks of 468 each
+  partTimer.initWithCallback(getSendNextPart(inputStream, response), 500,
+                             Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+}
+
+function getSendNextPart(inputStream, response) {
+  return function () {
+    response.bodyOutputStream.writeFrom(inputStream, 468);
+    if (!inputStream.available()) {
+      inputStream.close();
+      response.finish();
+    } else {
+      sendParts(inputStream, response);
+    }
+  };
+}
+
new file mode 100644
--- /dev/null
+++ b/image/test/mochitest/test_bug767779.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=767779
+-->
+<head>
+  <title>Test for Bug 767779</title>
+  <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+  <script type="application/javascript" src="imgutils.js"></script>
+  <script type="application/javascript" src="animationPolling.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=767779">Mozilla Bug 767779</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+const FAILURE_TIMEOUT = 30000; // Fail early after 30 seconds
+
+function main()
+{
+  // referenceDiv's size and color correspond to the last frame of the GIF
+  var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
+                                   'animatedGif', 'debug');
+  animTest.beginTest();
+}
+
+window.onload = main;
+</script>
+</pre>
+<div id="content"> <!-- style="display: none" -->
+  <div id="referenceDiv" style="height: 40px; width: 40px;
+                                display: none; background: #18ff00;"></div>
+  <div id="animatedImage">
+    <img id="animatedGif" src="bug767779.sjs" style="display: none;"/>
+      <div id="text-descr"></div>
+  </div>
+  <div id="debug" style="display:none">
+  </div>
+</div>
+</body>
+</html>
--- a/intl/locale/src/unix/nsCollationUnix.h
+++ b/intl/locale/src/unix/nsCollationUnix.h
@@ -6,20 +6,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef nsCollationUnix_h__
 #define nsCollationUnix_h__
 
 
 #include "nsICollation.h"
 #include "nsCollation.h"  // static library
 #include "plstr.h"
+#include "mozilla/Attributes.h"
 
 
 
-class nsCollationUnix : public nsICollation {
+class nsCollationUnix MOZ_FINAL : public nsICollation {
 
 protected:
   nsCollation   *mCollation;
   nsCString     mLocale;
   nsCString     mSavedLocale;
   bool          mUseCodePointOrder;
 
   void DoSetLocale();
--- a/ipc/chromium/src/chrome/common/ipc_message_utils.h
+++ b/ipc/chromium/src/chrome/common/ipc_message_utils.h
@@ -789,17 +789,17 @@ struct ParamTraits<LogData> {
     WriteParam(m, static_cast<int>(p.type));
     WriteParam(m, p.flags);
     WriteParam(m, p.sent);
     WriteParam(m, p.receive);
     WriteParam(m, p.dispatch);
     WriteParam(m, p.params);
   }
   static bool Read(const Message* m, void** iter, param_type* r) {
-    int type;
+    int type = 0;
     bool result =
       ReadParam(m, iter, &r->channel) &&
       ReadParam(m, iter, &r->routing_id) &&
       ReadParam(m, iter, &type) &&
       ReadParam(m, iter, &r->flags) &&
       ReadParam(m, iter, &r->sent) &&
       ReadParam(m, iter, &r->receive) &&
       ReadParam(m, iter, &r->dispatch) &&
--- a/ipc/glue/MessagePump.h
+++ b/ipc/glue/MessagePump.h
@@ -10,24 +10,25 @@
 #include "base/time.h"
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 
 #include "nsIRunnable.h"
 #include "nsIThread.h"
 #include "nsITimer.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 namespace ipc {
 
 class MessagePump;
 
-class DoWorkRunnable : public nsIRunnable,
-                       public nsITimerCallback
+class DoWorkRunnable MOZ_FINAL : public nsIRunnable,
+                                 public nsITimerCallback
 {
 public:
   DoWorkRunnable(MessagePump* aPump)
   : mPump(aPump) { }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSITIMERCALLBACK
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1741,16 +1741,23 @@ FREEZE_VARIABLES = \
   XPIDLSRCS \
   DIRS \
   LIBRARY \
   MODULE \
   SHORT_LIBNAME \
   TIERS \
   EXTRA_COMPONENTS \
   EXTRA_PP_COMPONENTS \
+  MOCHITEST_FILES \
+  MOCHITEST_FILES_PARTS \
+  MOCHITEST_CHROME_FILES \
+  MOCHITEST_BROWSER_FILES \
+  MOCHITEST_BROWSER_FILES_PARTS \
+  MOCHITEST_A11Y_FILES \
+  MOCHITEST_WEBAPPRT_CHROME_FILES \
   $(NULL)
 
 $(foreach var,$(FREEZE_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
 
 CHECK_FROZEN_VARIABLES = $(foreach var,$(FREEZE_VARIABLES), \
   $(if $(subst $($(var)_FROZEN),,'$($(var))'),$(error Makefile variable '$(var)' changed value after including rules.mk. Was $($(var)_FROZEN), now $($(var)).)))
 
 libs export::
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -55,51 +55,17 @@ BumpChunk::canAlloc(size_t n)
 void
 LifoAlloc::freeAll()
 {
     while (first) {
         BumpChunk *victim = first;
         first = first->next();
         BumpChunk::delete_(victim);
     }
-    first = latest = NULL;
-}
-
-void
-LifoAlloc::freeUnused()
-{
-    /* Don't free anything if we have outstanding marks. */
-    if (markCount || !first)
-        return; 
-
-    JS_ASSERT(first && latest);
-
-    /* Rewind through any unused chunks. */
-    if (!latest->used()) {
-        BumpChunk *lastUsed = NULL;
-        for (BumpChunk *it = first; it != latest; it = it->next()) {
-            if (it->used())
-                lastUsed = it;
-        }
-        if (!lastUsed) {
-            freeAll();
-            return;
-        }
-        latest = lastUsed;
-    }
-
-    /* Free all chunks after |latest|. */
-    BumpChunk *it = latest->next();
-    while (it) {
-        BumpChunk *victim = it;
-        it = it->next();
-        BumpChunk::delete_(victim);
-    }
-
-    latest->setNext(NULL);
+    first = latest = last = NULL;
 }
 
 LifoAlloc::BumpChunk *
 LifoAlloc::getOrCreateChunk(size_t n)
 {
     if (first) {
         /* Look for existing, unused BumpChunks to satisfy the request. */
         while (latest->next()) {
@@ -126,16 +92,53 @@ LifoAlloc::getOrCreateChunk(size_t n)
         chunkSize = defaultChunkSize_;
     }
 
     /* If we get here, we couldn't find an existing BumpChunk to fill the request. */
     BumpChunk *newChunk = BumpChunk::new_(chunkSize);
     if (!newChunk)
         return NULL;
     if (!first) {
-        latest = first = newChunk;
+        latest = first = last = newChunk;
     } else {
         JS_ASSERT(latest && !latest->next());
         latest->setNext(newChunk);
-        latest = newChunk;
+        latest = last = newChunk;
     }
     return newChunk;
 }
+
+void
+LifoAlloc::transferFrom(LifoAlloc *other)
+{
+    JS_ASSERT(!markCount);
+    JS_ASSERT(latest == first);
+    JS_ASSERT(!other->markCount);
+
+    if (!other->first)
+        return;
+
+    append(other->first, other->last);
+    other->first = other->last = other->latest = NULL;
+}
+
+void
+LifoAlloc::transferUnusedFrom(LifoAlloc *other)
+{
+    JS_ASSERT(!markCount);
+    JS_ASSERT(latest == first);
+
+    if (other->markCount || !other->first)
+        return;
+
+    /*
+     * Because of how getOrCreateChunk works, there may be unused chunks before
+     * |last|. We do not transfer those chunks. In most cases it is expected
+     * that last == first, so this should be a rare situation that, when it
+     * happens, should not recur.
+     */
+
+    if (other->latest->next()) {
+        append(other->latest->next(), other->last);
+        other->latest->setNext(NULL);
+        other->last = other->latest;
+    }
+}
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -139,16 +139,17 @@ class BumpChunk
  * chain after they've been released to avoid thrashing before a GC.
  */
 class LifoAlloc
 {
     typedef detail::BumpChunk BumpChunk;
 
     BumpChunk   *first;
     BumpChunk   *latest;
+    BumpChunk   *last;
     size_t      markCount;
     size_t      defaultChunkSize_;
 
     void operator=(const LifoAlloc &) MOZ_DELETE;
     LifoAlloc(const LifoAlloc &) MOZ_DELETE;
 
     /* 
      * Return a BumpChunk that can perform an allocation of at least size |n|
@@ -156,41 +157,53 @@ class LifoAlloc
      *
      * Side effect: if retval is non-null, |first| and |latest| are initialized
      * appropriately.
      */
     BumpChunk *getOrCreateChunk(size_t n);
 
     void reset(size_t defaultChunkSize) {
         JS_ASSERT(RoundUpPow2(defaultChunkSize) == defaultChunkSize);
-        first = latest = NULL;
+        first = latest = last = NULL;
         defaultChunkSize_ = defaultChunkSize;
         markCount = 0;
     }
 
+    void append(BumpChunk *start, BumpChunk *end) {
+        JS_ASSERT(start && end);
+        if (last)
+            last->setNext(start);
+        else
+            first = latest = start;
+        last = end;
+    }
+
   public:
     explicit LifoAlloc(size_t defaultChunkSize) { reset(defaultChunkSize); }
 
     /* Steal allocated chunks from |other|. */
     void steal(LifoAlloc *other) {
         JS_ASSERT(!other->markCount);
         PodCopy((char *) this, (char *) other, sizeof(*this));
         other->reset(defaultChunkSize_);
     }
 
+    /* Append allocated chunks from |other|. They are removed from |other|. */
+    void transferFrom(LifoAlloc *other);
+
+    /* Append unused chunks from |other|. They are removed from |other|. */
+    void transferUnusedFrom(LifoAlloc *other);
+
     ~LifoAlloc() { freeAll(); }
 
     size_t defaultChunkSize() const { return defaultChunkSize_; }
 
     /* Frees all held memory. */
     void freeAll();
 
-    /* Should be called on GC in order to release any held chunks. */
-    void freeUnused();
-
     JS_ALWAYS_INLINE
     void *alloc(size_t n) {
         JS_OOM_POSSIBLY_FAIL();
 
         void *result;
         if (latest && (result = latest->tryAlloc(n)))
             return result;
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -716,16 +716,17 @@ static JSBool js_NewRuntimeWasCalled = J
 static const JSSecurityCallbacks NullSecurityCallbacks = { };
 
 JSRuntime::JSRuntime()
   : atomsCompartment(NULL),
 #ifdef JS_THREADSAFE
     ownerThread_(NULL),
 #endif
     tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
+    freeLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     execAlloc_(NULL),
     bumpAlloc_(NULL),
 #ifdef JS_METHODJIT
     jaegerRuntime_(NULL),
 #endif
     nativeStackBase(0),
     nativeStackQuota(0),
     interpreterFrames(NULL),
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -382,19 +382,25 @@ struct JSRuntime : js::RuntimeFriendFiel
   public:
     bool onOwnerThread() const { return true; }
 #endif
 
     /* Keeper of the contiguous stack used by all contexts in this thread. */
     js::StackSpace stackSpace;
 
     /* Temporary arena pool used while compiling and decompiling. */
-    static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
+    static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 4 * 1024;
     js::LifoAlloc tempLifoAlloc;
 
+    /*
+     * Free LIFO blocks are transferred to this allocator before being freed on
+     * the background GC thread.
+     */
+    js::LifoAlloc freeLifoAlloc;
+
   private:
     /*
      * Both of these allocators are used for regular expression code which is shared at the
      * thread-data level.
      */
     JSC::ExecutableAllocator *execAlloc_;
     WTF::BumpPointerAllocator *bumpAlloc_;
 #ifdef JS_METHODJIT
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -566,17 +566,17 @@ JSCompartment::sweep(FreeOp *fop, bool r
             for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
                 JSScript *script = i.get<JSScript>();
                 script->clearAnalysis();
             }
         }
 
         {
             gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_FREE_TI_ARENA);
-            oldAlloc.freeAll();
+            rt->freeLifoAlloc.transferFrom(&oldAlloc);
             if (types.constrainedOutputs) {
                 fop->delete_(types.constrainedOutputs);
                 types.constrainedOutputs = NULL;
             }
         }
     }
 
     active = false;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3066,16 +3066,18 @@ GCHelperThread::doSweep()
         } else {
             JS_ASSERT(!freeCursorEnd);
         }
         for (void ***iter = freeVector.begin(); iter != freeVector.end(); ++iter) {
             void **array = *iter;
             freeElementsAndArray(array, array + FREE_ARRAY_LENGTH);
         }
         freeVector.resize(0);
+
+        rt->freeLifoAlloc.freeAll();
     }
 
     bool shrinking = shrinkFlag;
     ExpireChunksAndArenas(rt, shrinking);
 
     /*
      * The main thread may have called ShrinkGCBuffers while
      * ExpireChunksAndArenas(rt, false) was running, so we recheck the flag
@@ -3136,27 +3138,22 @@ SweepCompartments(FreeOp *fop, gcreason:
             continue;
         }
         *write++ = compartment;
     }
     rt->compartments.resize(write - rt->compartments.begin());
 }
 
 static void
-PurgeRuntime(JSTracer *trc)
-{
-    JSRuntime *rt = trc->runtime;
-
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        /* We can be called from StartVerifyBarriers with a non-GC marker. */
-        if (c->isCollecting() || !IS_GC_MARKING_TRACER(trc))
-            c->purge();
-    }
-
-    rt->tempLifoAlloc.freeUnused();
+PurgeRuntime(JSRuntime *rt)
+{
+    for (GCCompartmentsIter c(rt); !c.done(); c.next())
+        c->purge();
+
+    rt->freeLifoAlloc.transferUnusedFrom(&rt->tempLifoAlloc);
 
     rt->gsnCache.purge();
     rt->propertyCache.purge(rt);
     rt->newObjectCache.purge();
     rt->nativeIterCache.purge();
     rt->sourceDataCache.purge();
     rt->evalCache.clear();
 
@@ -3237,17 +3234,17 @@ BeginMarkPhase(JSRuntime *rt, bool isInc
      * GC will be broken, as follows. If some object is reachable only through
      * some cache (say the dtoaCache) then it will not be part of the snapshot.
      * If we purge after root marking, then the mutator could obtain a pointer
      * to the object and start using it. This object might never be marked, so
      * a GC hazard would exist.
      */
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_PURGE);
-        PurgeRuntime(gcmarker);
+        PurgeRuntime(rt);
     }
 
     /*
      * Mark phase.
      */
     gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_MARK);
     gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_MARK_ROOTS);
 
@@ -3603,16 +3600,19 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocat
 
 #ifdef DEBUG
     PropertyTree::dumpShapes(rt);
 #endif
 
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DESTROY);
 
+        if (!rt->gcSweepOnBackgroundThread)
+            rt->freeLifoAlloc.freeAll();
+
         /*
          * Sweep script filenames after sweeping functions in the generic loop
          * above. In this way when a scripted function's finalizer destroys the
          * script and calls rt->destroyScriptHook, the hook can still access the
          * script's filename. See bug 323267.
          */
         if (rt->gcIsFull) {
             SweepScriptFilenames(rt);
@@ -4829,18 +4829,16 @@ StartVerifyPreBarriers(JSRuntime *rt)
     VerifyPreTracer *trc = new (js_malloc(sizeof(VerifyPreTracer))) VerifyPreTracer;
 
     rt->gcNumber++;
     trc->number = rt->gcNumber;
     trc->count = 0;
 
     JS_TracerInit(trc, rt, AccumulateEdge);
 
-    PurgeRuntime(trc);
-
     const size_t size = 64 * 1024 * 1024;
     trc->root = (VerifyNode *)js_malloc(size);
     JS_ASSERT(trc->root);
     trc->edgeptr = (char *)trc->root;
     trc->term = trc->edgeptr + size;
 
     if (!trc->nodemap.init())
         return;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -875,28 +875,16 @@ DoIncDec(JSContext *cx, HandleScript scr
 #define PUSH_INT32(i)            regs.sp++->setInt32(i)
 #define PUSH_STRING(s)           do { regs.sp++->setString(s); assertSameCompartment(cx, regs.sp[-1]); } while (0)
 #define PUSH_OBJECT(obj)         do { regs.sp++->setObject(obj); assertSameCompartment(cx, regs.sp[-1]); } while (0)
 #define PUSH_OBJECT_OR_NULL(obj) do { regs.sp++->setObjectOrNull(obj); assertSameCompartment(cx, regs.sp[-1]); } while (0)
 #define PUSH_HOLE()              regs.sp++->setMagic(JS_ARRAY_HOLE)
 #define POP_COPY_TO(v)           v = *--regs.sp
 #define POP_RETURN_VALUE()       regs.fp()->setReturnValue(*--regs.sp)
 
-#define VALUE_TO_BOOLEAN(cx, vp, b)                                           \
-    JS_BEGIN_MACRO                                                            \
-        vp = &regs.sp[-1];                                                    \
-        if (vp->isNull()) {                                                   \
-            b = false;                                                        \
-        } else {                                                              \
-            b = ToBoolean(*vp);                                               \
-        }                                                                     \
-    JS_END_MACRO
-
-#define POP_BOOLEAN(cx, vp, b)   do { VALUE_TO_BOOLEAN(cx, vp, b); regs.sp--; } while(0)
-
 #define FETCH_OBJECT(cx, n, obj)                                              \
     JS_BEGIN_MACRO                                                            \
         Value *vp_ = &regs.sp[n];                                             \
         obj = ToObject(cx, (vp_));                                            \
         if (!obj)                                                             \
             goto error;                                                       \
     JS_END_MACRO
 
@@ -1615,55 +1603,49 @@ BEGIN_CASE(JSOP_GOTO)
 {
     len = GET_JUMP_OFFSET(regs.pc);
     BRANCH(len);
 }
 END_CASE(JSOP_GOTO)
 
 BEGIN_CASE(JSOP_IFEQ)
 {
-    bool cond;
-    Value *_;
-    POP_BOOLEAN(cx, _, cond);
+    bool cond = ToBoolean(regs.sp[-1]);
+    regs.sp--;
     if (cond == false) {
         len = GET_JUMP_OFFSET(regs.pc);
         BRANCH(len);
     }
 }
 END_CASE(JSOP_IFEQ)
 
 BEGIN_CASE(JSOP_IFNE)
 {
-    bool cond;
-    Value *_;
-    POP_BOOLEAN(cx, _, cond);
+    bool cond = ToBoolean(regs.sp[-1]);
+    regs.sp--;
     if (cond != false) {
         len = GET_JUMP_OFFSET(regs.pc);
         BRANCH(len);
     }
 }
 END_CASE(JSOP_IFNE)
 
 BEGIN_CASE(JSOP_OR)
 {
-    bool cond;
-    Value *_;
-    VALUE_TO_BOOLEAN(cx, _, cond);
+    bool cond = ToBoolean(regs.sp[-1]);
     if (cond == true) {
         len = GET_JUMP_OFFSET(regs.pc);
         DO_NEXT_OP(len);
     }
 }
 END_CASE(JSOP_OR)
 
 BEGIN_CASE(JSOP_AND)
 {
-    bool cond;
-    Value *_;
-    VALUE_TO_BOOLEAN(cx, _, cond);
+    bool cond = ToBoolean(regs.sp[-1]);
     if (cond == false) {
         len = GET_JUMP_OFFSET(regs.pc);
         DO_NEXT_OP(len);
     }
 }
 END_CASE(JSOP_AND)
 
 /*
@@ -2104,19 +2086,18 @@ BEGIN_CASE(JSOP_MOD)
     if (!ModOperation(cx, lval, rval, &regs.sp[-2]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_MOD)
 
 BEGIN_CASE(JSOP_NOT)
 {
-    Value *_;
-    bool cond;
-    POP_BOOLEAN(cx, _, cond);
+    bool cond = ToBoolean(regs.sp[-1]);
+    regs.sp--;
     PUSH_BOOLEAN(!cond);
 }
 END_CASE(JSOP_NOT)
 
 BEGIN_CASE(JSOP_BITNOT)
 {
     int32_t i;
     if (!ToInt32(cx, regs.sp[-1], &i))
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -4781,16 +4781,31 @@ mjit::Compiler::jsop_getprop(PropertyNam
             masm.loadPtr(Address(str, JSString::offsetOfLengthAndFlags()), str);
             masm.urshift32(Imm32(JSString::LENGTH_SHIFT), str);
             frame.pop();
             frame.pushTypedPayload(JSVAL_TYPE_INT32, str);
         }
         return true;
     }
 
+    /* Handle lenth accesses of optimize 'arguments'. */
+    if (name == cx->runtime->atomState.lengthAtom &&
+        cx->typeInferenceEnabled() &&
+        analysis->poppedTypes(PC, 0)->isMagicArguments(cx) &&
+        knownPushedType(0) == JSVAL_TYPE_INT32)
+    {
+        frame.pop();
+        RegisterID reg = frame.allocReg();
+        masm.load32(Address(JSFrameReg, StackFrame::offsetOfNumActual()), reg);
+        frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
+        if (script->hasScriptCounts)
+            bumpPropCount(PC, PCCounts::PROP_DEFINITE);
+        return true;
+    }
+
     if (top->mightBeType(JSVAL_TYPE_OBJECT) &&
         JSOp(*PC) == JSOP_LENGTH && cx->typeInferenceEnabled() &&
         !hasTypeBarriers(PC) && knownPushedType(0) == JSVAL_TYPE_INT32) {
         /* Check if this is an array we can make a loop invariant entry for. */
         if (loop && loop->generatingInvariants()) {
             CrossSSAValue topv(a->inlineIndex, analysis->poppedValue(PC, 0));
             FrameEntry *fe = loop->invariantLength(topv);
             if (fe) {
@@ -4861,28 +4876,16 @@ mjit::Compiler::jsop_getprop(PropertyNam
             masm.loadPayload(Address(reg, TypedArray::lengthOffset()), reg);
             frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
             if (script->hasScriptCounts)
                 bumpPropCount(PC, PCCounts::PROP_DEFINITE);
             if (!isObject)
                 stubcc.rejoin(Changes(1));
             return true;
         }
-
-        /*
-         * Check if we are accessing the 'length' of the lazy arguments for the
-         * current frame.
-         */
-        if (types->isMagicArguments(cx)) {
-            frame.pop();
-            frame.pushWord(Address(JSFrameReg, StackFrame::offsetOfNumActual()), JSVAL_TYPE_INT32);
-            if (script->hasScriptCounts)
-                bumpPropCount(PC, PCCounts::PROP_DEFINITE);
-            return true;
-        }
     }
 
     /* If the access will definitely be fetching a particular value, nop it. */
     bool testObject;
     JSObject *singleton =
         (*PC == JSOP_GETPROP || *PC == JSOP_CALLPROP) ? pushedSingleton(0) : NULL;
     if (singleton && singleton->isFunction() && !hasTypeBarriers(PC)) {
         Rooted<jsid> id(cx, NameToId(name));
--- a/js/src/tests/lib/progressbar.py
+++ b/js/src/tests/lib/progressbar.py
@@ -1,29 +1,25 @@
 # Text progress bar library, like curl or scp.
 
 import sys
 from datetime import datetime
 
-class NullProgressBar:
+if sys.platform.startswith('win'):
+    from lib.terminal_win import Terminal
+else:
+    from lib.terminal_unix import Terminal
+
+class NullProgressBar(object):
     def update(self, current, data): pass
     def poke(self): pass
     def finish(self, complete=True): pass
     def message(self, msg): sys.stdout.write(msg + '\n')
 
-class ProgressBar:
-    GREEN = '\x1b[32;1m'
-    RED   = '\x1b[31;1m'
-    BLUE  = '\x1b[34;1m'
-    GRAY  = '\x1b[37;2m'
-
-    RESET = '\x1b[0m'
-
-    CLEAR_RIGHT = '\x1b[K'
-
+class ProgressBar(object):
     def __init__(self, limit, fmt):
         assert not self.conservative_isatty()
         assert limit < 9999
 
         self.prior = None
         self.counters_fmt = fmt # [{str:str}] Describtion of how to lay out each
                                 #             field in the counters map.
         self.limit = limit # int: The value of 'current' equal to 100%.
@@ -31,39 +27,45 @@ class ProgressBar:
 
         # Compute the width of the counters and build the format string.
         self.counters_width = 1 # [
         for layout in self.counters_fmt:
             self.counters_width += 4 # Less than 9999 tests total.
             self.counters_width += 1 # | (or ']' for the last one)
 
         self.barlen = 64 - self.counters_width
-        self.fmt = ('\r%-' + str(self.counters_width) + 's %3d%% %-' +
-                    str(self.barlen) + 's| %6.1fs' + self.CLEAR_RIGHT)
 
     def update(self, current, data):
         # Record prior for poke.
         self.prior = (current, data)
 
         # Build counters string.
-        counters = '['
+        sys.stdout.write('\r[')
         for layout in self.counters_fmt:
-            counters += layout['color'] + ('%4d' % data[layout['value']]) + self.RESET
-            counters += '|'
-        counters = counters[:-1] + ']'
+            Terminal.set_color(layout['color'])
+            sys.stdout.write('%4d' % data[layout['value']])
+            Terminal.reset_color()
+            if layout != self.counters_fmt[-1]:
+                sys.stdout.write('|')
+            else:
+                sys.stdout.write('] ')
 
         # Build the bar.
         pct = int(100.0 * current / self.limit)
+        sys.stdout.write('%3d%% ' % pct)
+
         barlen = int(1.0 * self.barlen * current / self.limit) - 1
-        bar = '='*barlen + '>'
+        bar = '=' * barlen + '>' + ' ' * (self.barlen - barlen - 1)
+        sys.stdout.write(bar + '|')
 
         # Update the bar.
         dt = datetime.now() - self.t0
         dt = dt.seconds + dt.microseconds * 1e-6
-        sys.stdout.write(self.fmt % (counters, pct, bar, dt))
+        sys.stdout.write('%6.1fs' % dt)
+        Terminal.clear_right()
 
         # Force redisplay, since we didn't write a \n.
         sys.stdout.flush()
 
     def poke(self):
         if not self.prior:
             return
         self.update(*self.prior)
--- a/js/src/tests/lib/results.py
+++ b/js/src/tests/lib/results.py
@@ -85,20 +85,20 @@ class ResultsSink:
         self.groups = {}
         self.counts = {'PASS': 0, 'FAIL': 0, 'TIMEOUT': 0, 'SKIP': 0}
         self.n = 0
 
         if options.hide_progress:
             self.pb = NullProgressBar()
         else:
             fmt = [
-                {'value': 'PASS',    'color': ProgressBar.GREEN},
-                {'value': 'FAIL',    'color': ProgressBar.RED},
-                {'value': 'TIMEOUT', 'color': ProgressBar.BLUE},
-                {'value': 'SKIP',    'color': ProgressBar.GRAY},
+                {'value': 'PASS',    'color': 'green'},
+                {'value': 'FAIL',    'color': 'red'},
+                {'value': 'TIMEOUT', 'color': 'blue'},
+                {'value': 'SKIP',    'color': 'brightgray'},
             ]
             self.pb = ProgressBar(testcount, fmt)
 
     def push(self, output):
         if output.timed_out:
             self.counts['TIMEOUT'] += 1
         if isinstance(output, NullTestOutput):
             if self.options.tinderbox:
new file mode 100644
--- /dev/null
+++ b/js/src/tests/lib/terminal_unix.py
@@ -0,0 +1,37 @@
+import sys
+
+class Terminal(object):
+    COLOR = {
+        'red': '31',
+        'green': '32',
+        'blue': '34',
+        'gray': '37'
+    }
+    NORMAL_INTENSITY = '1'
+    BRIGHT_INTENSITY = '2'
+    ESCAPE = '\x1b['
+    RESET = '0'
+    SEPARATOR = ';'
+    COLOR_CODE = 'm'
+    CLEAR_RIGHT_CODE = 'K'
+
+    @classmethod
+    def set_color(cls, color):
+        """
+        color: str - color definition string
+        """
+        mod = Terminal.NORMAL_INTENSITY
+        if color.startswith('bright'):
+            mod = Terminal.BRIGHT_INTENSITY
+            color = color[len('bright'):]
+        color_code = Terminal.COLOR[color]
+
+        sys.stdout.write(cls.ESCAPE + color_code + cls.SEPARATOR + mod + cls.COLOR_CODE)
+
+    @classmethod
+    def reset_color(cls):
+        sys.stdout.write(cls.ESCAPE + cls.RESET + cls.COLOR_CODE)
+
+    @classmethod
+    def clear_right(cls):
+        sys.stdout.write(cls.ESCAPE + cls.CLEAR_RIGHT_CODE)
new file mode 100644
--- /dev/null
+++ b/js/src/tests/lib/terminal_win.py
@@ -0,0 +1,109 @@
+"""
+From Andre Burgaud's Blog, from the CTypes Wiki:
+http://www.burgaud.com/bring-colors-to-the-windows-console-with-python/
+
+Colors text in console mode application (win32).
+Uses ctypes and Win32 methods SetConsoleTextAttribute and
+GetConsoleScreenBufferInfo.
+
+$Id: color_console.py 534 2009-05-10 04:00:59Z andre $
+"""
+
+from ctypes import windll, Structure, c_short, c_ushort, byref
+
+SHORT = c_short
+WORD = c_ushort
+
+class COORD(Structure):
+  """struct in wincon.h."""
+  _fields_ = [
+    ("X", SHORT),
+    ("Y", SHORT)]
+
+class SMALL_RECT(Structure):
+  """struct in wincon.h."""
+  _fields_ = [
+    ("Left", SHORT),
+    ("Top", SHORT),
+    ("Right", SHORT),
+    ("Bottom", SHORT)]
+
+class CONSOLE_SCREEN_BUFFER_INFO(Structure):
+  """struct in wincon.h."""
+  _fields_ = [
+    ("dwSize", COORD),
+    ("dwCursorPosition", COORD),
+    ("wAttributes", WORD),
+    ("srWindow", SMALL_RECT),
+    ("dwMaximumWindowSize", COORD)]
+
+# winbase.h
+STD_INPUT_HANDLE = -10
+STD_OUTPUT_HANDLE = -11
+STD_ERROR_HANDLE = -12
+
+# wincon.h
+FOREGROUND_BLACK     = 0x0000
+FOREGROUND_BLUE      = 0x0001
+FOREGROUND_GREEN     = 0x0002
+FOREGROUND_CYAN      = 0x0003
+FOREGROUND_RED       = 0x0004
+FOREGROUND_MAGENTA   = 0x0005
+FOREGROUND_YELLOW    = 0x0006
+FOREGROUND_GREY      = 0x0007
+FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.
+
+BACKGROUND_BLACK     = 0x0000
+BACKGROUND_BLUE      = 0x0010
+BACKGROUND_GREEN     = 0x0020
+BACKGROUND_CYAN      = 0x0030
+BACKGROUND_RED       = 0x0040
+BACKGROUND_MAGENTA   = 0x0050
+BACKGROUND_YELLOW    = 0x0060
+BACKGROUND_GREY      = 0x0070
+BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
+
+stdout_handle = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
+SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
+GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
+
+def get_text_attr():
+  csbi = CONSOLE_SCREEN_BUFFER_INFO()
+  GetConsoleScreenBufferInfo(stdout_handle, byref(csbi))
+  return csbi.wAttributes
+
+DEFAULT_COLORS = get_text_attr()
+
+class Terminal(object):
+    COLOR = {
+        'black': 0x0000,
+        'blue': 0x0001,
+        'green': 0x0002,
+        'cyan': 0x0003,
+        'red': 0x0004,
+        'magenta': 0x0005,
+        'yellow': 0x0006,
+        'gray': 0x0007
+    }
+    BRIGHT_INTENSITY = 0x0008
+    BACKGROUND_SHIFT = 4
+
+    @classmethod
+    def set_color(cls, color):
+        """
+        color: str - color definition string
+        """
+        color_code = 0
+        if color.startswith('bright'):
+            color_code |= cls.BRIGHT_INTENSITY
+            color = color[len('bright'):]
+        color_code |= Terminal.COLOR[color]
+        SetConsoleTextAttribute(stdout_handle, color_code)
+
+    @classmethod
+    def reset_color(cls):
+        SetConsoleTextAttribute(stdout_handle, DEFAULT_COLORS)
+
+    @classmethod
+    def clear_right(cls):
+        pass
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -1937,16 +1937,22 @@ public:
                          nsIFrame* aFixedPosFrame, nsDisplayList* aList);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayFixedPosition();
 #endif
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerParameters& aContainerParameters);
+  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
+                                   LayerManager* aManager,
+                                   const ContainerParameters& aParameters)
+  {
+    return mozilla::LAYER_ACTIVE;
+  }
   NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
 
 protected:
   nsIFrame* mFixedPosFrame;
 };
 
 /**
  * This potentially creates a layer for the given list of items, whose
@@ -2157,16 +2163,22 @@ public:
   
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion,
                                    const nsRect& aAllowVisibleRegionExpansion);
+  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
+                                   LayerManager* aManager,
+                                   const ContainerParameters& aParameters)
+  {
+    return mozilla::LAYER_ACTIVE;
+  }
   NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
 
   // Get the app units per dev pixel ratio of the child document.
   PRInt32 GetChildAppUnitsPerDevPixel() { return mAPD; }
   // Get the app units per dev pixel ratio of the parent document.
   PRInt32 GetParentAppUnitsPerDevPixel() { return mParentAPD; }
 
 private:
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1638,17 +1638,20 @@ PresShell::InitialReflow(nscoord aWidth,
 
   NS_ENSURE_STATE(!mHaveShutDown);
 
   if (!rootFrame) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   for (nsIFrame* f = rootFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
-    f->RemoveStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
+    if (f->GetStateBits() & NS_FRAME_NO_COMPONENT_ALPHA) {
+      f->InvalidateFrameSubtree();
+      f->RemoveStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
+    }
   }
 
   Element *root = mDocument->GetRootElement();
 
   if (root) {
     {
       nsAutoCauseReflowNotifier reflowNotifier(this);
       mFrameConstructor->BeginUpdate();
--- a/layout/generic/nsFrameSelection.h
+++ b/layout/generic/nsFrameSelection.h
@@ -689,19 +689,21 @@ private:
 
   // maintain selection
   nsRefPtr<nsRange> mMaintainRange;
   nsSelectionAmount mMaintainedAmount;
 
   //batching
   PRInt32 mBatching;
     
-  nsIContent *mLimiter;     //limit selection navigation to a child of this node.
-  nsIContent *mAncestorLimiter; // Limit selection navigation to a descendant of
-                                // this node.
+  // Limit selection navigation to a child of this node.
+  nsCOMPtr<nsIContent> mLimiter;
+  // Limit selection navigation to a descendant of this node.
+  nsCOMPtr<nsIContent> mAncestorLimiter;
+
   nsIPresShell *mShell;
 
   PRInt16 mSelectionChangeReason; // reason for notifications of selection changing
   PRInt16 mDisplaySelection; //for visual display purposes.
 
   HINT  mHint;   //hint to tell if the selection is at the end of this line or beginning of next
 #ifdef IBMBIDI
   PRUint8 mCaretBidiLevel;
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -447,18 +447,16 @@ nsFrameSelection::nsFrameSelection()
   PRInt32 i;
   for (i = 0;i<nsISelectionController::NUM_SELECTIONTYPES;i++){
     mDomSelections[i] = new Selection(this);
     mDomSelections[i]->SetType(GetSelectionTypeFromIndex(i));
   }
   mBatching = 0;
   mChangesDuringBatching = false;
   mNotifyFrames = true;
-  mLimiter = nsnull; //no default limiter.
-  mAncestorLimiter = nsnull;
   
   mMouseDoubleDownState = false;
   
   mHint = HINTLEFT;
 #ifdef IBMBIDI
   mCaretBidiLevel = BIDI_LEVEL_UNDEFINED;
 #endif
   mDragSelectingCells = false;
@@ -501,16 +499,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCellParent)
   tmp->mSelectingTableCellMode = 0;
   tmp->mDragSelectingCells = false;
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mStartSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mEndSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAppendStartSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mUnselectCellOnMouseUp)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMaintainRange)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLimiter)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAncestorLimiter)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameSelection)
   if (tmp->mShell && tmp->mShell->GetDocument() &&
       nsCCUncollectableMarker::InGeneration(cb,
                                             tmp->mShell->GetDocument()->
                                               GetMarkedCCGeneration())) {
     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
   }
@@ -521,16 +521,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCellParent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStartSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mEndSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAppendStartSelectedCell)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mUnselectCellOnMouseUp)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mMaintainRange, nsIDOMRange)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLimiter)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mAncestorLimiter)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameSelection)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameSelection)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameSelection)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -264,36 +264,46 @@ MapAllAttributesIntoCSS(nsIFrame* aTable
           MapColAttributesIntoCSS(aTableFrame, rowFrame, cellFrame);
         }
       }
     }
   }
 }
 
 // the align attribute of mtable can have a row number which indicates
-// from where to anchor the table, e.g., top5 means anchor the table at
-// the top of the 5th row, axis-1 means anchor the table on the axis of
-// the last row (could have been nicer if the REC used the '#' separator,
-// e.g., top#5, or axis#-1)
+// from where to anchor the table, e.g., top 5 means anchor the table at
+// the top of the 5th row, axis -1 means anchor the table on the axis of
+// the last row
+
+// The REC says that the syntax is 
+// '\s*(top|bottom|center|baseline|axis)(\s+-?[0-9]+)?\s*' 
+// the parsing could have been simpler with that syntax
+// but for backward compatibility we make optional 
+// the whitespaces between the alignment name and the row number
 
 enum eAlign {
   eAlign_top,
   eAlign_bottom,
   eAlign_center,
   eAlign_baseline,
   eAlign_axis
 };
 
 static void
 ParseAlignAttribute(nsString& aValue, eAlign& aAlign, PRInt32& aRowIndex)
 {
   // by default, the table is centered about the axis
   aRowIndex = 0;
   aAlign = eAlign_axis;
   PRInt32 len = 0;
+
+  // we only have to remove the leading spaces because 
+  // ToInteger ignores the whitespaces around the number
+  aValue.CompressWhitespace(true, false);
+
   if (0 == aValue.Find("top")) {
     len = 3; // 3 is the length of 'top'
     aAlign = eAlign_top;
   }
   else if (0 == aValue.Find("bottom")) {
     len = 6; // 6 is the length of 'bottom'
     aAlign = eAlign_bottom;
   }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mtable-align-whitespace-ref.html
@@ -0,0 +1,336 @@
+<!DOCTYPE html>
+<head>
+<title>mtable align : WhiteSpace Check</title>
+</head>
+
+<body>
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math> 
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>   
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+   <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math> 
+ 
+<br><br><br>
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+
+
+
+</body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/mtable-align-whitespace.html
@@ -0,0 +1,332 @@
+<!DOCTYPE html>
+<head>
+<title>mtable align : WhiteSpace Check</title>
+</head>
+
+<body>
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center-3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center-3  ">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="  center-3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math> 
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="  center-3  ">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>   
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+   <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="  center   -3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center  -3  ">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="  center  -3  ">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+
+<br><br><br>
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="&#xA&#xD;&#x20;center&#xA&#xD;&#x20;-3&#xA&#xD;&#x9;">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="&#xA&#xD;&#x9;&#x20;center&#xA&#xD;&#x9;&#x20;-3&#xA&#xD;&#x9;&#x20;">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center-3&#xA&#xD;&#x9;&#x20;">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="&#xA&#xD;&#x9;&#x20;center-3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="&#xA&#xD;&#x9;&#x20;center-3&#xA&#xD;&#x9;&#x20;">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="&#xA&#xD;&#x9;&#x20;center&#xA&#xD;&#x9;&#x20;-3">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+    <math>  
+          
+        <mi>X</mi>  
+        <mo>=</mo>  
+        <mtable frame="solid" rowlines="solid" align="center&#xA&#xD;&#x9;&#x20;-3&#xA&#xD;&#x9;&#x20;">  
+            <mtr>  
+                 <mtd><mi>A</mi></mtd>  
+                 <mtd><mi>B</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>C</mi></mtd>  
+                 <mtd><mi>D</mi></mtd>  
+            </mtr>  
+            <mtr>  
+                 <mtd><mi>E</mi></mtd>  
+                 <mtd><mi>F</mi></mtd>  
+            </mtr>  
+        </mtable>  
+      
+    </math>  
+
+</body>
+</html>
--- a/layout/reftests/mathml/reftest.list
+++ b/layout/reftests/mathml/reftest.list
@@ -91,15 +91,16 @@ fails == mstyle-5.xhtml mstyle-5-ref.xht
 == munderover-align-accent-true.html munderover-align-accent-true-ref.html
 == munder-mover-align-accent-true.html munder-mover-align-accent-true-ref.html
 == munder-mover-align-accent-false.html munder-mover-align-accent-false-ref.html
 == mfrac-linethickness-1.xhtml mfrac-linethickness-1-ref.xhtml
 == mathml-negativespace.html mathml-negativespace-ref.html
 != link-1.xhtml link-ref.xhtml
 == munderover-empty-scripts.html munderover-empty-scripts-ref.html
 == positive-namedspace.html positive-namedspace-ref.html
+== mtable-align-whitespace.html mtable-align-whitespace-ref.html
 == mtable-width.html mtable-width-ref.html
 == maction-selection.html maction-selection-ref.html
 == maction-dynamic-embellished-op.html maction-dynamic-embellished-op-ref.html
 == maction-dynamic-1.html maction-dynamic-1-ref.html
 == maction-dynamic-2.html maction-dynamic-2-ref.html
 == mo-lspace-rspace.html mo-lspace-rspace-ref.html
 == maction-dynamic-3.html maction-dynamic-3-ref.html
--- a/mobile/android/base/Favicons.java
+++ b/mobile/android/base/Favicons.java
@@ -147,16 +147,20 @@ public class Favicons {
     private synchronized AndroidHttpClient getHttpClient() {
         if (mHttpClient != null)
             return mHttpClient;
 
         mHttpClient = AndroidHttpClient.newInstance(USER_AGENT);
         return mHttpClient;
     }
 
+    public String getFaviconUrlForPageUrl(String pageUrl) {
+        return mDbHelper.getFaviconUrlForPageUrl(pageUrl);
+    }
+
     public long loadFavicon(String pageUrl, String faviconUrl,
             OnFaviconLoadedListener listener) {
 
         // Handle the case where page url is empty
         if (pageUrl == null || pageUrl.length() == 0) {
             if (listener != null)
                 listener.onFaviconLoaded(null, null);
         }
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -189,22 +189,16 @@ abstract public class GeckoApp
     public ArrayList<PackageInfo> mPackageInfoCache = new ArrayList<PackageInfo>();
 
     // Returns null if plugins are blocked on the device.
     String[] getPluginDirectories() {
 
         // An awful hack to detect Tegra devices. Easiest way to do it without spinning up a EGL context.
         boolean isTegra = (new File("/system/lib/hw/gralloc.tegra.so")).exists();
         if (isTegra) {
-            // disable Flash on pre-HC Tegra (bug 703056)
-            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
-                Log.w(LOGTAG, "Blocking plugins because of Tegra 2 + Gingerbread bug (bug 703056)");
-                return null;
-            }
-
             // disable Flash on Tegra ICS with CM9 and other custom firmware (bug 736421)
             File vfile = new File("/proc/version");
             FileReader vreader = null;
             try {
                 if (vfile.canRead()) {
                     vreader = new FileReader(vfile);
                     String version = new BufferedReader(vreader).readLine();
                     if (version.indexOf("CM9") != -1 ||
@@ -714,17 +708,17 @@ abstract public class GeckoApp
       if (tab == null)
         return;
 
       String url = tab.getURL();
       if (url == null)
           return;
 
       GeckoAppShell.openUriExternal(url, "text/plain", "", "",
-                                    Intent.ACTION_SEND, tab.getTitle());
+                                    Intent.ACTION_SEND, tab.getDisplayTitle());
     }
 
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
 
         if (outState == null)
             outState = new Bundle();
 
@@ -852,16 +846,40 @@ abstract public class GeckoApp
     void handleReaderEnabled(final int tabId) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         tab.setReaderEnabled(true);
     }
 
+    void handleFaviconRequest(final String url) {
+        (new GeckoAsyncTask<Void, Void, String>() {
+            @Override
+            public String doInBackground(Void... params) {
+                return getFavicons().getFaviconUrlForPageUrl(url);
+            }
+
+            @Override
+            public void onPostExecute(String faviconUrl) {
+                if (faviconUrl != null) {
+                    JSONObject args = new JSONObject();
+                    try {
+                        args.put("url", url);
+                        args.put("faviconUrl", faviconUrl);
+                    } catch (JSONException e) {
+                        Log.e(LOGTAG, "error building json arguments");
+                    }
+
+                    GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Reader:FaviconReturn", args.toString()));
+                }
+            }
+        }).execute();
+    }
+
     void handleLoadError(final int tabId, final String uri, final String title) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         // When a load error occurs, the URLBar can get corrupt so we reset it
         mMainHandler.post(new Runnable() {
             public void run() {
@@ -1032,16 +1050,19 @@ abstract public class GeckoApp
             } else if (event.equals("Content:SecurityChange")) {
                 final int tabId = message.getInt("tabID");
                 final JSONObject identity = message.getJSONObject("identity");
                 Log.i(LOGTAG, "Security Mode - " + identity.getString("mode"));
                 handleSecurityChange(tabId, identity);
             } else if (event.equals("Content:ReaderEnabled")) {
                 final int tabId = message.getInt("tabID");
                 handleReaderEnabled(tabId);
+            } else if (event.equals("Reader:FaviconRequest")) {
+                final String url = message.getString("url");
+                handleFaviconRequest(url);
             } else if (event.equals("Content:StateChange")) {
                 final int tabId = message.getInt("tabID");
                 final String uri = message.getString("uri");
                 final boolean success = message.getBoolean("success");
                 int state = message.getInt("state");
                 Log.i(LOGTAG, "State - " + state);
                 if ((state & GeckoAppShell.WPL_STATE_IS_NETWORK) != 0) {
                     if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
@@ -1863,16 +1884,17 @@ abstract public class GeckoApp
         GeckoAppShell.registerGeckoEventListener("DOMWindowClose", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("log", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Content:LocationChange", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Content:SecurityChange", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Content:ReaderEnabled", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Content:StateChange", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Content:LoadError", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Content:PageShow", GeckoApp.mAppContext);
+        GeckoAppShell.registerGeckoEventListener("Reader:FaviconRequest", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("onCameraCapture", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Doorhanger:Add", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Doorhanger:Remove", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Menu:Add", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Menu:Remove", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Gecko:Ready", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("Toast:Show", GeckoApp.mAppContext);
         GeckoAppShell.registerGeckoEventListener("DOMFullScreen:Start", GeckoApp.mAppContext);
@@ -2227,16 +2249,17 @@ abstract public class GeckoApp
         GeckoAppShell.unregisterGeckoEventListener("DOMWindowClose", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("log", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Content:LocationChange", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Content:SecurityChange", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Content:ReaderEnabled", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Content:StateChange", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Content:LoadError", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Content:PageShow", GeckoApp.mAppContext);
+        GeckoAppShell.unregisterGeckoEventListener("Reader:FaviconRequest", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("onCameraCapture", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Doorhanger:Add", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Doorhanger:Remove", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Menu:Add", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Menu:Remove", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Gecko:Ready", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("Toast:Show", GeckoApp.mAppContext);
         GeckoAppShell.unregisterGeckoEventListener("DOMFullScreen:Start", GeckoApp.mAppContext);
@@ -2928,17 +2951,17 @@ abstract public class GeckoApp
                     }
                 }
                 return true;
             }
             case R.id.add_to_launcher: {
                 Tab tab = Tabs.getInstance().getSelectedTab();
                 if (tab != null) {
                     String url = tab.getURL();
-                    String title = tab.getTitle();
+                    String title = tab.getDisplayTitle();
                     BitmapDrawable favicon = (BitmapDrawable)(tab.getFavicon());
                     if (url != null && title != null) {
                         GeckoAppShell.createShortcut(title, url, url, favicon == null ? null : favicon.getBitmap(), "");
                     }
                 }
                 return true;
             }
         }
--- a/mobile/android/base/GeckoInputConnection.java
+++ b/mobile/android/base/GeckoInputConnection.java
@@ -431,17 +431,21 @@ public class GeckoInputConnection
             return false;
         }
 
         commitText(null, 1);
         return true;
     }
 
     private static InputMethodManager getInputMethodManager() {
-        Context context = getView().getContext();
+        View view = getView();
+        if (view == null) {
+            return null;
+        }
+        Context context = view.getContext();
         return InputMethods.getInputMethodManager(context);
     }
 
     protected void notifyTextChange(InputMethodManager imm, String text,
                                     int start, int oldEnd, int newEnd) {
         if (!mBatchMode) {
             if (!text.contentEquals(mEditable)) {
                 if (DEBUG) Log.d(LOGTAG, ". . . notifyTextChange: current mEditable="
--- a/mobile/android/base/PromptService.java
+++ b/mobile/android/base/PromptService.java
@@ -462,36 +462,22 @@ public class PromptService implements On
     }
 
     public class PromptListAdapter extends ArrayAdapter<PromptListItem> {
         private static final int VIEW_TYPE_ITEM = 0;
         private static final int VIEW_TYPE_GROUP = 1;
         private static final int VIEW_TYPE_COUNT = 2;
 
         public ListView listView = null;
-    	private PromptListItem[] mList;
     	private int mResourceId = -1;
     	PromptListAdapter(Context context, int textViewResourceId, PromptListItem[] objects) {
             super(context, textViewResourceId, objects);
-            mList = objects;
             mResourceId = textViewResourceId;
     	}
 
-        public int getCount() {
-            return mList.length;
-        }
-
-        public PromptListItem getItem(int position) {
-            return mList[position];
-        }
-
-        public long getItemId(int position) {
-            return mList[position].id;
-        }
-
         @Override
         public int getItemViewType(int position) {
             PromptListItem item = getItem(position);
             return (item.isGroup ? VIEW_TYPE_GROUP : VIEW_TYPE_ITEM);
         }
 
         @Override
         public int getViewTypeCount() {
@@ -543,16 +529,17 @@ public class PromptService implements On
                 listView.setItemChecked(position, mSelected[position]);
 
             ct.setPadding((item.inGroup ? mGroupPaddingSize : viewHolder.paddingLeft),
                           viewHolder.paddingTop,
                           viewHolder.paddingRight,
                           viewHolder.paddingBottom);
         }
 
+        @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             PromptListItem item = getItem(position);
             ViewHolder viewHolder = null;
 
             if (convertView == null) {
                 int resourceId = mResourceId;
                 if (item.isGroup) {
                     resourceId = R.layout.list_item_header;
--- a/mobile/android/base/Tab.java
+++ b/mobile/android/base/Tab.java
@@ -119,20 +119,16 @@ public final class Tab {
         return mParentId;
     }
 
     // may be null if user-entered query hasn't yet been resolved to a URI
     public String getURL() {
         return mUrl;
     }
 
-    public String getTitle() {
-        return mTitle;
-    }
-
     public String getDisplayTitle() {
         if (mTitle != null && mTitle.length() > 0) {
             return mTitle;
         }
 
         return mUrl;
     }
 
@@ -408,17 +404,17 @@ public final class Tab {
 
     public void addBookmark() {
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 String url = getURL();
                 if (url == null)
                     return;
 
-                BrowserDB.addBookmark(mContentResolver, getTitle(), url);
+                BrowserDB.addBookmark(mContentResolver, mTitle, url);
             }
         });
     }
 
     public void removeBookmark() {
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 String url = getURL();
--- a/mobile/android/base/awesomebar/AllPagesTab.java
+++ b/mobile/android/base/awesomebar/AllPagesTab.java
@@ -537,18 +537,18 @@ public class AllPagesTab extends Awesome
         Cursor cursor = ((AwesomeBarCursorItem) selectedItem).getCursor();
 
         // Don't show the context menu for folders
         String keyword = null;
         int keywordCol = cursor.getColumnIndex(URLColumns.KEYWORD);
         if (keywordCol != -1)
             keyword = cursor.getString(keywordCol);
 
-        // Use the bookmark id for the Bookmarks tab and the history id for the Top Sites tab 
-        int id = cursor.getInt(cursor.getColumnIndexOrThrow(Combined._ID));
+        // Use the history id in order to allow removing history entries
+        int id = cursor.getInt(cursor.getColumnIndexOrThrow(Combined.HISTORY_ID));
 
         subject = new ContextMenuSubject(id,
                                         cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.URL)),
                                         cursor.getBlob(cursor.getColumnIndexOrThrow(URLColumns.FAVICON)),
                                         cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.TITLE)),
                                         keyword);
 
         if (subject == null)
--- a/mobile/android/base/awesomebar/BookmarksTab.java
+++ b/mobile/android/base/awesomebar/BookmarksTab.java
@@ -409,17 +409,16 @@ public class BookmarksTab extends Awesom
 
         // Don't show the context menu for folders
         if (!(cursor.getInt(cursor.getColumnIndexOrThrow(Bookmarks.TYPE)) == Bookmarks.TYPE_FOLDER)) {
             String keyword = null;
             int keywordCol = cursor.getColumnIndex(URLColumns.KEYWORD);
             if (keywordCol != -1)
                 keyword = cursor.getString(keywordCol);
 
-            // Use the bookmark id for the Bookmarks tab and the history id for the Top Sites tab 
             int id = cursor.getInt(cursor.getColumnIndexOrThrow(Bookmarks._ID));
 
             subject = new ContextMenuSubject(id,
                                             cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.URL)),
                                             cursor.getBlob(cursor.getColumnIndexOrThrow(URLColumns.FAVICON)),
                                             cursor.getString(cursor.getColumnIndexOrThrow(URLColumns.TITLE)),
                                             keyword);
         }
--- a/mobile/android/chrome/content/Readability.js
+++ b/mobile/android/chrome/content/Readability.js
@@ -73,16 +73,19 @@ Readability.prototype = {
   /**
    * Run any post-process modifications to article content as necessary.
    *
    * @param Element
    * @return void
   **/
   _postProcessContent: function(articleContent) {
     this._fixImageFloats(articleContent);
+
+    // Readability cannot open relative uris so we convert them to absolute uris. 
+    this._fixRelativeUris(articleContent);
   },
 
   /**
    * Some content ends up looking ugly if the image is too large to be floated.
    * If the image is wider than a threshold (currently 55%), no longer float it,
    * center it instead.
    *
    * @param Element
@@ -96,16 +99,58 @@ Readability.prototype = {
       let image = images[i];
 
       if (image.offsetWidth > imageWidthThreshold)
         image.className += " blockImage";
     }
   },
 
   /**
+   * Converts each <a> and <img> uri in the given element to an absolute URI.
+   *
+   * @param Element
+   * @return void
+   */
+  _fixRelativeUris: function(articleContent) {
+    let baseUri = this._uri;
+    let ioService = Cc["@mozilla.org/network/io-service;1"]
+        .getService(Components.interfaces.nsIIOService);
+
+    // Fix links.
+    let links = articleContent.getElementsByTagName('a');
+    for (let i = links.length - 1; i >= 0; i--) {
+      links[i].href = this._newURIErrorWrapper(links[i].href, baseUri, ioService);
+    }
+
+    // Fix images.
+    let images = articleContent.getElementsByTagName('img');
+    for (let i = images.length - 1; i >= 0; i--) {
+      images[i].src = this._newURIErrorWrapper(images[i].src, baseUri, ioService);
+    }
+  },
+
+  /**
+   * Converts the given parameters into a new nsIURI object and returns the "spec" attribute of it.
+   * Catches errors of the newURI method and returns an appropriate value.
+   *
+   * @param string
+   * @param nsIURI
+   * @param nsIIOService
+   * @return string
+   */
+  _newURIErrorWrapper: function(aSpec, aBaseURI, ioService) {
+    try {
+      return ioService.newURI(aSpec, null, aBaseURI).spec;
+    } catch (err) {
+      dump("_newURIErrorWrapper: " + err.message);
+      return "";
+    }
+  },
+
+  /**
    * Get the article title as an H1.
    *
    * @return void
    **/
   _getArticleTitle: function() {
     let doc = this._doc;
     let curTitle = "";
     let origTitle = "";
--- a/mobile/android/chrome/content/aboutReader.html
+++ b/mobile/android/chrome/content/aboutReader.html
@@ -1,17 +1,16 @@
 <!DOCTYPE html>
 <html>
 
 <head>
   <title></title>
   <meta content="text/html; charset=UTF-8" http-equiv="content-type">
   <meta name="viewport" content="width=device-width; user-scalable=0" />
 
-  <link rel="icon" type="image/png" href="chrome://branding/content/favicon32.png" />
   <link rel="stylesheet" href="chrome://browser/skin/aboutReader.css" type="text/css"/>
 </head>
 
 <body onload="AboutReader.init();" onunload="AboutReader.uninit();">
   <div id="reader-header" class="header">
   </div>
 
   <div id="reader-content" class="content">
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -24,16 +24,18 @@ let gStrings = Services.strings.createBu
 
 let AboutReader = {
   _STEP_INCREMENT: 0,
   _STEP_DECREMENT: 1,
 
   init: function Reader_init() {
     dump("Init()");
 
+    Services.obs.addObserver(this, "Reader:FaviconReturn", false);
+
     this._article = null;
 
     dump("Feching toolbar, header and content notes from about:reader");
     this._titleElement = document.getElementById("reader-header");
     this._contentElement = document.getElementById("reader-content");
     this._toolbarElement = document.getElementById("reader-toolbar");
 
     this._toolbarEnabled = false;
@@ -83,16 +85,26 @@ let AboutReader = {
       var tabId = queryArgs.tabId;
       if (tabId) {
         dump("Loading from tab with ID: " + tabId);
         this._loadFromTab(tabId);
       }
     }
   },
 
+  observe: function(aMessage, aTopic, aData) {
+    switch(aTopic) {
+      case "Reader:FaviconReturn": {
+        let info = JSON.parse(aData);
+        this._loadFavicon(info.url, info.faviconUrl);
+        break;
+      }
+    }
+  },
+
   handleEvent: function Reader_handleEvent(aEvent) {
     switch (aEvent.type) {
       case "touchstart":
         this._scrolled = false;
         break;
       case "click":
         if (!this._scrolled)
           this._toggleToolbarVisibility();
@@ -108,16 +120,18 @@ let AboutReader = {
           this._closeAllDropdowns();
         break;
     }
   },
 
   uninit: function Reader_uninit() {
     dump("Uninit()");
 
+    Services.obs.removeObserver(this, "Reader:FaviconReturn", false);
+
     let body = document.body;
     body.removeEventListener("touchstart", this, false);
     body.removeEventListener("click", this, false);
     window.removeEventListener("scroll", this, false);
     window.removeEventListener("popstate", this, false);
 
     this._hideContent();
   },
@@ -238,16 +252,36 @@ let AboutReader = {
     gChromeWin.Reader.parseDocumentFromTab(tabId, function(article) {
       if (article)
         this._showContent(article);
       else
         this._showError(gStrings.GetStringFromName("aboutReader.loadError"));
     }.bind(this));
   },
 
+  _requestFavicon: function Reader_requestFavicon() {
+    gChromeWin.sendMessageToJava({
+      gecko: {
+        type: "Reader:FaviconRequest",
+        url: this._article.url
+      }
+    });
+  },
+
+  _loadFavicon: function Reader_loadFavicon(url, faviconUrl) {
+    if (this._article.url !== url)
+      return;
+
+    let link = document.createElement('link');
+    link.rel = 'shortcut icon';
+    link.href = faviconUrl;
+
+    document.getElementsByTagName('head')[0].appendChild(link);
+  },
+
   _showError: function Reader_showError(error) {
     this._titleElement.style.display = "none";
     this._contentElement.innerHTML = error;
     this._contentElement.style.display = "block";
 
     document.title = error;
   },
 
@@ -259,16 +293,18 @@ let AboutReader = {
 
     this._contentElement.innerHTML = article.content;
     this._contentElement.style.display = "block";
 
     document.title = article.title;
 
     this._toolbarEnabled = true;
     this._setToolbarVisibility(true);
+
+    this._requestFavicon();
   },
 
   _hideContent: function Reader_hideContent() {
     this._titleElement.style.display = "none";
     this._contentElement.style.display = "none";
   },
 
   _showProgress: function Reader_showProgress() {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2156,16 +2156,17 @@ Tab.prototype = {
     this.browser.addEventListener("DOMContentLoaded", this, true);
     this.browser.addEventListener("DOMLinkAdded", this, true);
     this.browser.addEventListener("DOMTitleChanged", this, true);
     this.browser.addEventListener("DOMWindowClose", this, true);
     this.browser.addEventListener("DOMWillOpenModalDialog", this, true);
     this.browser.addEventListener("scroll", this, true);
     this.browser.addEventListener("MozScrolledAreaChanged", this, true);
     this.browser.addEventListener("PluginClickToPlay", this, true);
+    this.browser.addEventListener("PluginNotFound", this, true);
     this.browser.addEventListener("pageshow", this, true);
 
     Services.obs.addObserver(this, "before-first-paint", false);
     Services.prefs.addObserver("browser.ui.zoom.force-user-scalable", this, false);
 
     if (!aParams.delayLoad) {
       let flags = "flags" in aParams ? aParams.flags : Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
       let postData = ("postData" in aParams && aParams.postData) ? aParams.postData.value : null;
@@ -2248,16 +2249,17 @@ Tab.prototype = {
     this.browser.removeProgressListener(this);
     this.browser.removeEventListener("DOMContentLoaded", this, true);
     this.browser.removeEventListener("DOMLinkAdded", this, true);
     this.browser.removeEventListener("DOMTitleChanged", this, true);
     this.browser.removeEventListener("DOMWindowClose", this, true);
     this.browser.removeEventListener("DOMWillOpenModalDialog", this, true);
     this.browser.removeEventListener("scroll", this, true);
     this.browser.removeEventListener("PluginClickToPlay", this, true);
+    this.browser.removeEventListener("PluginNotFound", this, true);
     this.browser.removeEventListener("MozScrolledAreaChanged", this, true);
 
     Services.obs.removeObserver(this, "before-first-paint");
     Services.prefs.removeObserver("browser.ui.zoom.force-user-scalable", this);
 
     // Make sure the previously selected panel remains selected. The selected panel of a deck is
     // not stable when panels are removed.
     let selectedPanel = BrowserApp.deck.selectedPanel;
@@ -2796,16 +2798,31 @@ Tab.prototype = {
           tab.clickToPlayPluginsActivated = true;
           PluginHelper.playAllPlugins(win);
 
           NativeWindow.doorhanger.hide("ask-to-play-plugins", tab.id);
         }, true);
         break;
       }
 
+      case "PluginNotFound": {
+        let plugin = aEvent.target;
+        plugin.clientTop; // force style flush
+
+        // On devices where we don't support Flash, there will be a "Learn More..." link in
+        // the missing plugin error message.
+        let learnMoreLink = plugin.ownerDocument.getAnonymousElementByAttribute(plugin, "class", "unsupportedLearnMoreLink");
+        if (learnMoreLink) {
+          let learnMoreUrl = Services.urlFormatter.formatURLPref("app.support.baseURL");
+          learnMoreUrl += "why-cant-firefox-mobile-play-flash-on-my-device";
+          learnMoreLink.href = learnMoreUrl;
+        }
+        break;
+      }
+
       case "pageshow": {
         // only send pageshow for the top-level document
         if (aEvent.originalTarget.defaultView != this.browser.contentWindow)
           return;
 
         sendMessageToJava({
           gecko: {
             type: "Content:PageShow",
--- a/mobile/android/components/PromptService.js
+++ b/mobile/android/components/PromptService.js
@@ -256,17 +256,17 @@ Prompt.prototype = {
       aCheckState.value = data.checkbox == "true";
     if (ok)
       aValue.value = data.textbox;
     return ok;
   },
 
   nsIPrompt_promptPassword: function nsIPrompt_promptPassword(
       aTitle, aText, aPassword, aCheckMsg, aCheckState) {
-    let inputs = [{ type: "password", hint: "Password", value: aPassword.value || "" }];
+    let inputs = [{ type: "password", hint: PromptUtils.getLocaleString("password", "passwdmgr"), value: aPassword.value || "" }];
     let data = this.commonPrompt(aTitle, aText, null, aCheckMsg, aCheckState, inputs);
 
     let ok = data.button == 0;
     if (aCheckMsg)
       aCheckState.value = data.checkbox == "true";
     if (ok)
       aPassword.value = data.password;
     return ok;
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -161,17 +161,19 @@ pref("media.opus.enabled", true);
 pref("media.wave.enabled", true);
 #endif
 #ifdef MOZ_WEBM
 pref("media.webm.enabled", true);
 #endif
 #ifdef MOZ_GSTREAMER
 pref("media.h264.enabled", true);
 #endif
-
+#ifdef MOZ_WEBRTC
+pref("media.navigator.enabled", false);
+#endif
 
 // Whether to autostart a media element with an |autoplay| attribute
 pref("media.autoplay.enabled", true);
 
 // 0 = Off, 1 = Full, 2 = Tagged Images Only. 
 // See eCMSMode in gfx/thebes/gfxPlatform.h
 pref("gfx.color_management.mode", 2);
 pref("gfx.color_management.display_profile", "");
@@ -220,20 +222,27 @@ pref("gfx.font_rendering.harfbuzz.script
 
 #ifdef XP_WIN
 pref("gfx.font_rendering.directwrite.enabled", false);
 pref("gfx.font_rendering.directwrite.use_gdi_table_loading", true);
 #endif
 
 #ifdef XP_WIN
 pref("gfx.canvas.azure.enabled", true);
+// comma separated list of backends to use in order of preference
+// e.g., pref("gfx.canvas.azure.backends", "direct2d,skia,cairo");
+pref("gfx.canvas.azure.backends", "direct2d");
 pref("gfx.content.azure.enabled", true);
 #else
 #ifdef XP_MACOSX
 pref("gfx.canvas.azure.enabled", true);
+pref("gfx.canvas.azure.backends", "cg");
+#else
+pref("gfx.canvas.azure.enabled", false);
+pref("gfx.canvas.azure.backends", "cairo,skia");
 #endif
 #endif
 
 #ifdef ANDROID
 pref("gfx.textures.poweroftwo.force-enabled", false);
 #endif
 
 pref("gfx.work-around-driver-bugs", true);
--- a/netwerk/protocol/http/nsHttpChannelAuthProvider.h
+++ b/netwerk/protocol/http/nsHttpChannelAuthProvider.h
@@ -12,16 +12,17 @@
 #include "nsIAuthPromptCallback.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIHttpAuthenticableChannel.h"
 #include "nsIURI.h"
 #include "nsHttpAuthCache.h"
 #include "nsProxyInfo.h"
 #include "nsIDNSListener.h"
+#include "mozilla/Attributes.h"
 
 class nsIHttpAuthenticator;
 
 class nsHttpChannelAuthProvider : public nsIHttpChannelAuthProvider
                                 , public nsIAuthPromptCallback
 {
 public:
     NS_DECL_ISUPPORTS
@@ -146,17 +147,17 @@ private:
     // 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
+    class DNSCallback MOZ_FINAL : public nsIDNSListener
     {
         NS_DECL_ISUPPORTS
         NS_DECL_NSIDNSLISTENER
 
         DNSCallback(nsHttpChannelAuthProvider *authProvider)
             : mAuthProvider(authProvider)
         { }
 
rename from other-licenses/simplejson-2.1.1/CHANGES.txt
rename to python/simplejson-2.1.1/CHANGES.txt
rename from other-licenses/simplejson-2.1.1/LICENSE.txt
rename to python/simplejson-2.1.1/LICENSE.txt
rename from other-licenses/simplejson-2.1.1/PKG-INFO
rename to python/simplejson-2.1.1/PKG-INFO
rename from other-licenses/simplejson-2.1.1/conf.py
rename to python/simplejson-2.1.1/conf.py
rename from other-licenses/simplejson-2.1.1/docs/_sources/index.txt
rename to python/simplejson-2.1.1/docs/_sources/index.txt
rename from other-licenses/simplejson-2.1.1/docs/_static/contents.png
rename to python/simplejson-2.1.1/docs/_static/contents.png
rename from other-licenses/simplejson-2.1.1/docs/_static/default.css
rename to python/simplejson-2.1.1/docs/_static/default.css
rename from other-licenses/simplejson-2.1.1/docs/_static/doctools.js
rename to python/simplejson-2.1.1/docs/_static/doctools.js
rename from other-licenses/simplejson-2.1.1/docs/_static/file.png
rename to python/simplejson-2.1.1/docs/_static/file.png
rename from other-licenses/simplejson-2.1.1/docs/_static/interface.js
rename to python/simplejson-2.1.1/docs/_static/interface.js
rename from other-licenses/simplejson-2.1.1/docs/_static/jquery.js
rename to python/simplejson-2.1.1/docs/_static/jquery.js
rename from other-licenses/simplejson-2.1.1/docs/_static/minus.png
rename to python/simplejson-2.1.1/docs/_static/minus.png
rename from other-licenses/simplejson-2.1.1/docs/_static/navigation.png
rename to python/simplejson-2.1.1/docs/_static/navigation.png
rename from other-licenses/simplejson-2.1.1/docs/_static/plus.png
rename to python/simplejson-2.1.1/docs/_static/plus.png
rename from other-licenses/simplejson-2.1.1/docs/_static/pygments.css
rename to python/simplejson-2.1.1/docs/_static/pygments.css
rename from other-licenses/simplejson-2.1.1/docs/_static/rightsidebar.css
rename to python/simplejson-2.1.1/docs/_static/rightsidebar.css
rename from other-licenses/simplejson-2.1.1/docs/_static/searchtools.js
rename to python/simplejson-2.1.1/docs/_static/searchtools.js
rename from other-licenses/simplejson-2.1.1/docs/_static/sphinxdoc.css
rename to python/simplejson-2.1.1/docs/_static/sphinxdoc.css
rename from other-licenses/simplejson-2.1.1/docs/_static/stickysidebar.css
rename to python/simplejson-2.1.1/docs/_static/stickysidebar.css
rename from other-licenses/simplejson-2.1.1/docs/_static/traditional.css
rename to python/simplejson-2.1.1/docs/_static/traditional.css
rename from other-licenses/simplejson-2.1.1/docs/genindex.html
rename to python/simplejson-2.1.1/docs/genindex.html
rename from other-licenses/simplejson-2.1.1/docs/index.html
rename to python/simplejson-2.1.1/docs/index.html
rename from other-licenses/simplejson-2.1.1/docs/objects.inv
rename to python/simplejson-2.1.1/docs/objects.inv
rename from other-licenses/simplejson-2.1.1/docs/search.html
rename to python/simplejson-2.1.1/docs/search.html
rename from other-licenses/simplejson-2.1.1/docs/searchindex.js
rename to python/simplejson-2.1.1/docs/searchindex.js
rename from other-licenses/simplejson-2.1.1/docs/searchindex.json
rename to python/simplejson-2.1.1/docs/searchindex.json
rename from other-licenses/simplejson-2.1.1/ez_setup.py
rename to python/simplejson-2.1.1/ez_setup.py
rename from other-licenses/simplejson-2.1.1/index.rst
rename to python/simplejson-2.1.1/index.rst
rename from other-licenses/simplejson-2.1.1/scripts/make_docs.py
rename to python/simplejson-2.1.1/scripts/make_docs.py
rename from other-licenses/simplejson-2.1.1/setup.cfg
rename to python/simplejson-2.1.1/setup.cfg
rename from other-licenses/simplejson-2.1.1/setup.py
rename to python/simplejson-2.1.1/setup.py
rename from other-licenses/simplejson-2.1.1/simplejson/__init__.py
rename to python/simplejson-2.1.1/simplejson/__init__.py
rename from other-licenses/simplejson-2.1.1/simplejson/_speedups.c
rename to python/simplejson-2.1.1/simplejson/_speedups.c
rename from other-licenses/simplejson-2.1.1/simplejson/decoder.py
rename to python/simplejson-2.1.1/simplejson/decoder.py
rename from other-licenses/simplejson-2.1.1/simplejson/encoder.py
rename to python/simplejson-2.1.1/simplejson/encoder.py
rename from other-licenses/simplejson-2.1.1/simplejson/ordered_dict.py
rename to python/simplejson-2.1.1/simplejson/ordered_dict.py
rename from other-licenses/simplejson-2.1.1/simplejson/scanner.py
rename to python/simplejson-2.1.1/simplejson/scanner.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/__init__.py
rename to python/simplejson-2.1.1/simplejson/tests/__init__.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_check_circular.py
rename to python/simplejson-2.1.1/simplejson/tests/test_check_circular.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_decimal.py
rename to python/simplejson-2.1.1/simplejson/tests/test_decimal.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_decode.py
rename to python/simplejson-2.1.1/simplejson/tests/test_decode.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_default.py
rename to python/simplejson-2.1.1/simplejson/tests/test_default.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_dump.py
rename to python/simplejson-2.1.1/simplejson/tests/test_dump.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_encode_basestring_ascii.py
rename to python/simplejson-2.1.1/simplejson/tests/test_encode_basestring_ascii.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_encode_for_html.py
rename to python/simplejson-2.1.1/simplejson/tests/test_encode_for_html.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_fail.py
rename to python/simplejson-2.1.1/simplejson/tests/test_fail.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_float.py
rename to python/simplejson-2.1.1/simplejson/tests/test_float.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_indent.py
rename to python/simplejson-2.1.1/simplejson/tests/test_indent.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_pass1.py
rename to python/simplejson-2.1.1/simplejson/tests/test_pass1.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_pass2.py
rename to python/simplejson-2.1.1/simplejson/tests/test_pass2.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_pass3.py
rename to python/simplejson-2.1.1/simplejson/tests/test_pass3.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_recursion.py
rename to python/simplejson-2.1.1/simplejson/tests/test_recursion.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_scanstring.py
rename to python/simplejson-2.1.1/simplejson/tests/test_scanstring.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_separators.py
rename to python/simplejson-2.1.1/simplejson/tests/test_separators.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_speedups.py
rename to python/simplejson-2.1.1/simplejson/tests/test_speedups.py
rename from other-licenses/simplejson-2.1.1/simplejson/tests/test_unicode.py
rename to python/simplejson-2.1.1/simplejson/tests/test_unicode.py
rename from other-licenses/simplejson-2.1.1/simplejson/tool.py
rename to python/simplejson-2.1.1/simplejson/tool.py
rename from other-licenses/virtualenv/AUTHORS.txt
rename to python/virtualenv/AUTHORS.txt
rename from other-licenses/virtualenv/LICENSE.txt
rename to python/virtualenv/LICENSE.txt
rename from other-licenses/virtualenv/MANIFEST.in
rename to python/virtualenv/MANIFEST.in
rename from other-licenses/virtualenv/PKG-INFO
rename to python/virtualenv/PKG-INFO
rename from other-licenses/virtualenv/docs/index.txt
rename to python/virtualenv/docs/index.txt
rename from other-licenses/virtualenv/docs/news.txt
rename to python/virtualenv/docs/news.txt
rename from other-licenses/virtualenv/scripts/virtualenv
rename to python/virtualenv/scripts/virtualenv
rename from other-licenses/virtualenv/setup.cfg
rename to python/virtualenv/setup.cfg
rename from other-licenses/virtualenv/setup.py
rename to python/virtualenv/setup.py
rename from other-licenses/virtualenv/virtualenv.py
rename to python/virtualenv/virtualenv.py
rename from other-licenses/virtualenv/virtualenv_embedded/activate.bat
rename to python/virtualenv/virtualenv_embedded/activate.bat
rename from other-licenses/virtualenv/virtualenv_embedded/activate.csh
rename to python/virtualenv/virtualenv_embedded/activate.csh
rename from other-licenses/virtualenv/virtualenv_embedded/activate.fish
rename to python/virtualenv/virtualenv_embedded/activate.fish
rename from other-licenses/virtualenv/virtualenv_embedded/activate.ps1
rename to python/virtualenv/virtualenv_embedded/activate.ps1
rename from other-licenses/virtualenv/virtualenv_embedded/activate.sh
rename to python/virtualenv/virtualenv_embedded/activate.sh
rename from other-licenses/virtualenv/virtualenv_embedded/activate_this.py
rename to python/virtualenv/virtualenv_embedded/activate_this.py
rename from other-licenses/virtualenv/virtualenv_embedded/deactivate.bat
rename to python/virtualenv/virtualenv_embedded/deactivate.bat
rename from other-licenses/virtualenv/virtualenv_embedded/distribute_setup.py
rename to python/virtualenv/virtualenv_embedded/distribute_setup.py
rename from other-licenses/virtualenv/virtualenv_embedded/distutils-init.py
rename to python/virtualenv/virtualenv_embedded/distutils-init.py
rename from other-licenses/virtualenv/virtualenv_embedded/distutils.cfg
rename to python/virtualenv/virtualenv_embedded/distutils.cfg
rename from other-licenses/virtualenv/virtualenv_embedded/ez_setup.py
rename to python/virtualenv/virtualenv_embedded/ez_setup.py
rename from other-licenses/virtualenv/virtualenv_embedded/site.py
rename to python/virtualenv/virtualenv_embedded/site.py
rename from other-licenses/virtualenv/virtualenv_support/__init__.py
rename to python/virtualenv/virtualenv_support/__init__.py
rename from other-licenses/virtualenv/virtualenv_support/distribute-0.6.27.tar.gz
rename to python/virtualenv/virtualenv_support/distribute-0.6.27.tar.gz
rename from other-licenses/virtualenv/virtualenv_support/pip-1.1.tar.gz
rename to python/virtualenv/virtualenv_support/pip-1.1.tar.gz
rename from other-licenses/virtualenv/virtualenv_support/setuptools-0.6c11-py2.4.egg
rename to python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.4.egg
rename from other-licenses/virtualenv/virtualenv_support/setuptools-0.6c11-py2.5.egg
rename to python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.5.egg
rename from other-licenses/virtualenv/virtualenv_support/setuptools-0.6c11-py2.6.egg
rename to python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.6.egg
rename from other-licenses/virtualenv/virtualenv_support/setuptools-0.6c11-py2.7.egg
rename to python/virtualenv/virtualenv_support/setuptools-0.6c11-py2.7.egg
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -11,16 +11,17 @@
  "content/base/test/test_bug166235.html": "",
  "content/base/test/test_bug338583.html": "",
  "content/base/test/test_bug466080.html": "",
  "content/base/test/test_bug503481.html": "TIMED_OUT",
  "content/base/test/test_bug503481b.html": "TIMED_OUT",
  "content/base/test/test_bug505783.html": "TIMED_OUT",
  "content/base/test/test_copypaste.html": "",
  "content/base/test/test_csp_redirects.html": "TIMED_OUT",
+ "content/base/test/test_fileapi_slice.html": "bug 775227",
  "content/base/test/test_mozfiledataurl.html": "TIMED_OUT",
  "content/base/test/test_mutationobservers.html": "",
  "content/base/test/test_plugin_freezing.html": "CLICK_TO_PLAY",
  "content/base/test/test_range_bounds.html": "",
  "content/base/test/test_reentrant_flush.html": "RANDOM",
  "content/base/test/test_sync_xhr_timer.xhtml": "RANDOM",
  "content/base/test/test_websocket.html": "",
  "content/base/test/test_websocket_basic.html": "",
@@ -28,16 +29,17 @@
  "content/base/test/test_x-frame-options.html": "",
  "content/base/test/test_xhr_abort_after_load.html": "",
  "content/base/test/test_xhr_forbidden_headers.html": "",
  "content/base/test/test_xhr_progressevents.html": "",
  "content/base/test/websocket_hybi/test_receive-arraybuffer.html": "",
  "content/base/test/websocket_hybi/test_receive-blob.html": "",
  "content/base/test/websocket_hybi/test_send-arraybuffer.html": "",
  "content/base/test/websocket_hybi/test_send-blob.html": "",
+ "content/canvas/test/webgl/test_webgl_conformance_test_suite.html": "bug 775227",
  "content/events/test/test_bug409604.html": "TIMED_OUT",
  "content/events/test/test_bug426082.html": "",
  "content/events/test/test_bug457672.html": "CRASH_DUMP, RANDOM",
  "content/events/test/test_bug502818.html": "CRASH_DUMP, RANDOM",
  "content/events/test/test_bug508479.html": "CRASH_DUMP, RANDOM",
  "content/events/test/test_bug508906.html": "CRASH_DUMP, RANDOM",
  "content/events/test/test_bug517851.htm": "CRASH_DUMP, RANDOM",
  "content/events/test/test_bug534833.html": "CRASH_DUMP, RANDOM",
@@ -102,44 +104,57 @@
  "content/media/test/test_decoder_disable.html": "",
  "content/media/test/test_fragment_noplay.html": "",
  "content/media/test/test_fragment_play.html": "",
  "content/media/test/test_framebuffer.html": "",
  "content/media/test/test_media_selection.html": "",
  "content/media/test/test_playback.html": "",
  "content/media/test/test_seekLies.html": "TIMED_OUT",
  "content/media/test/test_seekable2.html": "",
+ "content/media/test/test_too_many_elements.html": "bug 775227",
  "content/media/test/test_wave_data_s16.html": "TIMED_OUT",
  "content/media/test/test_wave_data_u8.html": "TIMED_OUT",
  "content/smil/test/test_smilRepeatTiming.xhtml": "TIMED_OUT",
  "content/smil/test/test_smilExtDoc.xhtml": "",
  "content/xul/content/test/test_bug486990.xul": "TIMED_OUT",
  "docshell/test/navigation/test_bug13871.html": "RANDOM",
  "docshell/test/navigation/test_bug430723.html": "TIMED_OUT",
  "docshell/test/navigation/test_sessionhistory.html": "RANDOM",
  "docshell/test/test_bug344861.html": "",
  "docshell/test/test_bug94514.html": "TIMED_OUT",
  "docshell/test/test_bug413310.html": "",
  "docshell/test/test_bug598895.html": "",
  "docshell/test/test_bug637644.html": "",
  "docshell/test/test_bug668513.html": "RANDOM",
  "dom/browser-element/mochitest/test_browserElement_oop_SecurityChange.html": "TIMED_OUT, bug 766586",
+ "dom/browser-element/mochitest/test_browserElement_inproc_Iconchange.html": "bug 775227",
  "dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html": "TIMED_OUT, bug 766586",
  "dom/imptests/editing/conformancetest/test_event.html": "",
  "dom/imptests/editing/conformancetest/test_runtest.html": "",
+ "dom/imptests/editing/selecttest/test_addRange.html": "bug 775227", 
  "dom/imptests/html/tests/submission/Mozilla/test_window-onerror-parse-error.html": "",
  "dom/imptests/html/tests/submission/Mozilla/test_window-onerror-runtime-error-throw.html": "",
  "dom/imptests/html/tests/submission/Mozilla/test_window-onerror-runtime-error.html": "",
+ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneContents.html": "bug 775227", 
+ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html": "bug 775227",
+ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-deleteContents.html": "bug 775227",
+ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-extractContents.html": "bug 775227",
+ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-insertNode.html": "bug 775227",
+ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html": "bug 775227",
+ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html": "bug 775227",
+ "dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html": "bug 775227",
+
  "dom/indexedDB/test/test_third_party.html": "TIMED_OUT",
  "dom/network/tests/test_network_basics.html": "",
  "dom/settings/tests/test_settings_events.html": "",
  "dom/settings/tests/test_settings_basics.html": "",
  "dom/contacts/tests/test_contacts_basics.html": "",
  "dom/contacts/tests/test_contacts_events.html": "",
  "dom/sms/tests/test_sms_basics.html": "",
+ "dom/tests/mochitest/ajax/jquery/test_jQuery.html": "bug 775227",
  "dom/tests/mochitest/ajax/offline/test_simpleManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_updatingManifest.html": "TIMED_OUT",
  "dom/tests/mochitest/ajax/offline/test_xhtmlManifest.xhtml": "TIMED_OUT",
  "dom/tests/mochitest/ajax/prototype/test_Prototype.html": "",
  "dom/tests/mochitest/ajax/scriptaculous/test_Scriptaculous.html": "",
  "dom/tests/mochitest/browser-frame/test_browserFrame1.html": "TIMED_OUT",
  "dom/tests/mochitest/bugs/test_bug260264.html": "",
  "dom/tests/mochitest/bugs/test_bug291653.html": "TIMED_OUT",
@@ -148,16 +163,17 @@
  "dom/tests/mochitest/bugs/test_bug414291.html": "",
  "dom/tests/mochitest/bugs/test_bug427744.html": "",
  "dom/tests/mochitest/bugs/test_bug437361.html": "",
  "dom/tests/mochitest/bugs/test_bug479143.html": "",
  "dom/tests/mochitest/bugs/test_bug504862.html": "RANDOM",
  "dom/tests/mochitest/bugs/test_bug597809.html": "",
  "dom/tests/mochitest/bugs/test_bug61098.html": "",
  "dom/tests/mochitest/bugs/test_bug641552.html": "",
+ "dom/tests/mochitest/bugs/test_devicemotion_multiple_listeners.html": "bug 775227",
  "dom/tests/mochitest/bugs/test_resize_move_windows.html": "TIMED_OUT",
  "dom/tests/mochitest/bugs/test_window_bar.html": "",
  "dom/devicestorage/ipc/test_ipc.html": "",
  "dom/devicestorage/test/test_basic.html": "",
  "dom/devicestorage/test/test_dotdot.html": "",
  "dom/devicestorage/test/test_enumerate.html": "",
  "dom/devicestorage/test/test_enumerateMultipleContinue.html": "",
  "dom/devicestorage/test/test_enumerateOptions.html": "",
@@ -216,16 +232,17 @@
  "editor/libeditor/text/tests/test_bug569988.html": "TIMED_OUT",
  "editor/libeditor/text/tests/test_bug596333.html": "",
  "editor/libeditor/text/tests/test_bug600570.html": "",
  "editor/libeditor/text/tests/test_bug604532.html": "",
  "editor/libeditor/text/tests/test_bug629172.html": "",
  "editor/libeditor/text/tests/test_texteditor_keyevent_handling.html": "",
  "embedding/test/test_bug449141.html": "",
  "embedding/test/test_window_open_units.html": "",
+ "intl/uconv/tests/test_long_doc.html": "bug 775227", 
  "js/jsd/test/test_bug507448.html": "TIMED_OUT",
  "js/jsd/test/test_bug617870-callhooks.html": "TIMED_OUT",
  "layout/base/tests/test_bug332655-1.html": "",
  "layout/base/tests/test_bug603550.html": "TIMED_OUT",
  "layout/base/tests/test_bug629838.html": "",
  "layout/base/tests/test_flush_on_paint.html": "",
  "layout/base/tests/test_mozPaintCount.html": "",
  "layout/base/tests/test_reftests_with_caret.html": "",
@@ -245,17 +262,19 @@
  "layout/generic/test/test_invalidate_during_plugin_paint.html": "",
  "layout/generic/test/test_plugin_mouse_coords.html": "",
  "layout/generic": "CRASH_DUMP, RANDOM, ONLY IN CHUNK 10",
  "layout/style/test/test_animations.html": "",
  "layout/style/test/test_bug379440.html": "",
  "layout/style/test/test_compute_data_with_start_struct.html": "",
  "layout/style/test/test_inherit_computation.html": "",
  "layout/style/test/test_initial_computation.html": "",
+ "layout/style/test/test_selectors.html": "bug 775227", 
  "layout/style/test/test_transitions_per_property.html": "bug 775227",
+ "layout/style/test/test_value_cloning.html": "bug 775227", 
  "layout/style/test/test_value_computation.html": "",
  "layout/style/test/test_visited_image_loading.html": "TIMED_OUT",
  "layout/style/test/test_visited_image_loading_empty.html": "TIMED_OUT",
  "layout/style/test/test_visited_lying.html": "",
  "layout/style/test/test_visited_pref.html": "TIMED_OUT",
  "layout/style/test/test_visited_reftests.html": "TIMED_OUT",
  "parser/htmlparser/tests/mochitest/test_html5_tree_construction.html": "TIMED_OUT",
  "parser/htmlparser/tests/mochitest/test_html5_tree_construction_part2.html": "TIMED_OUT",
--- a/toolkit/components/alerts/resources/content/alert.js
+++ b/toolkit/components/alerts/resources/content/alert.js
@@ -63,35 +63,43 @@ function prefillAlertInfo()
 
 function onAlertLoad()
 {
   gSlideIncrement     = Services.prefs.getIntPref("alerts.slideIncrement");
   gSlideTime          = Services.prefs.getIntPref("alerts.slideIncrementTime");
   gOpenTime           = Services.prefs.getIntPref("alerts.totalOpenTime");
   gDisableSlideEffect = Services.prefs.getBoolPref("alerts.disableSlidingEffect");
 
+  var alertBox = document.getElementById("alertBox");
   // Make sure that the contents are fixed at the window edge facing the
   // screen's center so that the window looks like "sliding in" and not
   // like "unfolding". The default packing of "start" only works for
   // vertical-bottom and horizontal-right positions, so we change it here.
   if (gOrigin & NS_ALERT_HORIZONTAL)
   {
-    if (gOrigin & NS_ALERT_LEFT)
+    if (gOrigin & NS_ALERT_LEFT) {
       document.documentElement.pack = "end";
+      alertBox.setAttribute("origin", "left");
+    } else {
+      alertBox.setAttribute("origin", "right");
+    }
 
     // Additionally, change the orientation so the packing works as intended
     document.documentElement.orient = "horizontal";
   }
   else
   {
-    if (gOrigin & NS_ALERT_TOP)
+    if (gOrigin & NS_ALERT_TOP) {
       document.documentElement.pack = "end";
+      alertBox.setAttribute("origin", "top");
+    } else {
+      alertBox.setAttribute("origin", "bottom");
+    }
   }
 
-  var alertBox = document.getElementById("alertBox");
   alertBox.orient = (gOrigin & NS_ALERT_HORIZONTAL) ? "vertical" : "horizontal";
 
   sizeToContent();
 
   // Start with a 1px width/height, because 0 causes trouble with gtk1/2
   gCurrentSize = 1;
 
   // Determine final size
--- a/toolkit/components/osfile/Makefile.in
+++ b/toolkit/components/osfile/Makefile.in
@@ -18,15 +18,17 @@ EXTRA_PP_JS_MODULES = \
 
 ifdef ENABLE_TESTS
 DIRS += tests
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 libs::
-	$(NSINSTALL) $(srcdir)/osfile_shared.jsm $(FINAL_TARGET)/modules/osfile
+	$(NSINSTALL) $(srcdir)/osfile_shared_allthreads.jsm $(FINAL_TARGET)/modules/osfile
+	$(NSINSTALL) $(srcdir)/osfile_unix_allthreads.jsm $(FINAL_TARGET)/modules/osfile
 	$(NSINSTALL) $(srcdir)/osfile_unix_back.jsm $(FINAL_TARGET)/modules/osfile
 	$(NSINSTALL) $(srcdir)/ospath_unix_back.jsm $(FINAL_TARGET)/modules/osfile
 	$(NSINSTALL) $(srcdir)/osfile_unix_front.jsm $(FINAL_TARGET)/modules/osfile
+	$(NSINSTALL) $(srcdir)/osfile_win_allthreads.jsm $(FINAL_TARGET)/modules/osfile
 	$(NSINSTALL) $(srcdir)/ospath_win_back.jsm $(FINAL_TARGET)/modules/osfile
 	$(NSINSTALL) $(srcdir)/osfile_win_back.jsm $(FINAL_TARGET)/modules/osfile
 	$(NSINSTALL) $(srcdir)/osfile_win_front.jsm $(FINAL_TARGET)/modules/osfile
rename from toolkit/components/osfile/osfile_shared.jsm
rename to toolkit/components/osfile/osfile_shared_allthreads.jsm
--- a/toolkit/components/osfile/osfile_shared.jsm
+++ b/toolkit/components/osfile/osfile_shared_allthreads.jsm
@@ -4,17 +4,17 @@
 
 {
   if (typeof Components != "undefined") {
     // We do not wish osfile_shared.jsm to be used directly as a main thread
     // module yet. When time comes, it will be loaded by a combination of
     // a main thread front-end/worker thread implementation that makes sure
     // that we are not executing synchronous IO code in the main thread.
 
-    throw new Error("osfile_shared.jsm cannot be used from the main thread yet");
+    throw new Error("osfile_shared_allthreads.jsm cannot be used from the main thread yet");
   }
 
   (function(exports) {
      "use strict";
      /*
       * This block defines |OS.Shared.Type|. However, |OS| can exist already
       * (in particular, if this code is executed in a worker thread, it is
       * defined).
new file mode 100644
--- /dev/null
+++ b/toolkit/components/osfile/osfile_unix_allthreads.jsm
@@ -0,0 +1,126 @@
+/* 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/. */
+
+/**
+ * This module defines the thread-agnostic components of the Unix version
+ * of OS.File. It depends on the thread-agnostic cross-platform components
+ * of OS.File.
+ *
+ * It serves the following purposes:
+ * - open libc;
+ * - define OS.Unix.Error;
+ * - define a few constants and types that need to be defined on all platforms.
+ *
+ * This module can be:
+ * - opened from the main thread as a jsm module;
+ * - opened from a chrome worker through importScripts.
+ */
+
+if (typeof Components != "undefined") {
+  // Module is opened as a jsm module
+  var EXPORTED_SYMBOLS = ["OS"];
+  Components.utils.import("resource://gre/modules/ctypes.jsm");
+  Components.utils.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
+} else {
+  // File is included from a chrome worker
+  importScripts("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
+}
+
+(function(exports) {
+  "use strict";
+  if (!exports.OS || !exports.OS.Shared) {
+    throw new Error("osfile_unix_allthreads.jsm must be loaded after osfile_shared_allthreads.jsm");
+  }
+  if (exports.OS.Shared.Unix) {
+    // Avoid double inclusion
+    return;
+  }
+  exports.OS.Shared.Unix = {};
+
+  let LOG = OS.Shared.LOG.bind(OS.Shared, "Unix", "allthreads");
+
+  // Open libc
+  let libc;
+  let libc_candidates =  [ "libsystem.B.dylib",
+                           "libc.so.6",
+                           "libc.so" ];
+  for (let i = 0; i < libc_candidates.length; ++i) {
+    try {
+      libc = ctypes.open(libc_candidates[i]);
+      break;
+    } catch (x) {
+      LOG("Could not open libc "+libc_candidates[i]);
+    }
+  }
+  if (!libc) {
+    throw new Error("Could not open any libc.");
+  }
+  exports.OS.Shared.Unix.libc = libc;
+
+  // Define declareFFI
+  let declareFFI = OS.Shared.declareFFI.bind(null, libc);
+  exports.OS.Shared.Unix.declareFFI = declareFFI;
+
+  // Define Error
+  let strerror = libc.declare("strerror",
+    ctypes.default_abi,
+    /*return*/ ctypes.char.ptr,
+    /*errnum*/ ctypes.int);
+
+  /**
+   * A File-related error.
+   *
+   * To obtain a human-readable error message, use method |toString|.
+   * To determine the cause of the error, use the various |becauseX|
+   * getters. To determine the operation that failed, use field
+   * |operation|.
+   *
+   * Additionally, this implementation offers a field
+   * |unixErrno|, which holds the OS-specific error
+   * constant. If you need this level of detail, you may match the value
+   * of this field against the error constants of |OS.Constants.libc|.
+   *
+   * @param {string=} operation The operation that failed. If unspecified,
+   * the name of the calling function is taken to be the operation that
+   * failed.
+   * @param {number=} lastError The OS-specific constant detailing the
+   * reason of the error. If unspecified, this is fetched from the system
+   * status.
+   *
+   * @constructor
+   * @extends {OS.Shared.Error}
+   */
+  let OSError = function OSError(operation, errno) {
+    operation = operation || "unknown operation";
+    exports.OS.Shared.Error.call(this, operation);
+    this.unixErrno = errno || ctypes.errno;
+  };
+  OSError.prototype = new exports.OS.Shared.Error();
+  OSError.prototype.toString = function toString() {
+    return "Unix error " + this.unixErrno +
+      " during operation " + this.operation +
+      " (" + strerror(this.unixErrno).readString() + ")";
+  };
+
+  /**
+   * |true| if the error was raised because a file or directory
+   * already exists, |false| otherwise.
+   */
+  Object.defineProperty(OSError.prototype, "becauseExists", {
+    get: function becauseExists() {
+      return this.unixErrno == OS.Constants.libc.EEXISTS;
+    }
+  });
+  /**
+   * |true| if the error was raised because a file or directory
+   * does not exist, |false| otherwise.
+   */
+  Object.defineProperty(OSError.prototype, "becauseNoSuchFile", {
+    get: function becauseNoSuchFile() {
+      return this.unixErrno == OS.Constants.libc.ENOENT;
+    }
+  });
+
+  exports.OS.Shared.Unix.Error = OSError;
+})(this);
--- a/toolkit/components/osfile/osfile_unix_back.jsm
+++ b/toolkit/components/osfile/osfile_unix_back.jsm
@@ -1,82 +1,51 @@
 /* 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/. */
 
-/**
- * This file can be used in the following contexts:
- *
- *  1. included from a non-osfile worker thread using importScript
- *   (it serves to define a synchronous API for that worker thread)
- *   (bug 707679)
- *
- *  2. included from the main thread using Components.utils.import
- *   (it serves to define the asynchronous API, whose implementation
- *    resides in the worker thread)
- *   (bug 729057)
- *
- * 3. included from the osfile worker thread using importScript
- *   (it serves to define the implementation of the asynchronous API)
- *   (bug 729057)
- */
-
 {
   if (typeof Components != "undefined") {
     // We do not wish osfile_unix_back.jsm to be used directly as a main thread
     // module yet. When time comes, it will be loaded by a combination of
     // a main thread front-end/worker thread implementation that makes sure
     // that we are not executing synchronous IO code in the main thread.
 
     throw new Error("osfile_unix_back.jsm cannot be used from the main thread yet");
   }
-  importScripts("resource://gre/modules/osfile/osfile_shared.jsm");
+  importScripts("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
+  importScripts("resource://gre/modules/osfile/osfile_unix_allthreads.jsm");
   (function(exports) {
      "use strict";
      if (!exports.OS) {
        exports.OS = {};
      }
      if (!exports.OS.Unix) {
        exports.OS.Unix = {};
      }
      if (exports.OS.Unix.File) {
        return; // Avoid double-initialization
      }
      exports.OS.Unix.File = {};
 
-     let LOG = OS.Shared.LOG.bind(OS.Shared, "Unix");
-
-     // Open libc
-     let libc;
-     let libc_candidates =  [ "libsystem.B.dylib",
-                              "libc.so.6",
-                              "libc.so" ];
-     for (let i = 0; i < libc_candidates.length; ++i) {
-       try {
-         libc = ctypes.open(libc_candidates[i]);
-         break;
-       } catch (x) {
-         LOG("Could not open libc "+libc_candidates[i]);
-       }
-     }
-     if (!libc) {
-       throw new Error("Could not open any libc.");
-     }
+     let LOG = exports.OS.Shared.LOG.bind(OS.Shared, "Unix", "back");
+     let libc = exports.OS.Shared.Unix.libc;
 
      /**
       * Initialize the Unix module.
       *
       * @param {function=} declareFFI
       */
+     // FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them
      let init = function init(aDeclareFFI) {
        let declareFFI;
        if (aDeclareFFI) {
          declareFFI = aDeclareFFI.bind(null, libc);
        } else {
-         declareFFI = OS.Shared.declareFFI.bind(null, libc);
+         declareFFI = exports.OS.Shared.Unix.declareFFI;
        }
 
        // Shorthands
        let OSUnix = exports.OS.Unix;
        let UnixFile = exports.OS.Unix.File;
        if (!exports.OS.Types) {
          exports.OS.Types = {};
        }
@@ -463,21 +432,16 @@
                     /*return*/ Types.long,
                     /*fd_in*/  Types.fd,
                     /*off_in*/ Types.off_t.in_ptr,
                     /*fd_out*/ Types.fd,
                     /*off_out*/Types.off_t.in_ptr,
                     /*len*/    Types.size_t,
                     /*flags*/  Types.unsigned_int); // Linux/Android-specific
 
-       UnixFile.strerror =
-         declareFFI("strerror", ctypes.default_abi,
-                    /*return*/ Types.null_or_string,
-                    /*errnum*/ Types.int);
-
        UnixFile.symlink =
          declareFFI("symlink", ctypes.default_abi,
                     /*return*/ Types.negativeone_or_nothing,
                     /*source*/ Types.string,
                     /*dest*/   Types.string);
 
        UnixFile.truncate =
          declareFFI("truncate", ctypes.default_abi,
@@ -589,18 +553,12 @@
          let result = _pipe(_pipebuf);
          if (result == -1) {
            return result;
          }
          array[0] = ctypes.CDataFinalizer(_pipebuf[0], _close);
          array[1] = ctypes.CDataFinalizer(_pipebuf[1], _close);
          return result;
        };
-
-       // Export useful stuff for extensibility
-
-       exports.OS.Unix.libc = libc;
-       exports.OS.Unix.declareFFI = declareFFI;
-
      };
      exports.OS.Unix.File._init = init;
    })(this);
 }
--- a/toolkit/components/osfile/osfile_unix_front.jsm
+++ b/toolkit/components/osfile/osfile_unix_front.jsm
@@ -11,17 +11,16 @@
 
 {
   if (typeof Components != "undefined") {
     // We do not wish osfile_unix_front.jsm to be used directly as a main thread
     // module yet.
 
     throw new Error("osfile_unix_front.jsm cannot be used from the main thread yet");
   }
-  importScripts("resource://gre/modules/osfile/osfile_shared.jsm");
   importScripts("resource://gre/modules/osfile/osfile_unix_back.jsm");
   importScripts("resource://gre/modules/osfile/ospath_unix_back.jsm");
   (function(exports) {
      "use strict";
 
      // exports.OS.Unix is created by osfile_unix_back.jsm
      if (exports.OS.File) {
        return; // Avoid double-initialization
@@ -168,69 +167,16 @@
         * @return File.Info The information on |this| file.
         */
        stat: function stat() {
          throw_on_negative("stat", UnixFile.fstat(this.fd, gStatDataPtr));
          return new File.Info(gStatData);
        }
      };
 
-     /**
-      * A File-related error.
-      *
-      * To obtain a human-readable error message, use method |toString|.
-      * To determine the cause of the error, use the various |becauseX|
-      * getters. To determine the operation that failed, use field
-      * |operation|.
-      *
-      * Additionally, this implementation offers a field
-      * |unixErrno|, which holds the OS-specific error
-      * constant. If you need this level of detail, you may match the value
-      * of this field against the error constants of |OS.Constants.libc|.
-      *
-      * @param {string=} operation The operation that failed. If unspecified,
-      * the name of the calling function is taken to be the operation that
-      * failed.
-      * @param {number=} lastError The OS-specific constant detailing the
-      * reason of the error. If unspecified, this is fetched from the system
-      * status.
-      *
-      * @constructor
-      * @extends {OS.Shared.Error}
-      */
-     File.Error = function(operation, errno) {
-       operation = operation || "unknown operation";
-       OS.Shared.Error.call(this, operation);
-       this.unixErrno = errno || ctypes.errno;
-     };
-     File.Error.prototype = new OS.Shared.Error();
-     File.Error.prototype.toString = function toString() {
-       return "Unix error " + this.unixErrno +
-         " during operation " + this.operation +
-         " (" + UnixFile.strerror(this.unixErrno).readString() + ")";
-     };
-
-     /**
-      * |true| if the error was raised because a file or directory
-      * already exists, |false| otherwise.
-      */
-     Object.defineProperty(File.Error.prototype, "becauseExists", {
-       get: function becauseExists() {
-         return this.unixErrno == OS.Constants.libc.EEXISTS;
-       }
-     });
-     /**
-      * |true| if the error was raised because a file or directory
-      * does not exist, |false| otherwise.
-      */
-     Object.defineProperty(File.Error.prototype, "becauseNoSuchFile", {
-       get: function becauseNoSuchFile() {
-         return this.unixErrno == OS.Constants.libc.ENOENT;
-       }
-     });
 
      // Constant used to normalize options.
      const noOptions = {};
 
      // The default unix mode for opening (0600)
      const DEFAULT_UNIX_MODE = 384;
 
      /**
@@ -881,11 +827,13 @@
        return result;
      }
 
      File.POS_START = exports.OS.Constants.libc.SEEK_SET;
      File.POS_CURRENT = exports.OS.Constants.libc.SEEK_CUR;
      File.POS_END = exports.OS.Constants.libc.SEEK_END;
 
      File.Unix = exports.OS.Unix.File;
+     File.Error = exports.OS.Shared.Unix.Error;
      exports.OS.File = File;
+
    })(this);
 }
new file mode 100644
--- /dev/null
+++ b/toolkit/components/osfile/osfile_win_allthreads.jsm
@@ -0,0 +1,136 @@
+/* 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/. */
+
+/**
+ * This module defines the thread-agnostic components of the Win version
+ * of OS.File. It depends on the thread-agnostic cross-platform components
+ * of OS.File.
+ *
+ * It serves the following purposes:
+ * - open libc;
+ * - define OS.Shared.Win.Error;
+ * - define a few constants and types that need to be defined on all platforms.
+ *
+ * This module can be:
+ * - opened from the main thread as a jsm module;
+ * - opened from a chrome worker through importScripts.
+ */
+
+if (typeof Components != "undefined") {
+  // Module is opened as a jsm module
+  var EXPORTED_SYMBOLS = ["OS"];
+  Components.utils.import("resource://gre/modules/ctypes.jsm");
+  Components.utils.import("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
+} else {
+  // File is included from a chrome worker
+  importScripts("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
+}
+
+(function(exports) {
+  "use strict";
+  if (!exports.OS || !exports.OS.Shared) {
+    throw new Error("osfile_win_allthreads.jsm must be loaded after osfile_shared_allthreads.jsm");
+  }
+  if (exports.OS.Shared.Win) {
+    // Avoid double inclusion
+    return;
+  }
+  exports.OS.Shared.Win = {};
+
+  let LOG = OS.Shared.LOG.bind(OS.Shared, "Win", "allthreads");
+
+  // Open libc
+  let libc = ctypes.open("kernel32.dll");
+  if (!libc) {
+    throw new Error("Could not open kernel32.dll");
+  }
+  exports.OS.Shared.Win.libc = libc;
+
+  // Define declareFFI
+  let declareFFI = OS.Shared.declareFFI.bind(null, libc);
+  exports.OS.Shared.Win.declareFFI = declareFFI;
+
+  // Define Error
+  let FormatMessage = libc.declare("FormatMessageW", ctypes.winapi_abi,
+    /*return*/ ctypes.uint32_t,
+    /*flags*/  ctypes.uint32_t,
+    /*source*/ ctypes.voidptr_t,
+    /*msgid*/  ctypes.uint32_t,
+    /*langid*/ ctypes.uint32_t,
+    /*buf*/    ctypes.jschar.ptr,
+    /*size*/   ctypes.uint32_t,
+    /*Arguments*/ctypes.voidptr_t
+  );
+
+  /**
+   * A File-related error.
+   *
+   * To obtain a human-readable error message, use method |toString|.
+   * To determine the cause of the error, use the various |becauseX|
+   * getters. To determine the operation that failed, use field
+   * |operation|.
+   *
+   * Additionally, this implementation offers a field
+   * |winLastError|, which holds the OS-specific error
+   * constant. If you need this level of detail, you may match the value
+   * of this field against the error constants of |OS.Constants.Win|.
+   *
+   * @param {string=} operation The operation that failed. If unspecified,
+   * the name of the calling function is taken to be the operation that
+   * failed.
+   * @param {number=} lastError The OS-specific constant detailing the
+   * reason of the error. If unspecified, this is fetched from the system
+   * status.
+   *
+   * @constructor
+   * @extends {OS.Shared.Error}
+   */
+  let OSError = function OSError(operation, lastError) {
+    operation = operation || "unknown operation";
+    exports.OS.Shared.Error.call(this, operation);
+    this.winLastError = lastError || ctypes.winLastError;
+  };
+  OSError.prototype = new exports.OS.Shared.Error();
+  OSError.prototype.toString = function toString() {
+    let buf = new (ctypes.ArrayType(ctypes.jschar, 1024))();
+    let result = FormatMessage(
+      exports.OS.Constants.Win.FORMAT_MESSAGE_FROM_SYSTEM |
+      exports.OS.Constants.Win.FORMAT_MESSAGE_IGNORE_INSERTS,
+      null,
+      /* The error number */ this.winLastError,
+      /* Default language */ 0,
+      /* Output buffer*/     buf,
+      /* Minimum size of buffer */ 1024,
+      /* Format args*/       null
+    );
+    if (!result) {
+      buf = "additional error " +
+        ctypes.winLastError +
+        " while fetching system error message";
+    }
+    return "Win error " + this.winLastError + " during operation "
+      + this.operation + " (" + buf.readString() + " )";
+  };
+
+  /**
+   * |true| if the error was raised because a file or directory
+   * already exists, |false| otherwise.
+   */
+  Object.defineProperty(OSError.prototype, "becauseExists", {
+    get: function becauseExists() {
+      return this.winLastError == exports.OS.Constants.Win.ERROR_FILE_EXISTS;
+    }
+  });
+  /**
+   * |true| if the error was raised because a file or directory
+   * does not exist, |false| otherwise.
+   */
+  Object.defineProperty(OSError.prototype, "becauseNoSuchFile", {
+    get: function becauseNoSuchFile() {
+      return this.winLastError == exports.OS.Constants.Win.ERROR_FILE_NOT_FOUND;
+    }
+  });
+
+  exports.OS.Shared.Win.Error = OSError;
+})(this);
\ No newline at end of file
--- a/toolkit/components/osfile/osfile_win_back.jsm
+++ b/toolkit/components/osfile/osfile_win_back.jsm
@@ -23,49 +23,47 @@
   if (typeof Components != "undefined") {
     // We do not wish osfile_win.jsm to be used directly as a main thread
     // module yet. When time comes, it will be loaded by a combination of
     // a main thread front-end/worker thread implementation that makes sure
     // that we are not executing synchronous IO code in the main thread.
 
     throw new Error("osfile_win.jsm cannot be used from the main thread yet");
   }
-  importScripts("resource://gre/modules/osfile/osfile_shared.jsm");
+  importScripts("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
+  importScripts("resource://gre/modules/osfile/osfile_win_allthreads.jsm");
 
   (function(exports) {
      "use strict";
      if (!exports.OS) {
        exports.OS = {};
      }
      if (!exports.OS.Win) {
        exports.OS.Win = {};
      }
      if (exports.OS.Win.File) {
        return; // Avoid double-initialization
      }
      exports.OS.Win.File = {};
 
-     let LOG = OS.Shared.LOG.bind(OS.Shared, "OS.Win.File");
-
-     let libc = ctypes.open("kernel32.dll");
-     if (!libc) {
-       throw new Error("Could not open kernel32.dll");
-     }
+     let LOG = OS.Shared.LOG.bind(OS.Shared, "Win", "back");
+     let libc = exports.OS.Shared.Win.libc;
 
      /**
       * Initialize the Windows module.
       *
       * @param {function=} declareFFI
       */
+     // FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them
      let init = function init(aDeclareFFI) {
        let declareFFI;
        if (aDeclareFFI) {
          declareFFI = aDeclareFFI.bind(null, libc);
        } else {
-         declareFFI = OS.Shared.declareFFI.bind(null, libc);
+         declareFFI = exports.OS.Shared.Win.declareFFI;
        }
 
        // Shorthands
        let OSWin = exports.OS.Win;
        let WinFile = exports.OS.Win.File;
        if (!exports.OS.Types) {
          exports.OS.Types = {};
        }
@@ -322,17 +320,12 @@
          declareFFI("WriteFile", ctypes.winapi_abi,
                     /*return*/ Types.zero_or_nothing,
                     /*file*/   Types.HANDLE,
                     /*buffer*/ Types.char.in_ptr,
                     /*nbytes*/ Types.DWORD,
                     /*nbytes_wr*/Types.DWORD.out_ptr,
                     /*overlapped*/Types.void_t.inout_ptr // FIXME: Implement?
          );
-
-       // Export useful stuff for extensibility
-
-       exports.OS.Win.libc = libc;
-       exports.OS.Win.declareFFI = declareFFI;
      };
      exports.OS.Win.File._init = init;
    })(this);
 }
--- a/toolkit/components/osfile/osfile_win_front.jsm
+++ b/toolkit/components/osfile/osfile_win_front.jsm
@@ -11,17 +11,17 @@
 
 {
   if (typeof Components != "undefined") {
     // We do not wish osfile_win_front.jsm to be used directly as a main thread
     // module yet.
     throw new Error("osfile_win_front.jsm cannot be used from the main thread yet");
   }
 
-  importScripts("resource://gre/modules/osfile/osfile_shared.jsm");
+  importScripts("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
   importScripts("resource://gre/modules/osfile/osfile_win_back.jsm");
   importScripts("resource://gre/modules/osfile/ospath_win_back.jsm");
 
   (function(exports) {
      "use strict";
 
      // exports.OS.Win is created by osfile_win_back.jsm
      if (exports.OS.File) {
@@ -193,85 +193,16 @@
         */
        stat: function stat() {
          throw_on_zero("stat",
            WinFile.GetFileInformationByHandle(this.fd, gFileInfoPtr));
          return new File.Info(gFileInfo);
        }
      };
 
-     /**
-      * A File-related error.
-      *
-      * To obtain a human-readable error message, use method |toString|.
-      * To determine the cause of the error, use the various |becauseX|
-      * getters. To determine the operation that failed, use field
-      * |operation|.
-      *
-      * Additionally, this implementation offers a field
-      * |winLastError|, which holds the OS-specific error
-      * constant. If you need this level of detail, you may match the value
-      * of this field against the error constants of |OS.Constants.Win|.
-      *
-      * @param {string=} operation The operation that failed. If unspecified,
-      * the name of the calling function is taken to be the operation that
-      * failed.
-      * @param {number=} lastError The OS-specific constant detailing the
-      * reason of the error. If unspecified, this is fetched from the system
-      * status.
-      *
-      * @constructor
-      * @extends {OS.Shared.Error}
-      */
-     File.Error = function FileError(operation, lastError) {
-       operation = operation || File.Error.caller.name || "unknown operation";
-       OS.Shared.Error.call(this, operation);
-       this.winLastError = lastError || ctypes.winLastError;
-     };
-     File.Error.prototype = new OS.Shared.Error();
-     File.Error.prototype.toString = function toString() {
-         let buf = new (ctypes.ArrayType(ctypes.jschar, 1024))();
-         let result = WinFile.FormatMessage(
-           OS.Constants.Win.FORMAT_MESSAGE_FROM_SYSTEM |
-           OS.Constants.Win.FORMAT_MESSAGE_IGNORE_INSERTS,
-           null,
-           /* The error number */ this.winLastError,
-           /* Default language */ 0,
-           /* Output buffer*/     buf,
-           /* Minimum size of buffer */ 1024,
-           /* Format args*/       null
-         );
-         if (!result) {
-           buf = "additional error " +
-             ctypes.winLastError +
-             " while fetching system error message";
-         }
-         return "Win error " + this.winLastError + " during operation "
-           + this.operation + " (" + buf.readString() + " )";
-     };
-
-     /**
-      * |true| if the error was raised because a file or directory
-      * already exists, |false| otherwise.
-      */
-     Object.defineProperty(File.Error.prototype, "becauseExists", {
-       get: function becauseExists() {
-         return this.winLastError == OS.Constants.Win.ERROR_FILE_EXISTS;
-       }
-     });
-     /**
-      * |true| if the error was raised because a file or directory
-      * does not exist, |false| otherwise.
-      */
-     Object.defineProperty(File.Error.prototype, "becauseNoSuchFile", {
-       get: function becauseNoSuchFile() {
-         return this.winLastError == OS.Constants.Win.ERROR_FILE_NOT_FOUND;
-       }
-     });
-
      // Constant used to normalize options.
      const noOptions = {};
 
      // The default sharing mode for opening files: files are not
      // locked against being reopened for reading/writing or against
      // being deleted by the same process or another process.
      // This is consistent with the default Unix policy.
      const DEFAULT_SHARE = Const.FILE_SHARE_READ |
@@ -889,11 +820,14 @@
      // Constants
 
      // Constants for File.prototype.setPosition
      File.POS_START = Const.FILE_BEGIN;
      File.POS_CURRENT = Const.FILE_CURRENT;
      File.POS_END = Const.FILE_END;
 
      File.Win = exports.OS.Win.File;
+     File.Error = exports.OS.Shared.Win.Error;
      exports.OS.File = File;
+
+     exports.OS.Path = exports.OS.Win.Path;
    })(this);
 }
--- a/toolkit/components/osfile/ospath_unix_back.jsm
+++ b/toolkit/components/osfile/ospath_unix_back.jsm
@@ -9,16 +9,20 @@
  * working with native paths through a cross-platform API. Functions
  * of this module will only work with the following assumptions:
  *
  * - paths are valid;
  * - paths are defined with one of the grammars that this module can
  *   parse (see later);
  * - all path concatenations go through function |join|.
  */
+if (typeof Components != "undefined") {
+  var EXPORTED_SYMBOLS = ["OS"];
+  Components.utils.import("resource://gre/modules/osfile/osfile_unix_allthreads.jsm");
+}
 (function(exports) {
    "use strict";
    if (!exports.OS) {
      exports.OS = {};
    }
    if (!exports.OS.Unix) {
      exports.OS.Unix = {};
    }
--- a/toolkit/components/osfile/ospath_win_back.jsm
+++ b/toolkit/components/osfile/ospath_win_back.jsm
@@ -17,16 +17,20 @@
  *
  * - drivename:backslash-separated components
  * - backslash-separated components
  *
  * Additionally, |normalize| can convert a path containing slash-
  * separated components to a path containing backslash-separated
  * components.
  */
+if (typeof Components != "undefined") {
+  var EXPORTED_SYMBOLS = ["OS"];
+  Components.utils.import("resource://gre/modules/osfile/osfile_win_allthreads.jsm");
+}
 (function(exports) {
    "use strict";
    if (!exports.OS) {
      exports.OS = {};
    }
    if (!exports.OS.Win) {
      exports.OS.Win = {};
    }
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -272,48 +272,64 @@ nsAppStartup::Run(void)
     if (NS_FAILED(rv))
       return rv;
   }
 
   return mRestart ? NS_SUCCESS_RESTART_APP : NS_OK;
 }
 
 static TimeStamp gRecordedShutdownStartTime;
+static bool gAlreadyFreedShutdownTimeFileName = false;
 static char *gRecordedShutdownTimeFileName = NULL;
 
+static char *
+GetShutdownTimeFileName()
+{
+  if (gAlreadyFreedShutdownTimeFileName) {
+    return NULL;
+  }
+
+  if (!gRecordedShutdownTimeFileName) {
+    nsCOMPtr<nsIFile> mozFile;
+    NS_GetSpecialDirectory(NS_APP_PREFS_50_DIR, getter_AddRefs(mozFile));
+    if (!mozFile)
+      return NULL;
+
+    mozFile->AppendNative(NS_LITERAL_CSTRING("Telemetry.ShutdownTime.txt"));
+    nsCAutoString nativePath;
+    nsresult rv = mozFile->GetNativePath(nativePath);
+    if (!NS_SUCCEEDED(rv))
+      return NULL;
+
+    gRecordedShutdownTimeFileName = PL_strdup(nativePath.get());
+  }
+
+  return gRecordedShutdownTimeFileName;
+}
+
 static void
 RecordShutdownStartTimeStamp() {
   if (!Telemetry::CanRecord())
     return;
 
   gRecordedShutdownStartTime = TimeStamp::Now();
 
-  nsCOMPtr<nsIFile> mozFile;
-  NS_GetSpecialDirectory(NS_APP_PREFS_50_DIR, getter_AddRefs(mozFile));
-  if (!mozFile)
-    return;
-
-  mozFile->AppendNative(NS_LITERAL_CSTRING("Telemetry.ShutdownTime.txt"));
-  nsCAutoString nativePath;
-  nsresult rv = mozFile->GetNativePath(nativePath);
-  if (!NS_SUCCEEDED(rv))
-    return;
-
-  gRecordedShutdownTimeFileName = PL_strdup(nativePath.get());
+  GetShutdownTimeFileName();
 }
 
 namespace mozilla {
 void
 RecordShutdownEndTimeStamp() {
-  if (!gRecordedShutdownTimeFileName)
+  if (!gRecordedShutdownTimeFileName || gAlreadyFreedShutdownTimeFileName)
     return;
 
   nsCString name(gRecordedShutdownTimeFileName);
   PL_strfree(gRecordedShutdownTimeFileName);
   gRecordedShutdownTimeFileName = NULL;
+  gAlreadyFreedShutdownTimeFileName = true;
 
   nsCString tmpName = name;
   tmpName += ".tmp";
   FILE *f = fopen(tmpName.get(), "w");
   if (!f)
     return;
   // On a normal release build this should be called just before
   // calling _exit, but on a debug build or when the user forces a full
@@ -545,16 +561,49 @@ nsAppStartup::ExitLastWindowClosingSurvi
   --mConsiderQuitStopper;
 
   if (mRunning)
     Quit(eConsiderQuit);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsAppStartup::GetLastShutdownDuration(PRUint32 *aResult)
+{
+  if (!mCachedShutdownTime) {
+    const char *filename = GetShutdownTimeFileName();
+
+    if (!filename) {
+      *aResult = 0;
+      return NS_OK;
+    }
+
+    FILE *f = fopen(filename, "r");
+    if (!f) {
+      *aResult = 0;
+      return NS_OK;
+    }
+
+    int shutdownTime;
+    int r = fscanf(f, "%d\n", &shutdownTime);
+    if (r != 1) {
+      *aResult = 0;
+      return NS_OK;
+    }
+
+    fclose(f);
+    mLastShutdownTime = shutdownTime;
+    mCachedShutdownTime = true;
+  }
+
+  *aResult = mLastShutdownTime;
+  return NS_OK;
+}
+
 //
 // nsAppStartup->nsIAppStartup2
 //
 
 NS_IMETHODIMP
 nsAppStartup::GetShuttingDown(bool *aResult)
 {
   *aResult = mShuttingDown;
--- a/toolkit/components/startup/nsAppStartup.h
+++ b/toolkit/components/startup/nsAppStartup.h
@@ -56,16 +56,18 @@ private:
   PRInt32      mConsiderQuitStopper; // if > 0, Quit(eConsiderQuit) fails
   bool mRunning;        // Have we started the main event loop?
   bool mShuttingDown;   // Quit method reentrancy check
   bool mAttemptingQuit; // Quit(eAttemptQuit) still trying
   bool mRestart;        // Quit(eRestart)
   bool mInterrupted;    // Was startup interrupted by an interactive prompt?
   bool mIsSafeModeNecessary;       // Whether safe mode is necessary
   bool mStartupCrashTrackingEnded; // Whether startup crash tracking has already ended
+  bool mCachedShutdownTime;
+  PRUint32 mLastShutdownTime;
 
 #if defined(XP_WIN)
   //Interaction with OS-provided profiling probes
   typedef mozilla::probes::ProbeManager ProbeManager;
   typedef mozilla::probes::Probe        Probe;
   nsRefPtr<ProbeManager> mProbesManager;
   nsRefPtr<Probe> mPlacesInitCompleteProbe;
   nsRefPtr<Probe> mSessionWindowRestoredProbe;
--- a/toolkit/components/startup/public/nsIAppStartup.idl
+++ b/toolkit/components/startup/public/nsIAppStartup.idl
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsICmdLineService;
 
-[scriptable, uuid(50c4194b-61c6-4292-963f-6e1a8e11c9d3)]
+[scriptable, uuid(5016bc45-54d9-4f97-935c-df4cef4b999f)]
 interface nsIAppStartup : nsISupports
 {
     /**
      * Create the hidden window.
      */
     void createHiddenWindow();
 
     /**
@@ -38,16 +38,22 @@ interface nsIAppStartup : nsISupports
      * closed but we don't want to take this as a signal to quit the
      * app. Bracket the code where the last window could close with
      * these.
      */
     void enterLastWindowClosingSurvivalArea();
     void exitLastWindowClosingSurvivalArea();
 
     /**
+     * The amount of time, in milliseconds, that the last session took
+     * to shutdown.  Reads as 0 to indicate failure.
+     */
+    readonly attribute PRUint32 lastShutdownDuration;
+
+    /**
      * Startup Crash Detection
      *
      * Keeps track of application startup begining and success using flags to
      * determine whether the application is crashing on startup.
      * When the number of crashes crosses the acceptable threshold, safe mode
      * or other repair procedures are performed.
      */
 
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -128,16 +128,20 @@ function getSimpleMeasurements() {
   let isDebuggerAttached = debugService.isDebuggerAttached;
   gWasDebuggerAttached = gWasDebuggerAttached || isDebuggerAttached;
   ret.debuggerAttached = new Number(gWasDebuggerAttached);
 
   ret.js = Cc["@mozilla.org/js/xpc/XPConnect;1"]
            .getService(Ci.nsIJSEngineTelemetryStats)
            .telemetryValue;
 
+  let shutdownDuration = si.lastShutdownDuration;
+  if (shutdownDuration)
+    ret.shutdownDuration = shutdownDuration;
+
   return ret;
 }
 
 /**
  * Read the update channel from defaults only.  We do this to ensure that
  * the channel is tightly coupled with the application and does not apply
  * to other installations of the application that may use the same profile.
  */
--- a/toolkit/crashreporter/test/Makefile.in
+++ b/toolkit/crashreporter/test/Makefile.in
@@ -38,29 +38,31 @@ LOCAL_INCLUDES += \
   -I$(XPIDL_GEN_DIR) \
   -I$(srcdir)/../google-breakpad/src/ \
   $(NULL)
 EXTRA_DSO_LIBS += xpcom
 EXTRA_DSO_LDOPTS += $(LIBS_DIR) $(MOZ_COMPONENT_LIBS) $(XPCOM_GLUE_LDOPTS)
 
 EXTRA_JS_MODULES = CrashTestUtils.jsm
 
-include $(topsrcdir)/config/rules.mk
-
-DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY) -DNOMINMAX
-
 ifneq (mobile,$(MOZ_BUILD_APP))
 MOCHITEST_BROWSER_FILES = \
   browser/head.js \
   browser/crashreport.sjs \
   browser/browser_aboutCrashes.js \
   browser/browser_bug471404.js \
   browser/browser_aboutCrashesResubmit.js \
   $(NULL)
+endif
 
+include $(topsrcdir)/config/rules.mk
+
+DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY) -DNOMINMAX
+
+ifneq (mobile,$(MOZ_BUILD_APP))
 libs::  $(MOCHITEST_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/browser
 endif
 
 libs:: $(SHARED_LIBRARY) $(EXTRA_JS_MODULES)
 	$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/
 	$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit_ipc/
 
--- a/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
+++ b/toolkit/locales/en-US/chrome/mozapps/plugins/plugins.dtd
@@ -15,19 +15,26 @@
 <!ENTITY pluginWizard.installPluginsPage.title               "Installing Plugins">
 <!ENTITY pluginWizard.installPluginsPage.description.label   "&brandShortName; is installing plugins…">
 
 <!ENTITY pluginWizard.finalPage.description.label            "&brandShortName; finished installing the missing plugins:">
 
 <!ENTITY pluginWizard.finalPage.moreInfo.label               "Find out more about Plugins or manually find missing plugins.">
 <!ENTITY pluginWizard.finalPage.restart.label                "&brandShortName; needs to be restarted for the plugin(s) to work.">
 
+<!-- LOCALIZATION NOTE (unsupportedPlatform.pre): Mobile only. Flash (the only plugin available on mobile)
+     is not supported on some devices. Include a trailing space as needed. -->
+<!ENTITY unsupportedPlatform.pre                             "We're very sorry, but &brandShortName; can't play Flash on this device. ">
+<!-- LOCALIZATION NOTE (unsupportedPlatform.learnMore): Mobile only. This text is used to link to a SUMO page explaining why Flash is not
+     supported on this device. Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit traditions in your locale. -->
+<!ENTITY unsupportedPlatform.learnMore                       "Learn More…">
+<!-- LOCALIZATION NOTE (unsupportedPlatform.post): Mobile only. Include text here if needed for your locale. -->
+<!ENTITY unsupportedPlatform.post                            "">
+
 <!ENTITY missingPlugin                                       "A plugin is needed to display this content.">
-<!-- LOCALIZATION NOTE (unsupportedPlatform): Mobile only. Plugins are not supported on some mobile devices. -->
-<!ENTITY unsupportedPlatform                                 "Plugins are not supported on this device.">
 <!-- LOCALIZATION NOTE (tapToPlayPlugin): Mobile (used for touch interfaces) only has one type of plugin possible. -->
 <!ENTITY tapToPlayPlugin                                     "Tap here to activate plugin.">
 <!ENTITY clickToPlayPlugin                                   "Click here to activate plugin.">
 <!ENTITY clickToPlayPluginVulnerableUpdateAvailable          "Click here to activate vulnerable plugin.">
 <!ENTITY clickToPlayPluginVulnerableNoUpdate                 "Click here to activate vulnerable plugin (no update available).">
 <!ENTITY checkForUpdates                                     "Check for updates…">
 <!ENTITY disabledPlugin                                      "This plugin is disabled.">
 <!ENTITY blockedPlugin.label                                 "This plugin has been blocked for your protection.">
--- a/toolkit/mozapps/plugins/content/pluginProblem.xml
+++ b/toolkit/mozapps/plugins/content/pluginProblem.xml
@@ -1,17 +1,19 @@
 <?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <!DOCTYPE bindings [
   <!ENTITY % pluginsDTD SYSTEM "chrome://mozapps/locale/plugins/plugins.dtd">
   <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
+  <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
   %pluginsDTD;
   %globalDTD;
+  %brandDTD;
 ]>
 
 <bindings id="pluginBindings"
               xmlns="http://www.mozilla.org/xbl"
               xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
               xmlns:html="http://www.w3.org/1999/xhtml">
 <binding id="pluginProblem" inheritstyle="false">
     <resources>
@@ -19,17 +21,17 @@
         <stylesheet src="chrome://mozapps/skin/plugins/pluginProblem.css"/>
     </resources>
 
     <content>
         <xul:vbox class="mainBox" flex="1" chromedir="&locale.dir;">
             <xul:spacer flex="1"/>
             <xul:box class="icon"/>
             <html:div class="msg msgUnsupported">&missingPlugin;</html:div>
-            <html:div class="msg msgUnsupportedPlatform">&unsupportedPlatform;</html:div>
+            <html:div class="msg msgUnsupportedPlatform">&unsupportedPlatform.pre;<html:a class="unsupportedLearnMoreLink" href="" target="_blank">&unsupportedPlatform.learnMore;</html:a>&unsupportedPlatform.post;</html:div>
             <html:div class="msg msgTapToPlay">&tapToPlayPlugin;</html:div>
             <html:div class="msg msgClickToPlay">&clickToPlayPlugin;</html:div>
             <html:div class="msg msgVulnerableUpdatable">&clickToPlayPluginVulnerableUpdateAvailable;</html:div>
             <html:div class="msg msgVulnerableNoUpdate">&clickToPlayPluginVulnerableNoUpdate;</html:div>
             <html:div class="msg msgCheckForUpdates"><html:a class="checkForUpdatesLink" href="">&checkForUpdates;</html:a></html:div>
             <html:div class="msg msgDisabled">&disabledPlugin;</html:div>
             <html:div class="msg msgBlocked">&blockedPlugin.label;</html:div>
             <html:div class="msg msgCrashed"><!-- set at runtime --></html:div>
--- a/toolkit/themes/winstripe/global/alerts/alert.css
+++ b/toolkit/themes/winstripe/global/alerts/alert.css
@@ -6,31 +6,58 @@
   == Styles specific to the alerts dialog.
   ======================================================================= */
 
 @import url("chrome://global/skin/");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
 .alertBox {
-  border: 2px solid #7B969C;
+  border: 1px solid threedshadow;
   background-color: -moz-Dialog;
   min-height: 50px;
+  padding: 8px;
+}
+
+@media (-moz-windows-default-theme) {
+  .alertBox {
+    background-image: linear-gradient(to bottom, white 1px, rgba(255,255,255,0) 15px);
+  }
+}
+
+.alertBox[origin="top"] {
+  border-top: none;
+  border-bottom-left-radius: 3px;
+  border-bottom-right-radius: 3px;
+}
+
+.alertBox[origin="right"] {
+  border-right: none;
+  border-bottom-left-radius: 3px;
+  border-top-left-radius: 3px;
+}
+
+.alertBox[origin="bottom"] {
+  border-bottom: none;
+  border-top-left-radius: 3px;
+  border-top-right-radius: 3px;
+}
+
+.alertBox[origin="left"] {
+  border-left: none;
+  border-bottom-right-radius: 3px;
+  border-top-right-radius: 3px;
 }
 
 .alertBox[orient="horizontal"] > .alertImageBox {
-  -moz-margin-start: 4px;
-  -moz-margin-end: 6px;
-  min-height: 46px;
+  -moz-margin-end: 8px;
 }
 
 .alertBox[orient="vertical"] > .alertImageBox {
-  margin-top: 6px;
-  margin-bottom: 4px;
-  min-width: 46px;
+  margin-bottom: 8px;
 }
 
 .alertTitle {
   font-weight: bold;
 }
 
 #alertImage {
   max-width: 48px;
@@ -53,19 +80,11 @@ label {
   color: -moz-nativehyperlinktext;
   text-decoration: underline;
 }
 
 .alertText[clickable="true"]:hover:active {
   color: #424F63;
 }
 
-.alertBox[orient="horizontal"] > .alertTextBox {
-  -moz-padding-end: 10px;
-  padding-top: 5px;
-}
-
 .alertBox[orient="vertical"] > .alertTextBox {
-  -moz-padding-start: 5px;
-  -moz-padding-end: 5px;
-  margin-bottom: 8px;
   -moz-box-align: center;
 }
--- a/tools/profiler/platform-win32.cc
+++ b/tools/profiler/platform-win32.cc
@@ -1,13 +1,14 @@
 // Copyright (c) 2006-2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include <windows.h>
+#include <mmsystem.h>
 #include "platform.h"
 #include <process.h>
 
 
 class Sampler::PlatformData : public Malloced {
  public:
   // Get a handle to the calling thread. This is the thread that we are
   // going to profile. We need to make a copy of the handle because we are
@@ -58,21 +59,32 @@ class SamplerThread : public Thread {
   static void StopSampler() {
     instance_->Join();
     delete instance_;
     instance_ = NULL;
   }
 
   // Implement Thread::Run().
   virtual void Run() {
+
+    // By default we'll not adjust the timer resolution which tends to be around
+    // 16ms. However, if the requested interval is sufficiently low we'll try to
+    // adjust the resolution to match.
+    if (interval_ < 10)
+        ::timeBeginPeriod(interval_);
+
     while (sampler_->IsActive()) {
       if (!sampler_->IsPaused())
         SampleContext(sampler_);
       OS::Sleep(interval_);
     }
+
+    // disable any timer resolution changes we've made
+    if (interval_ < 10)
+        ::timeEndPeriod(interval_);
   }
 
   void SampleContext(Sampler* sampler) {
     HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
     if (profiled_thread == NULL)
       return;
 
     // Context used for sampling the register state of the profiled thread.
--- a/widget/android/AndroidGraphicBuffer.cpp
+++ b/widget/android/AndroidGraphicBuffer.cpp
@@ -438,33 +438,33 @@ static const char* const sAllowedBoards[
 
 bool
 AndroidGraphicBuffer::IsBlacklisted()
 {
   nsAutoString board;
   if (!AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "BOARD", board))
     return true;
 
-  const char* boardUtf8 = NS_ConvertUTF16toUTF8(board).get();
+  NS_ConvertUTF16toUTF8 boardUtf8(board);
 
   if (Preferences::GetBool("direct-texture.force.enabled", false)) {
-    LOG("allowing board '%s' due to prefs override", boardUtf8);
+    LOG("allowing board '%s' due to prefs override", boardUtf8.get());
     return false;
   }
 
   if (Preferences::GetBool("direct-texture.force.disabled", false)) {
-    LOG("disallowing board '%s' due to prefs override", boardUtf8);
+    LOG("disallowing board '%s' due to prefs override", boardUtf8.get());
     return true;
   }
 
   // FIXME: (Bug 722605) use something better than a linear search
   for (int i = 0; sAllowedBoards[i]; i++) {
     if (board.Find(sAllowedBoards[i]) >= 0) {
-      LOG("allowing board '%s' based on '%s'\n", boardUtf8, sAllowedBoards[i]);
+      LOG("allowing board '%s' based on '%s'\n", boardUtf8.get(), sAllowedBoards[i]);
       return false;
     }
   }
 
-  LOG("disallowing board: %s\n", boardUtf8);
+  LOG("disallowing board: %s\n", boardUtf8.get());
   return true;
 }
 
 } /* mozilla */
--- a/widget/android/GfxInfo.cpp
+++ b/widget/android/GfxInfo.cpp
@@ -38,22 +38,16 @@ GfxInfo::GetD2DEnabled(bool *aEnabled)
 }
 
 nsresult
 GfxInfo::GetDWriteEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
-nsresult
-GfxInfo::GetAzureEnabled(bool *aEnabled)
-{
-  return NS_ERROR_FAILURE;
-}
-
 /* readonly attribute DOMString DWriteVersion; */
 NS_IMETHODIMP
 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
 {
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute DOMString cleartypeParameters; */
--- a/widget/android/GfxInfo.h
+++ b/widget/android/GfxInfo.h
@@ -20,17 +20,16 @@ class GfxInfo : public GfxInfoBase
 {
 public:
   GfxInfo();
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
-  NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
   NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
   NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
   NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
   NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
   NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
   NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
   NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);
--- a/widget/cocoa/GfxInfo.h
+++ b/widget/cocoa/GfxInfo.h
@@ -19,17 +19,16 @@ class GfxInfo : public GfxInfoBase
 {
 public:
 
   GfxInfo();
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
-  NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
   NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
   NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
   NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
   NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
   NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
   NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
   NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);
--- a/widget/cocoa/GfxInfo.mm
+++ b/widget/cocoa/GfxInfo.mm
@@ -150,30 +150,16 @@ GfxInfo::Init()
 
 NS_IMETHODIMP
 GfxInfo::GetD2DEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-GfxInfo::GetAzureEnabled(bool *aEnabled)
-{
-  bool azure = false;
-  nsresult rv = mozilla::Preferences::GetBool("gfx.canvas.azure.enabled", &azure);
-  
-  if (NS_SUCCEEDED(rv) && azure) {
-    *aEnabled = true;
-  } else {
-    *aEnabled = false;
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 GfxInfo::GetDWriteEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute DOMString DWriteVersion; */
 NS_IMETHODIMP
 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
--- a/widget/gonk/OrientationObserver.cpp
+++ b/widget/gonk/OrientationObserver.cpp
@@ -12,16 +12,17 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #include "base/basictypes.h"
 #include "mozilla/ClearOnShutdown.h"
+#include "mozilla/StaticPtr.h"
 #include "mozilla/Hal.h"
 #include "nsIScreen.h"
 #include "nsIScreenManager.h"
 #include "OrientationObserver.h"
 #include "mozilla/HalSensor.h"
 
 using namespace mozilla;
 using namespace dom;
@@ -145,17 +146,17 @@ ConvertToDomOrientation(PRUint32 aRotati
   }
 
   *aResult = eScreenOrientation_None;
   return NS_ERROR_ILLEGAL_VALUE;
 }
 
 // Note that all operations with sOrientationSensorObserver
 // should be on the main thread.
-static nsAutoPtr<OrientationObserver> sOrientationSensorObserver;
+static StaticAutoPtr<OrientationObserver> sOrientationSensorObserver;
 
 } // Anonymous namespace
 
 OrientationObserver*
 OrientationObserver::GetInstance()
 {
   if (!sOrientationSensorObserver) {
     sOrientationSensorObserver = new OrientationObserver();
--- a/widget/gtk2/nsDeviceContextSpecG.h
+++ b/widget/gtk2/nsDeviceContextSpecG.h
@@ -6,16 +6,17 @@
 #ifndef nsDeviceContextSpecGTK_h___
 #define nsDeviceContextSpecGTK_h___
 
 #include "nsIDeviceContextSpec.h"
 #include "nsIPrintSettings.h"
 #include "nsIPrintOptions.h" 
 #include "nsCOMPtr.h"
 #include "nsString.h"
+#include "mozilla/Attributes.h"
 
 #include "nsCRT.h" /* should be <limits.h>? */
 
 #include <gtk/gtk.h>
 #include <gtk/gtkprinter.h>
 #include <gtk/gtkprintjob.h>
 
 #define NS_PORTRAIT  0
@@ -60,17 +61,17 @@ protected:
   nsCString         mSpoolName;
   nsCOMPtr<nsIFile> mSpoolFile;
 
 };
 
 //-------------------------------------------------------------------------
 // Printer Enumerator
 //-------------------------------------------------------------------------
-class nsPrinterEnumeratorGTK : public nsIPrinterEnumerator
+class nsPrinterEnumeratorGTK MOZ_FINAL : public nsIPrinterEnumerator
 {
 public:
   nsPrinterEnumeratorGTK();
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPRINTERENUMERATOR
 };
 
 #endif /* !nsDeviceContextSpecGTK_h___ */
--- a/widget/gtk2/nsDragService.cpp
+++ b/widget/gtk2/nsDragService.cpp
@@ -224,17 +224,16 @@ DispatchMotionEventCopy(gpointer aData)
 static void
 OnSourceGrabEventAfter(GtkWidget *widget, GdkEvent *event, gpointer user_data)
 {
     // If there is no longer a grab on the widget, then the drag motion is
     // over (though the data may not be fetched yet).
     if (!gtk_widget_has_grab(sGrabWidget))
         return;
 
-    GdkModifierType state;
     if (event->type == GDK_MOTION_NOTIFY) {
         if (sMotionEvent) {
             gdk_event_free(sMotionEvent);
         }
         sMotionEvent = gdk_event_copy(event);
 
         // Update the cursor position.  The last of these recorded gets used for
         // the NS_DRAGDROP_END event.
--- a/widget/gtk2/nsImageToPixbuf.h
+++ b/widget/gtk2/nsImageToPixbuf.h
@@ -2,22 +2,23 @@
 /* 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 NSIMAGETOPIXBUF_H_
 #define NSIMAGETOPIXBUF_H_
 
 #include "nsIImageToPixbuf.h"
+#include "mozilla/Attributes.h"
 
 class gfxASurface;
 class gfxPattern;
 class gfxImageSurface;
 
-class nsImageToPixbuf : public nsIImageToPixbuf {
+class nsImageToPixbuf MOZ_FINAL : public nsIImageToPixbuf {
     public:
         NS_DECL_ISUPPORTS
         NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(imgIContainer* aImage);
 
         // Friendlier version of ConvertImageToPixbuf for callers inside of
         // widget
         /**
          * The return value of all these, if not null, should be
--- a/widget/gtk2/nsNativeKeyBindings.h
+++ b/widget/gtk2/nsNativeKeyBindings.h
@@ -7,16 +7,17 @@
 #define nsNativeKeyBindings_h_
 
 // X.h defines KeyPress
 #ifdef KeyPress
 #undef KeyPress
 #endif
 
 #include "nsINativeKeyBindings.h"
+#include "mozilla/Attributes.h"
 #include <gtk/gtk.h>
 
 enum NativeKeyBindingsType {
   eKeyBindings_Input,
   eKeyBindings_TextArea
 };
 
 #define NS_NATIVEKEYBINDINGSINPUT_CID \
@@ -32,17 +33,17 @@ NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "
 NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "textarea"
 
 #define NS_NATIVEKEYBINDINGSEDITOR_CID \
 {0xf916ebfb, 0x78ef, 0x464b, {0x94, 0xd0, 0xa6, 0xf2, 0xca, 0x32, 0x00, 0xae}}
 
 #define NS_NATIVEKEYBINDINGSEDITOR_CONTRACTID \
 NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "editor"
 
-class nsNativeKeyBindings : public nsINativeKeyBindings
+class nsNativeKeyBindings MOZ_FINAL : public nsINativeKeyBindings
 {
 public:
   NS_HIDDEN_(void) Init(NativeKeyBindingsType aType);
 
   NS_DECL_ISUPPORTS
 
   // nsINativeKeyBindings
   virtual NS_HIDDEN_(bool) KeyDown(const nsNativeKeyEvent& aEvent,
--- a/widget/gtk2/nsNativeThemeGTK.cpp
+++ b/widget/gtk2/nsNativeThemeGTK.cpp
@@ -620,17 +620,16 @@ public:
       mDirection(aDirection), mGDKRect(aGDKRect), mGDKClip(aGDKClip) {}
   nsresult DrawWithGDK(GdkDrawable * drawable, gint offsetX, gint offsetY,
                        GdkRectangle * clipRects, PRUint32 numClipRects);
 private:
   GtkWidgetState mState;
   GtkThemeWidgetType mGTKWidgetType;
   gint mFlags;
   GtkTextDirection mDirection;
-  GdkWindow* mWindow;
   const GdkRectangle& mGDKRect;
   const GdkRectangle& mGDKClip;
 };
 
 nsresult
 ThemeRenderer::DrawWithGDK(GdkDrawable * drawable, gint offsetX, 
         gint offsetY, GdkRectangle * clipRects, PRUint32 numClipRects)
 {
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -131,17 +131,17 @@ struct ParamTraits<nsMouseEvent>
     WriteParam(aMsg, (PRUint8) aParam.context);
     WriteParam(aMsg, (PRUint8) aParam.exit);
     WriteParam(aMsg, aParam.clickCount);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     bool rv;
-    PRUint8 reason, context, exit;
+    PRUint8 reason = 0, context = 0, exit = 0;
     rv = ReadParam(aMsg, aIter, static_cast<nsMouseEvent_base*>(aResult)) &&
          ReadParam(aMsg, aIter, &aResult->ignoreRootScrollFrame) &&
          ReadParam(aMsg, aIter, &reason) &&
          ReadParam(aMsg, aIter, &context) &&
          ReadParam(aMsg, aIter, &exit) &&
          ReadParam(aMsg, aIter, &aResult->clickCount);
     aResult->reason = static_cast<nsMouseEvent::reasonType>(reason);
     aResult->context = static_cast<nsMouseEvent::contextType>(context);
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -11,17 +11,16 @@
 [scriptable, uuid(a67c77af-2952-4028-93ab-e7bc3b43cf81)]
 interface nsIGfxInfo : nsISupports
 {
   /*
    * These are win32-specific
    */
   readonly attribute boolean D2DEnabled;
   readonly attribute boolean DWriteEnabled;
-  readonly attribute boolean AzureEnabled;
   readonly attribute DOMString DWriteVersion;
   readonly attribute DOMString cleartypeParameters;
 
   // XXX: Switch to a list of devices, rather than explicitly numbering them. 
 
   /**
    * The name of the display adapter.
    */
--- a/widget/tests/test_bug760802.html
+++ b/widget/tests/test_bug760802.html
@@ -28,37 +28,47 @@ function getBaseWindowInterface(win) {
   return win.QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIWebNavigation)
     .QueryInterface(Ci.nsIDocShellTreeItem)
     .treeOwner
     .QueryInterface(Ci.nsIInterfaceRequestor)
     .nsIBaseWindow;
 }
 
-function shouldThrow(fun) {
+function getBaseWindowInterfaceFromDocShell(win) {
+  return win.QueryInterface(Ci.nsIInterfaceRequestor)
+    .getInterface(Ci.nsIWebNavigation)
+    .QueryInterface(Ci.nsIDocShell)
+    .QueryInterface(Ci.nsIBaseWindow);
+}
+
+function shouldThrowException(fun, exception) {
   try {
     fun.call();
     return false;
   } catch (e) {
-    return true;
+    $("display").innerHTML += "<br>OK thrown: "+e.message;
+    return (e instanceof Components.Exception &&
+            e.result === exception)
   }
 }
-function doesntThrow(fun) !shouldThrow(fun)
+function doesntThrowException(fun) !shouldThrowException(fun)
 
 
 var baseWindow = getBaseWindowInterface(window);
 var nativeHandle = baseWindow.nativeHandle;
 $("display").innerHTML = "found nativeHandle for this window: "+nativeHandle;
 
 var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
 var win = wm.getMostRecentWindow("navigator:browser");
-var docShell = win.gBrowser.docShell;
+var docShell = getBaseWindowInterfaceFromDocShell(win);
 
 ok(
-  shouldThrow(function(){docShell.getInterface(Ci.nsIBaseWindow).nativeHandle;}),
+  shouldThrowException(function(){docShell.nativeHandle;},
+              Components.results.NS_ERROR_NOT_IMPLEMENTED),
   "nativeHandle should not be implemented for nsDocShell"
 );
 
 ok(typeof(nativeHandle) === "string", "nativeHandle should be a string");
 ok(nativeHandle.match(/^0x[0-9a-f]+$/), "nativeHandle should have a memory address format");
 
 var iWin = window.document.getElementById("iframe_not_editable").contentWindow;
 is(getBaseWindowInterface(iWin).nativeHandle, nativeHandle,
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -54,36 +54,16 @@ GfxInfo::GetD2DEnabled(bool *aEnabled)
 
 nsresult
 GfxInfo::GetDWriteEnabled(bool *aEnabled)
 {
   *aEnabled = gfxWindowsPlatform::GetPlatform()->DWriteEnabled();
   return NS_OK;
 }
 
-nsresult
-GfxInfo::GetAzureEnabled(bool *aEnabled)
-{
-  *aEnabled = false;
-
-  bool d2dEnabled = 
-    gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D;
-
-  if (d2dEnabled) {
-    bool azure = false;
-    nsresult rv = mozilla::Preferences::GetBool("gfx.canvas.azure.enabled", &azure);
-
-    if (NS_SUCCEEDED(rv) && azure) {
-      *aEnabled = true;
-    }
-  }
-
-  return NS_OK;
-}
-
 /* readonly attribute DOMString DWriteVersion; */
 NS_IMETHODIMP
 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
 {
   gfxWindowsPlatform::GetDLLVersion(L"dwrite.dll", aDwriteVersion);
   return NS_OK;
 }
 
--- a/widget/windows/GfxInfo.h
+++ b/widget/windows/GfxInfo.h
@@ -17,17 +17,16 @@ class GfxInfo : public GfxInfoBase
 {
 public:
   GfxInfo();
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
-  NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
   NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
   NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
   NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
   NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
   NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
   NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
   NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);
--- a/widget/windows/TaskbarPreview.cpp
+++ b/widget/windows/TaskbarPreview.cpp
@@ -56,17 +56,17 @@ PRUint32 gInstCount = 0;
 nsresult
 GetRenderingContext(nsIDocShell *shell, gfxASurface *surface,
                     PRUint32 width, PRUint32 height) {
   nsresult rv;
   nsCOMPtr<nsIDOMCanvasRenderingContext2D> ctx = gCtx;
 
   if (!ctx) {
     // create the canvas rendering context
-    ctx = do_CreateInstance("@mozilla.org/content/2dthebes-canvas-rendering-context;1", &rv);
+    ctx = do_CreateInstance("@mozilla.org/content/canvas-rendering-context;1?id=2d", &rv);
     if (NS_FAILED(rv)) {
       NS_WARNING("Could not create nsICanvasRenderingContext2D for tab previews!");
       return rv;
     }
     gCtx = ctx;
     NS_ADDREF(gCtx);
   }
 
--- a/widget/xpwidgets/GfxInfoX11.cpp
+++ b/widget/xpwidgets/GfxInfoX11.cpp
@@ -365,22 +365,16 @@ GfxInfo::GetD2DEnabled(bool *aEnabled)
 }
 
 NS_IMETHODIMP
 GfxInfo::GetDWriteEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP
-GfxInfo::GetAzureEnabled(bool *aEnabled)
-{
-  return NS_ERROR_FAILURE;
-}
-
 /* readonly attribute DOMString DWriteVersion; */
 NS_IMETHODIMP
 GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion)
 {
   return NS_ERROR_FAILURE;
 }
 
 /* readonly attribute DOMString cleartypeParameters; */
--- a/widget/xpwidgets/GfxInfoX11.h
+++ b/widget/xpwidgets/GfxInfoX11.h
@@ -16,17 +16,16 @@ namespace widget {
 class GfxInfo : public GfxInfoBase
 {
 public:
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
-  NS_IMETHOD GetAzureEnabled(bool *aAzureEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
   NS_IMETHOD GetCleartypeParameters(nsAString & aCleartypeParams);
   NS_IMETHOD GetAdapterDescription(nsAString & aAdapterDescription);
   NS_IMETHOD GetAdapterDriver(nsAString & aAdapterDriver);
   NS_IMETHOD GetAdapterVendorID(nsAString & aAdapterVendorID);
   NS_IMETHOD GetAdapterDeviceID(nsAString & aAdapterDeviceID);
   NS_IMETHOD GetAdapterRAM(nsAString & aAdapterRAM);
   NS_IMETHOD GetAdapterDriverVersion(nsAString & aAdapterDriverVersion);
--- a/widget/xpwidgets/nsIdleService.h
+++ b/widget/xpwidgets/nsIdleService.h
@@ -60,21 +60,16 @@ private:
   /**
    * @note This is a normal pointer, part to avoid creating a cycle with the
    * idle service, part to avoid potential pointer corruption due to this class
    * being instantiated in the constructor of the service itself.
    */
   nsIIdleService* mIdleService;
 
   /**
-   * Set to true when the instantiated object has a idle observer.
-   */
-  bool mObservesIdle;
-
-  /**
    * Place to hold the timer used by this class to determine when a day has
    * passed, after that it will wait for idle time to be detected.
    */
   nsCOMPtr<nsITimer> mTimer;
 
   /**
    * Function that is called back once a day.
    */
--- a/xpcom/base/ClearOnShutdown.h
+++ b/xpcom/base/ClearOnShutdown.h
@@ -11,24 +11,28 @@
 #include "nsThreadUtils.h"
 
 /*
  * This header exports one public method in the mozilla namespace:
  *
  *   template<class SmartPtr>
  *   void ClearOnShutdown(SmartPtr *aPtr)
  *
- * This function takes a pointer to a smart pointer (i.e., nsCOMPtr<T>*,
- * nsRefPtr<T>*, or nsAutoPtr<T>*) and nulls the smart pointer on shutdown.
+ * This function takes a pointer to a smart pointer and nulls the smart pointer
+ * on shutdown.
  *
  * This is useful if you have a global smart pointer object which you don't
  * want to "leak" on shutdown.
  *
- * There is no way to undo a call to ClearOnShutdown, so you can call it only
- * on smart pointers which you know will live until the program shuts down.
+ * Although ClearOnShutdown will work with any smart pointer (i.e., nsCOMPtr,
+ * nsRefPtr, nsAutoPtr, StaticRefPtr, and StaticAutoPtr), you probably want to
+ * use it only with StaticRefPtr and StaticAutoPtr.  There is no way to undo a
+ * call to ClearOnShutdown, so you can call it only on smart pointers which you
+ * know will live until the program shuts down.  In practice, these are likely
+ * global variables, which should be Static{Ref,Auto}Ptr.
  *
  * ClearOnShutdown is currently main-thread only because we don't want to
  * accidentally free an object from a different thread than the one it was
  * created on.
  */
 
 namespace mozilla {
 namespace ClearOnShutdown_Internal {
--- a/xpcom/base/Makefile.in
+++ b/xpcom/base/Makefile.in
@@ -67,16 +67,17 @@ EXPORTS		= \
 		$(NULL)
 
 EXPORTS_NAMESPACES = mozilla
 
 EXPORTS_mozilla = \
 	FunctionTimer.h \
 	MapsMemoryReporter.h \
 	ClearOnShutdown.h \
+	StaticPtr.h \
 	AvailableMemoryTracker.h \
 	StackWalk.h \
 	VisualEventTracer.h \
 	$(NULL)
 
 ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += nsCrashOnException.cpp
 endif
--- a/xpcom/base/MapsMemoryReporter.cpp
+++ b/xpcom/base/MapsMemoryReporter.cpp
@@ -7,16 +7,17 @@
 #include "mozilla/Util.h"
 
 #include "mozilla/MapsMemoryReporter.h"
 #include "nsIMemoryReporter.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
+#include "mozilla/Attributes.h"
 #include <stdio.h>
 
 namespace mozilla {
 namespace MapsMemoryReporter {
 
 #if !defined(XP_LINUX)
 #error "This doesn't have a prayer of working if we're not on Linux."
 #endif
@@ -104,17 +105,17 @@ struct CategoriesSeen {
   bool mSeenRss;
   bool mSeenPss;
   bool mSeenSize;
   bool mSeenSwap;
 };
 
 } // anonymous namespace
 
-class MapsReporter : public nsIMemoryMultiReporter
+class MapsReporter MOZ_FINAL : public nsIMemoryMultiReporter
 {
 public: