Merge m-c to fxteam
authorWes Kocher <wkocher@mozilla.com>
Mon, 21 Oct 2013 20:52:31 -0400
changeset 166320 fee649b730fe1d7d1c59e2a2438cf86c0a8f1d65
parent 166319 f77442b1881340c7886087823bc639a532013205 (current diff)
parent 166317 177bf37a49f5b55eb00f2ce6d295fdc6b56cdb76 (diff)
child 166321 88c45f057f1e4c0699d12cb413a377b9266fd325
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fxteam
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "723401621af1bfabb671ec53ac7cafd62b700cb9", 
+    "revision": "175b7a89aa5f39aa2b2263029ab086ac1833a636", 
     "repo_path": "/integration/gaia-central"
 }
--- a/configure.in
+++ b/configure.in
@@ -217,34 +217,27 @@ if test -n "$gonkdir" ; then
         ARCH_DIR=arch-x86
         ;;
     esac
 
     case "$ANDROID_VERSION" in
     15)
         GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
         MOZ_B2G_BT=1
-        MOZ_B2G_BT_BLUEZ=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_RTSP=1
         ;;
     17|18)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         if test -d "$gonkdir/external/bluetooth/bluez"; then
-            GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
+            GONK_INCLUDES+=" -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
             MOZ_B2G_BT=1
-            MOZ_B2G_BT_BLUEZ=1
         fi
-        if test -d "$gonkdir/external/bluetooth/bluedroid"; then
-            MOZ_B2G_BT=1
-            MOZ_B2G_BT_BLUEDROID=1
-        fi
-
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         ;;
     *)
         AC_MSG_ERROR([Unsupported platform version: $ANDROID_VERSION])
         ;;
     esac
@@ -7290,18 +7283,16 @@ dnl ====================================
 MOZ_ARG_ENABLE_BOOL(b2g-bt,
 [  --enable-b2g-bt      Set compile flags necessary for compiling Bluetooth API for B2G ],
     MOZ_B2G_BT=1,
     MOZ_B2G_BT= )
 if test -n "$MOZ_B2G_BT"; then
     AC_DEFINE(MOZ_B2G_BT)
 fi
 AC_SUBST(MOZ_B2G_BT)
-AC_SUBST(MOZ_B2G_BT_BLUEZ)
-AC_SUBST(MOZ_B2G_BT_BLUEDROID)
 
 dnl ========================================================
 dnl = Enable Pico Speech Synthesis (Gonk usually)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(synth-pico,
 [  --enable-synth-pico  Set compile flags necessary for compiling Pico Web Speech API ],
     MOZ_SYNTH_PICO=1,
     MOZ_SYNTH_PICO= )
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -39,19 +39,17 @@
 #include "nsXPCOM.h"
 
 #if defined(MOZ_WIDGET_GONK)
 #include "cutils/properties.h"
 #endif
 
 #if defined(MOZ_B2G_BT)
 # if defined(MOZ_BLUETOOTH_GONK)
-#ifndef MOZ_B2G_BT_BLUEDROID
-#include "BluetoothGonkService.h"
-#endif
+#  include "BluetoothGonkService.h"
 # elif defined(MOZ_BLUETOOTH_DBUS)
 #  include "BluetoothDBusService.h"
 # else
 #  error No_suitable_backend_for_bluetooth!
 # endif
 #endif
 
 #define MOZSETTINGS_CHANGED_ID      "mozsettings-changed"
@@ -301,24 +299,20 @@ BluetoothService::Create()
 {
 #if defined(MOZ_B2G_BT)
   if (!IsMainProcess()) {
     return BluetoothServiceChildProcess::Create();
   }
 #endif
 
 #if defined(MOZ_BLUETOOTH_GONK)
-#ifndef MOZ_B2G_BT_BLUEDROID
   return new BluetoothGonkService();
-#endif
 #elif defined(MOZ_BLUETOOTH_DBUS)
-#ifdef MOZ_B2G_BT_BLUEZ
   return new BluetoothDBusService();
 #endif
-#endif
   BT_WARNING("No platform support for bluetooth!");
   return nullptr;
 }
 
 bool
 BluetoothService::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/bluetooth/BluetoothUnixSocketConnector.cpp
+++ b/dom/bluetooth/BluetoothUnixSocketConnector.cpp
@@ -22,34 +22,32 @@
  */
 
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
 
 #include <sys/socket.h>
-#ifdef MOZ_B2G_BT_BLUEZ
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/rfcomm.h>
 #include <bluetooth/sco.h>
-#endif
+
 #include "BluetoothUnixSocketConnector.h"
 #include "nsThreadUtils.h"
 
 using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 static const int RFCOMM_SO_SNDBUF = 70 * 1024;  // 70 KB send buffer
 static const int L2CAP_SO_SNDBUF = 400 * 1024;  // 400 KB send buffer
 static const int L2CAP_SO_RCVBUF = 400 * 1024;  // 400 KB receive buffer
 static const int L2CAP_MAX_MTU = 65000;
 
-#ifdef MOZ_B2G_BT_BLUEZ
 static
 int get_bdaddr(const char *str, bdaddr_t *ba)
 {
   char *d = ((char*)ba) + 5, *endp;
   for (int i = 0; i < 6; i++) {
     *d-- = strtol(str, &endp, 16);
     MOZ_ASSERT(!(*endp != ':' && i != 5));
     str = endp + 1;
@@ -59,33 +57,30 @@ int get_bdaddr(const char *str, bdaddr_t
 
 static
 void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
     const uint8_t *b = (const uint8_t *)ba;
     sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
             b[5], b[4], b[3], b[2], b[1], b[0]);
 }
 
-#endif
-
 BluetoothUnixSocketConnector::BluetoothUnixSocketConnector(
   BluetoothSocketType aType,
   int aChannel,
   bool aAuth,
   bool aEncrypt) : mType(aType)
                  , mChannel(aChannel)
                  , mAuth(aAuth)
                  , mEncrypt(aEncrypt)
 {
 }
 
 bool
 BluetoothUnixSocketConnector::SetUp(int aFd)
 {
-#ifdef MOZ_B2G_BT_BLUEZ
   int lm = 0;
   int sndbuf, rcvbuf;
 
   /* kernel does not yet support LM for SCO */
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     lm |= mAuth ? RFCOMM_LM_AUTH : 0;
     lm |= mEncrypt ? RFCOMM_LM_ENCRYPT : 0;
@@ -157,27 +152,26 @@ BluetoothUnixSocketConnector::SetUp(int 
 
       rcvbuf = L2CAP_SO_RCVBUF;
       if (setsockopt(aFd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) {
         BT_WARNING("setsockopt(SO_RCVBUF) failed, throwing");
         return false;
       }
     }
   }
-#endif
+
   return true;
 }
 
 int
 BluetoothUnixSocketConnector::Create()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   int fd = -1;
 
-#ifdef MOZ_B2G_BT_BLUEZ
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
     break;
   case BluetoothSocketType::SCO:
     fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
     break;
   case BluetoothSocketType::L2CAP:
@@ -194,27 +188,26 @@ BluetoothUnixSocketConnector::Create()
     BT_WARNING("Could not open bluetooth socket!");
     return -1;
   }
 
   if (!SetUp(fd)) {
     BT_WARNING("Could not set up socket!");
     return -1;
   }
-#endif
+
   return fd;
 }
 
 bool
 BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
                                          socklen_t& aAddrSize,
                                          sockaddr_any& aAddr,
                                          const char* aAddress)
 {
-#ifdef MOZ_B2G_BT_BLUEZ
   // Set to BDADDR_ANY, if it's not a server, we'll reset.
   bdaddr_t bd_address_obj = {{0, 0, 0, 0, 0, 0}};
 
   if (!aIsServer && aAddress && strlen(aAddress) > 0) {
     if (get_bdaddr(aAddress, &bd_address_obj)) {
       BT_WARNING("Can't get bluetooth address!");
       return false;
     }
@@ -244,35 +237,32 @@ BluetoothUnixSocketConnector::CreateAddr
     aAddrSize = sizeof(addr_sco);
     aAddr.sco.sco_family = AF_BLUETOOTH;
     memcpy(&aAddr.sco.sco_bdaddr, &bd_address_obj, sizeof(bd_address_obj));
     break;
   default:
     BT_WARNING("Socket type unknown!");
     return false;
   }
-#endif
   return true;
 }
 
 void
 BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr,
                                             nsAString& aAddrStr)
 {
-#ifdef MOZ_B2G_BT_BLUEZ
   char addr[18];
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.rc.rc_bdaddr), addr);
     break;
   case BluetoothSocketType::SCO:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.sco.sco_bdaddr), addr);
     break;
   case BluetoothSocketType::L2CAP:
   case BluetoothSocketType::EL2CAP:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.l2.l2_bdaddr), addr);
     break;
   default:
     MOZ_CRASH("Socket should be either RFCOMM or SCO!");
   }
   aAddrStr.AssignASCII(addr);
-#endif
 }
--- a/dom/bluetooth/Makefile.in
+++ b/dom/bluetooth/Makefile.in
@@ -31,24 +31,16 @@ ifdef MOZ_ENABLE_DBUS
 VPATH += $(srcdir)/linux
 LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
 CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
 CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) -DHAVE_PTHREADS
 DEFINES += -DMOZ_BLUETOOTH_DBUS
 endif
 endif
 
-ifdef MOZ_B2G_BT_BLUEZ
-DEFINES += -DMOZ_B2G_BT_BLUEZ
-endif
-
-ifdef MOZ_B2G_BT_BLUEDROID
-DEFINES += -DMOZ_B2G_BT_BLUEDROID
-endif
-
 # Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
 # subdirectory.
 LOCAL_INCLUDES += $(VPATH:%=-I%)
 
 endif # MOZ_B2G_BT
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -19,19 +19,16 @@ BEGIN_BLUETOOTH_NAMESPACE
 /**
  * BluetoothDBusService is the implementation of BluetoothService for DBus on
  * linux/android/B2G. Function comments are in BluetoothService.h
  */
 
 class BluetoothDBusService : public BluetoothService
 {
 public:
-  BluetoothDBusService();
-  ~BluetoothDBusService();
-
   bool IsReady();
 
   virtual nsresult StartInternal() MOZ_OVERRIDE;
 
   virtual nsresult StopInternal() MOZ_OVERRIDE;
 
   virtual bool IsEnabledInternal() MOZ_OVERRIDE;
 
@@ -166,16 +163,21 @@ public:
 
   virtual nsresult
   SendSinkMessage(const nsAString& aDeviceAddresses,
                   const nsAString& aMessage) MOZ_OVERRIDE;
 
   virtual nsresult
   SendInputMessage(const nsAString& aDeviceAddresses,
                    const nsAString& aMessage) MOZ_OVERRIDE;
+
+protected:
+  BluetoothDBusService();
+  ~BluetoothDBusService();
+
 private:
   /**
    * For DBus Control method of "UpdateNotification", event id should be
    * specified as following:
    * (Please see specification of AVRCP 1.3, Table 5.28 for more details.)
    */
   enum ControlEventId {
     EVENT_PLAYBACK_STATUS_CHANGED            = 0x01,
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -47,17 +47,17 @@ if CONFIG['MOZ_B2G_BT']:
         'BluetoothProfileController.cpp'
     ]
 
     if CONFIG['MOZ_B2G_RIL']:
         CPP_SOURCES += [
             'BluetoothRilListener.cpp',
         ]
 
-    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_BT_BLUEZ']:
+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
         CPP_SOURCES += [
             'linux/BluetoothDBusService.cpp',
             'gonk/BluetoothGonkService.cpp',
         ]
     else:
         if CONFIG['MOZ_ENABLE_DBUS']:
             CPP_SOURCES += [
                 'linux/BluetoothDBusService.cpp',
--- a/dom/system/gonk/AutoMounter.cpp
+++ b/dom/system/gonk/AutoMounter.cpp
@@ -311,21 +311,47 @@ AutoMounterResponseCallback::ResponseRec
       aCommand->CmdStr(), ResponseCode(), ResponseStr().get());
 
   if (++mErrorCount < kMaxErrorCount) {
     DBG("Calling UpdateState due to VolumeResponseCallback::OnError");
     sAutoMounter->UpdateState();
   }
 }
 
+class AutoBool {
+public:
+    explicit AutoBool(bool &aBool) : mBool(aBool) {
+      mBool = true;
+    }
+
+    ~AutoBool() {
+      mBool = false;
+    }
+
+private:
+    bool &mBool;
+};
+
 /***************************************************************************/
 
 void
 AutoMounter::UpdateState()
 {
+  static bool inUpdateState = false;
+  if (inUpdateState) {
+    // When UpdateState calls SetISharing, this causes a volume state
+    // change to occur, which would normally cause UpdateState to be called
+    // again. We want the volume state change to go out (so that device
+    // storage will see the change in sharing state), but since we're
+    // already in UpdateState we just want to prevent recursion from screwing
+    // things up.
+    return;
+  }
+  AutoBool inUpdateStateDetector(inUpdateState);
+
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
 
   // If the following preconditions are met:
   //    - UMS is available (i.e. compiled into the kernel)
   //    - UMS is enabled
   //    - AutoMounter is enabled
   //    - USB cable is plugged in
   //  then we will try to unmount and share
@@ -374,16 +400,17 @@ AutoMounter::UpdateState()
     }
   }
 
   bool tryToShare = (umsAvail && umsEnabled && enabled && usbCablePluggedIn);
   LOG("UpdateState: umsAvail:%d umsEnabled:%d mode:%d usbCablePluggedIn:%d tryToShare:%d",
       umsAvail, umsEnabled, mMode, usbCablePluggedIn, tryToShare);
 
   bool filesOpen = false;
+  static unsigned filesOpenDelayCount = 0;
   VolumeArray::index_type volIndex;
   VolumeArray::size_type  numVolumes = VolumeManager::NumVolumes();
   for (volIndex = 0; volIndex < numVolumes; volIndex++) {
     RefPtr<Volume>  vol = VolumeManager::GetVolume(volIndex);
     Volume::STATE   volState = vol->State();
 
     if (vol->State() == nsIVolume::STATE_MOUNTED) {
       LOG("UpdateState: Volume %s is %s and %s @ %s gen %d locked %d sharing %c",
@@ -408,16 +435,22 @@ AutoMounter::UpdateState()
           if (vol->IsMountLocked()) {
             // The volume is currently locked, so leave it in the mounted
             // state.
             LOGW("UpdateState: Mounted volume %s is locked, not sharing",
                  vol->NameStr());
             break;
           }
 
+          // Mark the volume as if we've started sharing. This will cause
+          // apps which watch device storage notifications to see the volume
+          // go into the shared state, and prompt them to close any open files
+          // that they might have.
+          vol->SetIsSharing(true);
+
           // Check to see if there are any open files on the volume and
           // don't initiate the unmount while there are open files.
           OpenFileFinder::Info fileInfo;
           OpenFileFinder fileFinder(vol->MountPoint());
           if (fileFinder.First(&fileInfo)) {
             LOGW("The following files are open under '%s'",
                  vol->MountPoint().get());
             do {
@@ -426,33 +459,43 @@ AutoMounter::UpdateState()
                    fileInfo.mFileName.get(),
                    fileInfo.mAppName.get(),
                    fileInfo.mComm.get(),
                    fileInfo.mExe.get());
             } while (fileFinder.Next(&fileInfo));
             LOGW("UpdateState: Mounted volume %s has open files, not sharing",
                  vol->NameStr());
 
-            // Check again in 5 seconds to see if the files are closed. Since
-            // we're trying to share the volume, this implies that we're
+            // Check again in a few seconds to see if the files are closed.
+            // Since we're trying to share the volume, this implies that we're
             // plugged into the PC via USB and this in turn implies that the
             // battery is charging, so we don't need to be too concerned about
             // wasting battery here.
+            //
+            // If we just detected that there were files open, then we use
+            // a short timer. We will have told the apps that we're trying
+            // trying to share, and they'll be closing their files. This makes
+            // the sharing more responsive. If after a few seconds, the apps
+            // haven't closed their files, then we back off.
+
+            int delay = 1000;
+            if (filesOpenDelayCount > 10) {
+              delay = 5000;
+            }
             MessageLoopForIO::current()->
               PostDelayedTask(FROM_HERE,
                               NewRunnableMethod(this, &AutoMounter::UpdateState),
-                              5000);
+                              delay);
             filesOpen = true;
             break;
           }
 
           // Volume is mounted, we need to unmount before
           // we can share.
           LOG("UpdateState: Unmounting %s", vol->NameStr());
-          vol->SetIsSharing(true);
           vol->StartUnmount(mResponseCallback);
           return; // UpdateState will be called again when the Unmount command completes
         }
         case nsIVolume::STATE_IDLE: {
           // Volume is unmounted. We can go ahead and share.
           LOG("UpdateState: Sharing %s", vol->NameStr());
           vol->StartShare(mResponseCallback);
           return; // UpdateState will be called again when the Share command completes
@@ -483,18 +526,20 @@ AutoMounter::UpdateState()
           break;
         }
       }
     }
   }
 
   int32_t status = AUTOMOUNTER_STATUS_DISABLED;
   if (filesOpen) {
+    filesOpenDelayCount++;
     status = AUTOMOUNTER_STATUS_FILES_OPEN;
   } else if (enabled) {
+    filesOpenDelayCount = 0;
     status = AUTOMOUNTER_STATUS_ENABLED;
   }
   SetAutoMounterStatus(status);
 }
 
 /***************************************************************************/
 
 static void
--- a/dom/system/gonk/Volume.cpp
+++ b/dom/system/gonk/Volume.cpp
@@ -63,17 +63,25 @@ Volume::Volume(const nsCSubstring& aName
     mIsSharing(false)
 {
   DBG("Volume %s: created", NameStr());
 }
 
 void
 Volume::SetIsSharing(bool aIsSharing)
 {
+  if (aIsSharing == mIsSharing) {
+    return;
+  }
   mIsSharing = aIsSharing;
+  LOG("Volume %s: IsSharing set to %d state %s",
+      NameStr(), (int)mIsSharing, StateStr(mState));
+  if (mIsSharing) {
+    mEventObserverList.Broadcast(this);
+  }
 }
 
 void
 Volume::SetMediaPresent(bool aMediaPresent)
 {
   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
 
--- a/dom/system/gonk/nsVolume.cpp
+++ b/dom/system/gonk/nsVolume.cpp
@@ -90,16 +90,22 @@ bool nsVolume::Equals(nsIVolume* aVolume
   }
 
   bool isFake;
   aVolume->GetIsFake(&isFake);
   if (mIsFake != isFake) {
     return false;
   }
 
+  bool isSharing;
+  aVolume->GetIsSharing(&isSharing);
+  if (mIsSharing != isSharing) {
+    return false;
+  }
+
   return true;
 }
 
 NS_IMETHODIMP nsVolume::GetIsMediaPresent(bool *aIsMediaPresent)
 {
   *aIsMediaPresent = mIsMediaPresent;
   return NS_OK;
 }
--- a/dom/system/gonk/nsVolume.h
+++ b/dom/system/gonk/nsVolume.h
@@ -66,28 +66,29 @@ public:
   bool IsMountLocked() const          { return mMountLocked; }
 
   const nsString& MountPoint() const  { return mMountPoint; }
   nsCString MountPointStr() const     { return NS_LossyConvertUTF16toASCII(mMountPoint); }
 
   int32_t State() const               { return mState; }
   const char* StateStr() const        { return NS_VolumeStateStr(mState); }
 
+  bool IsFake() const                 { return mIsFake; }
+  bool IsMediaPresent() const         { return mIsMediaPresent; }
+  bool IsSharing() const              { return mIsSharing; }
+
   typedef nsTArray<nsRefPtr<nsVolume> > Array;
 
 private:
   ~nsVolume() {}
 
   friend class nsVolumeService; // Calls the following XxxMountLock functions
   void UpdateMountLock(const nsAString& aMountLockState);
   void UpdateMountLock(bool aMountLocked);
 
-  bool IsFake() const                 { return mIsFake; }
-  bool IsMediaPresent() const         { return mIsMediaPresent; }
-  bool IsSharing() const              { return mIsSharing; }
   void SetIsFake(bool aIsFake);
   void SetState(int32_t aState);
 
   nsString mName;
   nsString mMountPoint;
   int32_t  mState;
   int32_t  mMountGeneration;
   bool     mMountLocked;
--- a/dom/system/gonk/nsVolumeService.cpp
+++ b/dom/system/gonk/nsVolumeService.cpp
@@ -449,15 +449,15 @@ private:
 
 void
 nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
 {
   DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d "
       "media %d sharing %d",
       aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
       aVolume->MountGeneration(), (int)aVolume->IsMountLocked(),
-      (int)aVolume->IsMediaPresent(), (int)aVolume->IsSharing());
+      (int)aVolume->MediaPresent(), (int)aVolume->IsSharing());
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
   NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
 }
 
 } // namespace system
 } // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -302,31 +302,49 @@ ShadowLayerForwarder::RepositionChild(Sh
   } else {
     MOZ_LAYERS_LOG(("[LayersForwarder] OpRaiseToTopChild container=%p child=%p",
                    aContainer->AsLayer(), aChild->AsLayer()));
     mTxn->AddEdit(OpRaiseToTopChild(nullptr, Shadow(aContainer),
                                     nullptr, Shadow(aChild)));
   }
 }
 
+
+#ifdef DEBUG
+void
+ShadowLayerForwarder::CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const
+{
+  if (!aDescriptor) {
+    return;
+  }
+
+  if (aDescriptor->type() == SurfaceDescriptor::TShmem) {
+    const mozilla::ipc::Shmem& shmem = aDescriptor->get_Shmem();
+    shmem.AssertInvariants();
+    MOZ_ASSERT(mShadowManager->IsTrackingSharedMemory(shmem.mSegment));
+  }
+}
+#endif
+
 void
 ShadowLayerForwarder::PaintedTiledLayerBuffer(CompositableClient* aCompositable,
                                               const SurfaceDescriptorTiles& aTileLayerDescriptor)
 {
   mTxn->AddNoSwapPaint(OpPaintTiledLayerBuffer(nullptr, aCompositable->GetIPDLActor(),
                                                aTileLayerDescriptor));
 }
 
 void
 ShadowLayerForwarder::UpdateTexture(CompositableClient* aCompositable,
                                     TextureIdentifier aTextureId,
                                     SurfaceDescriptor* aDescriptor)
 {
   if (aDescriptor->type() != SurfaceDescriptor::T__None &&
       aDescriptor->type() != SurfaceDescriptor::Tnull_t) {
+    CheckSurfaceDescriptor(aDescriptor);
     MOZ_ASSERT(aCompositable);
     MOZ_ASSERT(aCompositable->GetIPDLActor());
     mTxn->AddPaint(OpPaintTexture(nullptr, aCompositable->GetIPDLActor(), 1,
                                   SurfaceDescriptor(*aDescriptor)));
     *aDescriptor = SurfaceDescriptor();
   } else {
     NS_WARNING("Trying to send a null SurfaceDescriptor.");
   }
@@ -334,16 +352,17 @@ ShadowLayerForwarder::UpdateTexture(Comp
 
 void
 ShadowLayerForwarder::UpdateTextureNoSwap(CompositableClient* aCompositable,
                                           TextureIdentifier aTextureId,
                                           SurfaceDescriptor* aDescriptor)
 {
   if (aDescriptor->type() != SurfaceDescriptor::T__None &&
       aDescriptor->type() != SurfaceDescriptor::Tnull_t) {
+    CheckSurfaceDescriptor(aDescriptor);
     MOZ_ASSERT(aCompositable);
     MOZ_ASSERT(aCompositable->GetIPDLActor());
     mTxn->AddNoSwapPaint(OpPaintTexture(nullptr, aCompositable->GetIPDLActor(), 1,
                                         SurfaceDescriptor(*aDescriptor)));
     *aDescriptor = SurfaceDescriptor();
   } else {
     NS_WARNING("Trying to send a null SurfaceDescriptor.");
   }
@@ -364,16 +383,17 @@ ShadowLayerForwarder::UpdateTextureRegio
 void
 ShadowLayerForwarder::UpdateTextureIncremental(CompositableClient* aCompositable,
                                                TextureIdentifier aTextureId,
                                                SurfaceDescriptor& aDescriptor,
                                                const nsIntRegion& aUpdatedRegion,
                                                const nsIntRect& aBufferRect,
                                                const nsIntPoint& aBufferRotation)
 {
+  CheckSurfaceDescriptor(&aDescriptor);
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   mTxn->AddNoSwapPaint(OpPaintTextureIncremental(nullptr, aCompositable->GetIPDLActor(),
                                                  aTextureId,
                                                  aDescriptor,
                                                  aUpdatedRegion,
                                                  aBufferRect,
                                                  aBufferRotation));
@@ -391,16 +411,19 @@ bool
 ShadowLayerForwarder::AddTexture(CompositableClient* aCompositable,
                                  TextureClient* aTexture)
 {
   SurfaceDescriptor descriptor;
   if (!aTexture->ToSurfaceDescriptor(descriptor)) {
     NS_WARNING("Failed to serialize a TextureClient");
     return false;
   }
+  CheckSurfaceDescriptor(&descriptor);
+  MOZ_ASSERT(aCompositable);
+  MOZ_ASSERT(aCompositable->GetIPDLActor());
   MOZ_ASSERT(aTexture->GetFlags() != 0);
   mTxn->AddEdit(OpAddTexture(nullptr, aCompositable->GetIPDLActor(),
                              aTexture->GetID(),
                              descriptor,
                              aTexture->GetFlags()));
   return true;
 }
 
@@ -847,16 +870,19 @@ ShadowLayerForwarder::Connect(Compositab
 }
 
 void
 ShadowLayerForwarder::CreatedSingleBuffer(CompositableClient* aCompositable,
                                           const SurfaceDescriptor& aDescriptor,
                                           const TextureInfo& aTextureInfo,
                                           const SurfaceDescriptor* aDescriptorOnWhite)
 {
+  CheckSurfaceDescriptor(&aDescriptor);
+  CheckSurfaceDescriptor(aDescriptorOnWhite);
+
   MOZ_ASSERT(aDescriptor.type() != SurfaceDescriptor::T__None &&
              aDescriptor.type() != SurfaceDescriptor::Tnull_t);
   mTxn->AddEdit(OpCreatedTexture(nullptr, aCompositable->GetIPDLActor(),
                                  TextureFront,
                                  aDescriptor,
                                  aTextureInfo));
   if (aDescriptorOnWhite) {
     mTxn->AddEdit(OpCreatedTexture(nullptr, aCompositable->GetIPDLActor(),
@@ -878,16 +904,20 @@ ShadowLayerForwarder::CreatedIncremental
 void
 ShadowLayerForwarder::CreatedDoubleBuffer(CompositableClient* aCompositable,
                                           const SurfaceDescriptor& aFrontDescriptor,
                                           const SurfaceDescriptor& aBackDescriptor,
                                           const TextureInfo& aTextureInfo,
                                           const SurfaceDescriptor* aFrontDescriptorOnWhite,
                                           const SurfaceDescriptor* aBackDescriptorOnWhite)
 {
+  CheckSurfaceDescriptor(&aFrontDescriptor);
+  CheckSurfaceDescriptor(&aBackDescriptor);
+  CheckSurfaceDescriptor(aFrontDescriptorOnWhite);
+  CheckSurfaceDescriptor(aBackDescriptorOnWhite);
   MOZ_ASSERT(aFrontDescriptor.type() != SurfaceDescriptor::T__None &&
              aBackDescriptor.type() != SurfaceDescriptor::T__None &&
              aFrontDescriptor.type() != SurfaceDescriptor::Tnull_t &&
              aBackDescriptor.type() != SurfaceDescriptor::Tnull_t);
   mTxn->AddEdit(OpCreatedTexture(nullptr, aCompositable->GetIPDLActor(),
                                  TextureFront,
                                  aFrontDescriptor,
                                  aTextureInfo));
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -408,16 +408,22 @@ public:
   static void PlatformSyncBeforeUpdate();
 
   static already_AddRefed<gfxASurface>
   OpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aSurface);
 
 protected:
   ShadowLayerForwarder();
 
+#ifdef DEBUG
+  void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const;
+#else
+  void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const {}
+#endif
+
   PLayerTransactionChild* mShadowManager;
 
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   // from ISurfaceAllocator
   virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
                                                   uint32_t aFormat,
                                                   uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
--- a/ipc/glue/Shmem.h
+++ b/ipc/glue/Shmem.h
@@ -49,21 +49,29 @@
  * If parent code wants to give access rights to the Shmem to the
  * child, it does so by sending its |Shmem| to the child, in an IPDL
  * message.  The parent's |Shmem| then "dies", i.e. becomes
  * inaccessible.  This process could be compared to passing a
  * "shmem-access baton" between parent and child.
  */
 
 namespace mozilla {
+namespace layers {
+class ShadowLayerForwarder;
+}
+
 namespace ipc {
 
 class Shmem MOZ_FINAL
 {
   friend struct IPC::ParamTraits<mozilla::ipc::Shmem>;
+#ifdef DEBUG
+  // For ShadowLayerForwarder::CheckSurfaceDescriptor
+  friend class mozilla::layers::ShadowLayerForwarder;
+#endif
 
 public:
   typedef int32_t id_t;
   // Low-level wrapper around platform shmem primitives.
   typedef mozilla::ipc::SharedMemory SharedMemory;
   typedef SharedMemory::SharedMemoryType SharedMemoryType;
   struct IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead {};
 
--- a/ipc/moz.build
+++ b/ipc/moz.build
@@ -9,17 +9,17 @@ DIRS += [
     'glue',
     'ipdl',
     'testshell',
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     DIRS += ['ril']
 
-if CONFIG['MOZ_B2G_BT_BLUEZ']:
+if CONFIG['MOZ_B2G_BT']:
     DIRS += ['dbus']
 
 if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT']:
     DIRS += ['unixsocket', 'keystore']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['netd']
 
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_ipc_UnixSocket_h
 #define mozilla_ipc_UnixSocket_h
 
 
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
 #include <netinet/in.h>
-#ifdef MOZ_B2G_BT_BLUEZ
+#ifdef MOZ_B2G_BT
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/sco.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/rfcomm.h>
 #endif
 #include <stdlib.h>
 #include "nsString.h"
 #include "nsAutoPtr.h"
@@ -26,17 +26,17 @@
 namespace mozilla {
 namespace ipc {
 
 union sockaddr_any {
   sockaddr_storage storage; // address-family only
   sockaddr_un un;
   sockaddr_in in;
   sockaddr_in6 in6;
-#ifdef MOZ_B2G_BT_BLUEZ
+#ifdef MOZ_B2G_BT
   sockaddr_sco sco;
   sockaddr_rc rc;
   sockaddr_l2 l2;
 #endif
   // ... others
 };
 
 class UnixSocketRawData
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2618,16 +2618,32 @@ EmitSwitch(ExclusiveContext *cx, Bytecod
     if (pn->pn_right->isKind(PNK_LEXICALSCOPE))
         EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, blockObjCount);
 #endif
 
     return true;
 }
 
 bool
+BytecodeEmitter::isRunOnceLambda()
+{
+    // The run once lambda flags set by the parser are approximate, and we look
+    // at properties of the function itself before deciding to emit a function
+    // as a run once lambda.
+
+    if (!(parent && parent->emittingRunOnceLambda) && !lazyRunOnceLambda)
+        return false;
+
+    FunctionBox *funbox = sc->asFunctionBox();
+    return !funbox->argumentsHasLocalBinding() &&
+           !funbox->isGenerator() &&
+           !funbox->function()->name();
+}
+
+bool
 frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *body)
 {
     /*
      * The decompiler has assumptions about what may occur immediately after
      * script->main (e.g., in the case of destructuring params). Thus, put the
      * following ops into the range [script->code, script->main). Note:
      * execution starts from script->code, so this has no semantic effect.
      */
@@ -2662,21 +2678,17 @@ frontend::EmitFunctionScript(ExclusiveCo
         bce->switchToMain();
     }
 
     /*
      * Emit a prologue for run-once scripts which will deoptimize JIT code if
      * the script ends up running multiple times via foo.caller related
      * shenanigans.
      */
-    bool runOnce =
-        bce->isRunOnceLambda() &&
-        !funbox->argumentsHasLocalBinding() &&
-        !funbox->isGenerator() &&
-        !funbox->function()->name();
+    bool runOnce = bce->isRunOnceLambda();
     if (runOnce) {
         bce->switchToProlog();
         if (Emit1(cx, bce, JSOP_RUNONCE) < 0)
             return false;
         bce->switchToMain();
     }
 
     if (!EmitTree(cx, bce, body))
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -122,19 +122,17 @@ struct BytecodeEmitter
 
     bool            emittingForInit:1;  /* true while emitting init expr of for; exclude 'in' */
 
     bool            emittingRunOnceLambda:1; /* true while emitting a lambda which is only
                                                 expected to run once. */
     bool            lazyRunOnceLambda:1; /* true while lazily emitting a script for
                                           * a lambda which is only expected to run once. */
 
-    bool isRunOnceLambda() {
-        return (parent && parent->emittingRunOnceLambda) || lazyRunOnceLambda;
-    }
+    bool isRunOnceLambda();
 
     bool            insideEval:1;       /* True if compiling an eval-expression or a function
                                            nested inside an eval. */
 
     const bool      hasGlobalScope:1;   /* frontend::CompileScript's scope chain is the
                                            global object */
 
     enum EmitterMode {
--- a/js/src/jit/IonFrames.cpp
+++ b/js/src/jit/IonFrames.cpp
@@ -1244,36 +1244,43 @@ SnapshotIterator::slotReadable(const Slo
           return hasLocation(slot.value());
 #endif
 
       default:
         return true;
     }
 }
 
+typedef union {
+    double d;
+    float f;
+} PunDoubleFloat;
+
 Value
 SnapshotIterator::slotValue(const Slot &slot)
 {
     switch (slot.mode()) {
       case SnapshotReader::DOUBLE_REG:
         return DoubleValue(machine_.read(slot.floatReg()));
 
       case SnapshotReader::FLOAT32_REG:
       {
-        double asDouble = machine_.read(slot.floatReg());
+        PunDoubleFloat pdf;
+        pdf.d = machine_.read(slot.floatReg());
         // The register contains the encoding of a float32. We just read
         // the bits without making any conversion.
-        float asFloat = *(float*) &asDouble;
+        float asFloat = pdf.f;
         return DoubleValue(asFloat);
       }
 
       case SnapshotReader::FLOAT32_STACK:
       {
-        double asDouble = ReadFrameDoubleSlot(fp_, slot.stackSlot());
-        float asFloat = *(float*) &asDouble; // no conversion, see comment above.
+        PunDoubleFloat pdf;
+        pdf.d = ReadFrameDoubleSlot(fp_, slot.stackSlot());
+        float asFloat = pdf.f; // no conversion, see comment above.
         return DoubleValue(asFloat);
       }
 
       case SnapshotReader::TYPED_REG:
         return FromTypedPayload(slot.knownType(), machine_.read(slot.reg()));
 
       case SnapshotReader::TYPED_STACK:
       {
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -76,16 +76,22 @@ js::intrinsic_IsCallable(JSContext *cx, 
 
 bool
 js::intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args.length() >= 1);
     uint32_t errorNumber = args[0].toInt32();
 
+#ifdef DEBUG
+    const JSErrorFormatString *efs =
+        js_GetLocalizedErrorMessage(cx, NULL, NULL, errorNumber);
+    JS_ASSERT(efs->argCount == args.length() - 1);
+#endif
+
     char *errorArgs[3] = {nullptr, nullptr, nullptr};
     for (unsigned i = 1; i < 4 && i < args.length(); i++) {
         RootedValue val(cx, args[i]);
         if (val.isInt32()) {
             JSString *str = ToString<CanGC>(cx, val);
             if (!str)
                 return false;
             errorArgs[i - 1] = JS_EncodeString(cx, str);
--- a/layout/svg/nsSVGGlyphFrame.cpp
+++ b/layout/svg/nsSVGGlyphFrame.cpp
@@ -1070,93 +1070,16 @@ nsSVGGlyphFrame::SetupContextPaint(gfxCo
     return false;
   }
 
   aContext->SetPattern(pattern);
   return true;
 }
 
 //----------------------------------------------------------------------
-// SVGTextContextPaint methods:
-
-already_AddRefed<gfxPattern>
-mozilla::SVGTextContextPaint::GetFillPattern(float aOpacity,
-                                            const gfxMatrix& aCTM)
-{
-  return mFillPaint.GetPattern(aOpacity, &nsStyleSVG::mFill, aCTM);
-}
-
-already_AddRefed<gfxPattern>
-mozilla::SVGTextContextPaint::GetStrokePattern(float aOpacity,
-                                              const gfxMatrix& aCTM)
-{
-  return mStrokePaint.GetPattern(aOpacity, &nsStyleSVG::mStroke, aCTM);
-}
-
-already_AddRefed<gfxPattern>
-mozilla::SVGTextContextPaint::Paint::GetPattern(float aOpacity,
-                                               nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
-                                               const gfxMatrix& aCTM)
-{
-  nsRefPtr<gfxPattern> pattern;
-  if (mPatternCache.Get(aOpacity, getter_AddRefs(pattern))) {
-    // Set the pattern matrix just in case it was messed with by a previous
-    // caller. We should get the same matrix each time a pattern is constructed
-    // so this should be fine.
-    pattern->SetMatrix(aCTM * mPatternMatrix);
-    return pattern.forget();
-  }
-
-  switch (mPaintType) {
-  case eStyleSVGPaintType_None:
-    pattern = new gfxPattern(gfxRGBA(0.0f, 0.0f, 0.0f, 0.0f));
-    mPatternMatrix = gfxMatrix();
-    break;
-  case eStyleSVGPaintType_Color:
-    pattern = new gfxPattern(gfxRGBA(NS_GET_R(mPaintDefinition.mColor) / 255.0,
-                                     NS_GET_G(mPaintDefinition.mColor) / 255.0,
-                                     NS_GET_B(mPaintDefinition.mColor) / 255.0,
-                                     NS_GET_A(mPaintDefinition.mColor) / 255.0 * aOpacity));
-    mPatternMatrix = gfxMatrix();
-    break;
-  case eStyleSVGPaintType_Server:
-    pattern = mPaintDefinition.mPaintServerFrame->GetPaintServerPattern(mFrame,
-                                                                        mContextMatrix,
-                                                                        aFillOrStroke,
-                                                                        aOpacity);
-    {
-      // m maps original-user-space to pattern space
-      gfxMatrix m = pattern->GetMatrix();
-      gfxMatrix deviceToOriginalUserSpace = mContextMatrix;
-      deviceToOriginalUserSpace.Invert();
-      // mPatternMatrix maps device space to pattern space via original user space
-      mPatternMatrix = deviceToOriginalUserSpace * m;
-    }
-    pattern->SetMatrix(aCTM * mPatternMatrix);
-    break;
-  case eStyleSVGPaintType_ContextFill:
-    pattern = mPaintDefinition.mContextPaint->GetFillPattern(aOpacity, aCTM);
-    // Don't cache this. mContextPaint will have cached it anyway. If we
-    // cache it, we'll have to compute mPatternMatrix, which is annoying.
-    return pattern.forget();
-  case eStyleSVGPaintType_ContextStroke:
-    pattern = mPaintDefinition.mContextPaint->GetStrokePattern(aOpacity, aCTM);
-    // Don't cache this. mContextPaint will have cached it anyway. If we
-    // cache it, we'll have to compute mPatternMatrix, which is annoying.
-    return pattern.forget();
-  default:
-    MOZ_ASSERT(false, "invalid paint type");
-    return nullptr;
-  }
-
-  mPatternCache.Put(aOpacity, pattern);
-  return pattern.forget();
-}
-
-//----------------------------------------------------------------------
 // Internal methods
 
 void
 nsSVGGlyphFrame::SetGlyphPosition(gfxPoint *aPosition, bool aForceGlobalTransform)
 {
   float drawScale, metricsScale;
 
   nsSVGTextPathFrame *textPath = FindTextPathParent();
--- a/layout/svg/nsSVGGlyphFrame.h
+++ b/layout/svg/nsSVGGlyphFrame.h
@@ -6,16 +6,17 @@
 #ifndef __NS_SVGGLYPHFRAME_H__
 #define __NS_SVGGLYPHFRAME_H__
 
 #include "mozilla/Attributes.h"
 #include "gfxSVGGlyphs.h"
 #include "nsISVGChildFrame.h"
 #include "nsISVGGlyphFragmentNode.h"
 #include "nsSVGGeometryFrame.h"
+#include "nsSVGTextFrame2.h" // for SVGTextContextPaint
 #include "nsSVGUtils.h"
 #include "nsTextFragment.h"
 #include "nsIContent.h"
 #include "DrawMode.h"
 
 class CharacterIterator;
 class gfxContext;
 class nsDisplaySVGGlyphs;
@@ -23,87 +24,20 @@ class nsRenderingContext;
 class nsSVGGlyphFrame;
 class nsSVGTextFrame;
 class nsSVGTextPathFrame;
 class gfxTextContextPaint;
 
 struct CharacterPosition;
 
 namespace mozilla {
-
 namespace dom {
 class SVGIRect;
 }
-
-// Slightly horrible callback for deferring application of opacity
-struct SVGTextContextPaint : public gfxTextContextPaint {
-  already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
-                                              const gfxMatrix& aCTM) MOZ_OVERRIDE;
-  already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
-                                                const gfxMatrix& aCTM) MOZ_OVERRIDE;
-
-  void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
-  float GetFillOpacity() MOZ_OVERRIDE { return mFillOpacity; }
-
-  void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
-  float GetStrokeOpacity() MOZ_OVERRIDE { return mStrokeOpacity; }
-
-  struct Paint {
-    Paint() : mPaintType(eStyleSVGPaintType_None) {}
-
-    void SetPaintServer(nsIFrame *aFrame, const gfxMatrix& aContextMatrix,
-                        nsSVGPaintServerFrame *aPaintServerFrame) {
-      mPaintType = eStyleSVGPaintType_Server;
-      mPaintDefinition.mPaintServerFrame = aPaintServerFrame;
-      mFrame = aFrame;
-      mContextMatrix = aContextMatrix;
-    }
-
-    void SetColor(const nscolor &aColor) {
-      mPaintType = eStyleSVGPaintType_Color;
-      mPaintDefinition.mColor = aColor;
-    }
-
-    void SetContextPaint(gfxTextContextPaint *aContextPaint,
-                         nsStyleSVGPaintType aPaintType) {
-      NS_ASSERTION(aPaintType == eStyleSVGPaintType_ContextFill ||
-                   aPaintType == eStyleSVGPaintType_ContextStroke,
-                   "Invalid context paint type");
-      mPaintType = aPaintType;
-      mPaintDefinition.mContextPaint = aContextPaint;
-    }
-
-    union {
-      nsSVGPaintServerFrame *mPaintServerFrame;
-      gfxTextContextPaint *mContextPaint;
-      nscolor mColor;
-    } mPaintDefinition;
-
-    nsIFrame *mFrame;
-    // CTM defining the user space for the pattern we will use.
-    gfxMatrix mContextMatrix;
-    nsStyleSVGPaintType mPaintType;
-
-    // Device-space-to-pattern-space
-    gfxMatrix mPatternMatrix;
-    nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
-
-    already_AddRefed<gfxPattern> GetPattern(float aOpacity,
-                                            nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
-                                            const gfxMatrix& aCTM);
-  };
-
-  Paint mFillPaint;
-  Paint mStrokePaint;
-
-  float mFillOpacity;
-  float mStrokeOpacity;
-};
-
-} // namespace mozilla
+}
 
 using namespace mozilla;
 
 typedef nsSVGGeometryFrame nsSVGGlyphFrameBase;
 
 class nsSVGGlyphFrame : public nsSVGGlyphFrameBase,
                         public nsISVGGlyphFragmentNode,
                         public nsISVGChildFrame
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -2964,18 +2964,96 @@ SVGTextDrawPathCallbacks::StrokeGeometry
       mColor == NS_40PERCENT_FOREGROUND_COLOR) {
     // Don't paint the stroke when we are filling with a selection color.
     if (nsSVGUtils::SetupCairoStroke(mFrame, gfx)) {
       gfx->Stroke();
     }
   }
 }
 
+//----------------------------------------------------------------------
+// SVGTextContextPaint methods:
+
+already_AddRefed<gfxPattern>
+SVGTextContextPaint::GetFillPattern(float aOpacity,
+                                    const gfxMatrix& aCTM)
+{
+  return mFillPaint.GetPattern(aOpacity, &nsStyleSVG::mFill, aCTM);
 }
 
+already_AddRefed<gfxPattern>
+SVGTextContextPaint::GetStrokePattern(float aOpacity,
+                                      const gfxMatrix& aCTM)
+{
+  return mStrokePaint.GetPattern(aOpacity, &nsStyleSVG::mStroke, aCTM);
+}
+
+already_AddRefed<gfxPattern>
+SVGTextContextPaint::Paint::GetPattern(float aOpacity,
+                                       nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
+                                       const gfxMatrix& aCTM)
+{
+  nsRefPtr<gfxPattern> pattern;
+  if (mPatternCache.Get(aOpacity, getter_AddRefs(pattern))) {
+    // Set the pattern matrix just in case it was messed with by a previous
+    // caller. We should get the same matrix each time a pattern is constructed
+    // so this should be fine.
+    pattern->SetMatrix(aCTM * mPatternMatrix);
+    return pattern.forget();
+  }
+
+  switch (mPaintType) {
+  case eStyleSVGPaintType_None:
+    pattern = new gfxPattern(gfxRGBA(0.0f, 0.0f, 0.0f, 0.0f));
+    mPatternMatrix = gfxMatrix();
+    break;
+  case eStyleSVGPaintType_Color:
+    pattern = new gfxPattern(gfxRGBA(NS_GET_R(mPaintDefinition.mColor) / 255.0,
+                                     NS_GET_G(mPaintDefinition.mColor) / 255.0,
+                                     NS_GET_B(mPaintDefinition.mColor) / 255.0,
+                                     NS_GET_A(mPaintDefinition.mColor) / 255.0 * aOpacity));
+    mPatternMatrix = gfxMatrix();
+    break;
+  case eStyleSVGPaintType_Server:
+    pattern = mPaintDefinition.mPaintServerFrame->GetPaintServerPattern(mFrame,
+                                                                        mContextMatrix,
+                                                                        aFillOrStroke,
+                                                                        aOpacity);
+    {
+      // m maps original-user-space to pattern space
+      gfxMatrix m = pattern->GetMatrix();
+      gfxMatrix deviceToOriginalUserSpace = mContextMatrix;
+      deviceToOriginalUserSpace.Invert();
+      // mPatternMatrix maps device space to pattern space via original user space
+      mPatternMatrix = deviceToOriginalUserSpace * m;
+    }
+    pattern->SetMatrix(aCTM * mPatternMatrix);
+    break;
+  case eStyleSVGPaintType_ContextFill:
+    pattern = mPaintDefinition.mContextPaint->GetFillPattern(aOpacity, aCTM);
+    // Don't cache this. mContextPaint will have cached it anyway. If we
+    // cache it, we'll have to compute mPatternMatrix, which is annoying.
+    return pattern.forget();
+  case eStyleSVGPaintType_ContextStroke:
+    pattern = mPaintDefinition.mContextPaint->GetStrokePattern(aOpacity, aCTM);
+    // Don't cache this. mContextPaint will have cached it anyway. If we
+    // cache it, we'll have to compute mPatternMatrix, which is annoying.
+    return pattern.forget();
+  default:
+    MOZ_ASSERT(false, "invalid paint type");
+    return nullptr;
+  }
+
+  mPatternCache.Put(aOpacity, pattern);
+  return pattern.forget();
+}
+
+} // namespace mozilla
+
+
 // ============================================================================
 // nsSVGTextFrame2
 
 // ----------------------------------------------------------------------------
 // Display list item
 
 class nsDisplaySVGText : public nsDisplayItem {
 public:
--- a/layout/svg/nsSVGTextFrame2.h
+++ b/layout/svg/nsSVGTextFrame2.h
@@ -5,18 +5,19 @@
 
 #ifndef NS_SVGTEXTFRAME2_H
 #define NS_SVGTEXTFRAME2_H
 
 #include "mozilla/Attributes.h"
 #include "gfxMatrix.h"
 #include "gfxRect.h"
 #include "gfxSVGGlyphs.h"
+#include "nsIContent.h"
 #include "nsStubMutationObserver.h"
-#include "nsSVGGlyphFrame.h" // for SVGTextContextPaint
+#include "nsSVGPaintServerFrame.h"
 #include "nsSVGTextContainerFrame.h"
 
 class nsDisplaySVGText;
 class nsRenderingContext;
 class nsSVGTextFrame2;
 class nsTextFrame;
 class gfxPath;
 
@@ -130,17 +131,82 @@ public:
   NS_DECL_NSIRUNNABLE
   GlyphMetricsUpdater(nsSVGTextFrame2* aFrame) : mFrame(aFrame) { }
   static void Run(nsSVGTextFrame2* aFrame);
   void Revoke() { mFrame = nullptr; }
 private:
   nsSVGTextFrame2* mFrame;
 };
 
-}
+// Slightly horrible callback for deferring application of opacity
+struct SVGTextContextPaint : public gfxTextContextPaint {
+  already_AddRefed<gfxPattern> GetFillPattern(float aOpacity,
+                                              const gfxMatrix& aCTM) MOZ_OVERRIDE;
+  already_AddRefed<gfxPattern> GetStrokePattern(float aOpacity,
+                                                const gfxMatrix& aCTM) MOZ_OVERRIDE;
+
+  void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
+  float GetFillOpacity() MOZ_OVERRIDE { return mFillOpacity; }
+
+  void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
+  float GetStrokeOpacity() MOZ_OVERRIDE { return mStrokeOpacity; }
+
+  struct Paint {
+    Paint() : mPaintType(eStyleSVGPaintType_None) {}
+
+    void SetPaintServer(nsIFrame *aFrame, const gfxMatrix& aContextMatrix,
+                        nsSVGPaintServerFrame *aPaintServerFrame) {
+      mPaintType = eStyleSVGPaintType_Server;
+      mPaintDefinition.mPaintServerFrame = aPaintServerFrame;
+      mFrame = aFrame;
+      mContextMatrix = aContextMatrix;
+    }
+
+    void SetColor(const nscolor &aColor) {
+      mPaintType = eStyleSVGPaintType_Color;
+      mPaintDefinition.mColor = aColor;
+    }
+
+    void SetContextPaint(gfxTextContextPaint *aContextPaint,
+                         nsStyleSVGPaintType aPaintType) {
+      NS_ASSERTION(aPaintType == eStyleSVGPaintType_ContextFill ||
+                   aPaintType == eStyleSVGPaintType_ContextStroke,
+                   "Invalid context paint type");
+      mPaintType = aPaintType;
+      mPaintDefinition.mContextPaint = aContextPaint;
+    }
+
+    union {
+      nsSVGPaintServerFrame *mPaintServerFrame;
+      gfxTextContextPaint *mContextPaint;
+      nscolor mColor;
+    } mPaintDefinition;
+
+    nsIFrame *mFrame;
+    // CTM defining the user space for the pattern we will use.
+    gfxMatrix mContextMatrix;
+    nsStyleSVGPaintType mPaintType;
+
+    // Device-space-to-pattern-space
+    gfxMatrix mPatternMatrix;
+    nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
+
+    already_AddRefed<gfxPattern> GetPattern(float aOpacity,
+                                            nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
+                                            const gfxMatrix& aCTM);
+  };
+
+  Paint mFillPaint;
+  Paint mStrokePaint;
+
+  float mFillOpacity;
+  float mStrokeOpacity;
+};
+
+} // namespace mozilla
 
 /**
  * Frame class for SVG <text> elements, used when the
  * layout.svg.css-text.enabled is true.
  *
  * An nsSVGTextFrame2 manages SVG text layout, painting and interaction for
  * all descendent text content elements.  The frame tree will look like this:
  *
@@ -180,16 +246,18 @@ class nsSVGTextFrame2 : public nsSVGText
   friend class mozilla::GlyphMetricsUpdater;
   friend class mozilla::TextFrameIterator;
   friend class mozilla::TextNodeCorrespondenceRecorder;
   friend struct mozilla::TextRenderedRun;
   friend class mozilla::TextRenderedRunIterator;
   friend class MutationObserver;
   friend class nsDisplaySVGText;
 
+  typedef mozilla::SVGTextContextPaint SVGTextContextPaint;
+
 protected:
   nsSVGTextFrame2(nsStyleContext* aContext)
     : nsSVGTextFrame2Base(aContext),
       mFontSizeScaleFactor(1.0f),
       mLastContextScale(1.0f),
       mLengthAdjustScaleFactor(1.0f)
   {
     AddStateBits(NS_STATE_SVG_POSITIONING_DIRTY);
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -2346,17 +2346,17 @@ nsCrypto::ImportUserCertificates(const n
     }
     // Let's figure out which nickname to give the cert.  If 
     // a certificate with the same subject name already exists,
     // then just use that one, otherwise, get the default nickname.
     if (currCert->nickname) {
       localNick = currCert->nickname;
     }
     else if (!nickname || nickname[0] == '\0') {
-      nsNSSCertificateDB::get_default_nickname(currCert, ctx, localNick);
+      nsNSSCertificateDB::get_default_nickname(currCert, ctx, localNick, locker);
     } else {
       //This is the case where we're getting a brand new
       //cert that doesn't have the same subjectName as a cert
       //that already exists in our db and the CA page has 
       //designated a nickname to use for the newly issued cert.
       localNick = nickname;
     }
     {
@@ -2402,17 +2402,17 @@ nsCrypto::ImportUserCertificates(const n
         rv = NS_ERROR_OUT_OF_MEMORY;
         goto loser;
       }
       for (node = CERT_LIST_HEAD(caPubs), i=0; 
            !CERT_LIST_END(node, caPubs);
            node = CERT_LIST_NEXT(node), i++) {
         derCerts[i] = node->cert->derCert;
       }
-      nsNSSCertificateDB::ImportValidCACerts(numCAs, derCerts, ctx);
+      nsNSSCertificateDB::ImportValidCACerts(numCAs, derCerts, ctx, locker);
       nsMemory::Free(derCerts);
     }
   }
  }
 
   if (aDoForcedBackup) {
     // I can't pop up a file picker from the depths of JavaScript,
     // so I'll just post an event on the UI queue to do the backups
--- a/security/manager/ssl/src/nsNSSCertificateDB.cpp
+++ b/security/manager/ssl/src/nsNSSCertificateDB.cpp
@@ -74,16 +74,19 @@ NS_IMETHODIMP
 nsNSSCertificateDB::FindCertByNickname(nsISupports *aToken,
                                       const nsAString &nickname,
                                       nsIX509Cert **_rvCert)
 {
   NS_ENSURE_ARG_POINTER(_rvCert);
   *_rvCert = nullptr;
 
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
   ScopedCERTCertificate cert;
   char *asciiname = nullptr;
   NS_ConvertUTF16toUTF8 aUtf8Nickname(nickname);
   asciiname = const_cast<char*>(aUtf8Nickname.get());
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting \"%s\"\n", asciiname));
 #if 0
   // what it should be, but for now...
   if (aToken) {
@@ -112,16 +115,20 @@ nsNSSCertificateDB::FindCertByDBKey(cons
                                    nsIX509Cert **_cert)
 {
   NS_ENSURE_ARG_POINTER(aDBkey);
   NS_ENSURE_ARG(aDBkey[0]);
   NS_ENSURE_ARG_POINTER(_cert);
   *_cert = nullptr;
 
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   SECItem keyItem = {siBuffer, nullptr, 0};
   SECItem *dummy;
   CERTIssuerAndSN issuerSN;
   //unsigned long moduleID,slotID;
 
   dummy = NSSBase64_DecodeBuffer(nullptr, &keyItem, aDBkey,
                                  (uint32_t)strlen(aDBkey)); 
   if (!dummy || keyItem.len < NS_NSS_LONG*4) {
@@ -160,16 +167,20 @@ nsNSSCertificateDB::FindCertByDBKey(cons
 
 NS_IMETHODIMP 
 nsNSSCertificateDB::FindCertNicknames(nsISupports *aToken, 
                                      uint32_t      aType,
                                      uint32_t     *_count,
                                      PRUnichar  ***_certNames)
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   nsresult rv = NS_ERROR_FAILURE;
   /*
    * obtain the cert list from NSS
    */
   ScopedCERTCertList certList;
   PK11CertListType pk11type;
 #if 0
   // this would seem right, but it didn't work...
@@ -181,17 +192,17 @@ nsNSSCertificateDB::FindCertNicknames(ns
     pk11type = PK11CertListUnique;
   certList = PK11_ListCerts(pk11type, nullptr);
   if (!certList)
     goto cleanup;
   /*
    * get list of cert names from list of certs
    * XXX also cull the list (NSS only distinguishes based on user/non-user
    */
-  getCertNames(certList, aType, _count, _certNames);
+  getCertNames(certList, aType, _count, _certNames, locker);
   rv = NS_OK;
   /*
    * finish up
    */
 cleanup:
   return rv;
 }
 
@@ -220,19 +231,19 @@ collect_certs(void *arg, SECItem **certs
     certs++;
   }
 
   return (SECSuccess);
 }
 
 CERTDERCerts*
 nsNSSCertificateDB::getCertsFromPackage(PLArenaPool *arena, uint8_t *data, 
-                                        uint32_t length)
+                                        uint32_t length,
+                                        const nsNSSShutDownPreventionLock &/*proofOfLock*/)
 {
-  nsNSSShutDownPreventionLock locker;
   CERTDERCerts *collectArgs = 
                (CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts));
   if (!collectArgs)
     return nullptr;
 
   collectArgs->arena = arena;
   SECStatus sec_rv = CERT_DecodeCertPackage(reinterpret_cast<char *>(data), 
                                             length, collect_certs, 
@@ -240,33 +251,32 @@ nsNSSCertificateDB::getCertsFromPackage(
   if (sec_rv != SECSuccess)
     return nullptr;
 
   return collectArgs;
 }
 
 nsresult
 nsNSSCertificateDB::handleCACertDownload(nsIArray *x509Certs,
-                                         nsIInterfaceRequestor *ctx)
+                                         nsIInterfaceRequestor *ctx,
+                                         const nsNSSShutDownPreventionLock &proofOfLock)
 {
   // First thing we have to do is figure out which certificate we're 
   // gonna present to the user.  The CA may have sent down a list of 
   // certs which may or may not be a chained list of certs.  Until
   // the day we can design some solid UI for the general case, we'll
   // code to the > 90% case.  That case is where a CA sends down a
   // list that is a hierarchy whose root is either the first or 
   // the last cert.  What we're gonna do is compare the first 
   // 2 entries, if the second was signed by the first, we assume
   // the root cert is the first cert and display it.  Otherwise,
   // we compare the last 2 entries, if the second to last cert was
   // signed by the last cert, then we assume the last cert is the
   // root and display it.
 
-  nsNSSShutDownPreventionLock locker;
-
   uint32_t numCerts;
 
   x509Certs->GetLength(&numCerts);
   NS_ASSERTION(numCerts > 0, "Didn't get any certs to import.");
   if (numCerts == 0)
     return NS_OK; // Nothing to import, so nothing to do.
 
   nsCOMPtr<nsIX509Cert> certToShow;
@@ -346,22 +356,22 @@ nsNSSCertificateDB::handleCACertDownload
   der.len = 0;
   
   if (!tmpCert) {
     NS_ERROR("Couldn't create cert from DER blob");
     return NS_ERROR_FAILURE;
   }
 
   if (!CERT_IsCACert(tmpCert, nullptr)) {
-    DisplayCertificateAlert(ctx, "NotACACert", certToShow);
+    DisplayCertificateAlert(ctx, "NotACACert", certToShow, proofOfLock);
     return NS_ERROR_FAILURE;
   }
 
   if (tmpCert->isperm) {
-    DisplayCertificateAlert(ctx, "CaCertExists", certToShow);
+    DisplayCertificateAlert(ctx, "CaCertExists", certToShow, proofOfLock);
     return NS_ERROR_FAILURE;
   }
 
   uint32_t trustBits;
   bool allows;
   rv = dialogs->ConfirmDownloadCACert(ctx, certToShow, &trustBits, &allows);
   if (NS_FAILED(rv))
     return rv;
@@ -417,38 +427,42 @@ nsNSSCertificateDB::handleCACertDownload
     if (!tmpCert2) {
       NS_ERROR("Couldn't create temp cert from DER blob");
       continue;  // Let's try to import the rest of 'em
     }
     
     CERT_AddCertToListTail(certList, tmpCert2);
   }
 
-  return ImportValidCACertsInList(certList, ctx);
+  return ImportValidCACertsInList(certList, ctx, proofOfLock);
 }
 
 /*
  *  [noscript] void importCertificates(in charPtr data, in unsigned long length,
  *                                     in unsigned long type, 
  *                                     in nsIInterfaceRequestor ctx);
  */
 NS_IMETHODIMP 
 nsNSSCertificateDB::ImportCertificates(uint8_t * data, uint32_t length, 
                                        uint32_t type, 
                                        nsIInterfaceRequestor *ctx)
 
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   nsresult nsrv;
 
   PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   if (!arena)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
+  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length, locker);
   if (!certCollection) {
     PORT_FreeArena(arena, false);
     return NS_ERROR_FAILURE;
   }
   nsCOMPtr<nsIMutableArray> array =
     do_CreateInstance(NS_ARRAY_CONTRACTID, &nsrv);
   if (NS_FAILED(nsrv)) {
     PORT_FreeArena(arena, false);
@@ -464,17 +478,17 @@ nsNSSCertificateDB::ImportCertificates(u
      nssCert = nsNSSCertificate::ConstructFromDER((char*)currItem->data, currItem->len);
      if (!nssCert)
        return NS_ERROR_FAILURE;
      x509Cert = do_QueryInterface((nsIX509Cert*)nssCert);
      array->AppendElement(x509Cert, false);
   }
   switch (type) {
   case nsIX509Cert::CA_CERT:
-    nsrv = handleCACertDownload(array, ctx);
+    nsrv = handleCACertDownload(array, ctx, locker);
     break;
   default:
     // We only deal with import CA certs in this method currently.
      nsrv = NS_ERROR_FAILURE;
      break;
   }  
   PORT_FreeArena(arena, false);
   return nsrv;
@@ -519,31 +533,35 @@ ImportCertsIntoPermanentStorage(const Sc
  *                                     in nsIInterfaceRequestor ctx);
  */
 NS_IMETHODIMP
 nsNSSCertificateDB::ImportEmailCertificate(uint8_t * data, uint32_t length, 
                                        nsIInterfaceRequestor *ctx)
 
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   SECStatus srv = SECFailure;
   nsresult nsrv = NS_OK;
   CERTCertDBHandle *certdb;
   CERTCertificate **certArray = nullptr;
   ScopedCERTCertList certList;
   CERTCertListNode *node;
   SECItem **rawArray;
   int numcerts;
   int i;
 
   PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   if (!arena)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
+  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length, locker);
   if (!certCollection) {
     PORT_FreeArena(arena, false);
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
@@ -604,17 +622,17 @@ nsNSSCertificateDB::ImportEmailCertifica
     SECStatus rv = certVerifier->VerifyCert(node->cert,
                                             certificateUsageEmailRecipient,
                                             now, ctx, 0, &verifyCertChain);
 
     ScopedCERTCertList certChain(verifyCertChain);
 
     if (rv != SECSuccess) {
       nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
-      DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
+      DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, locker);
       continue;
     }
     rv = ImportCertsIntoPermanentStorage(certChain, certUsageEmailRecipient, false);
     if (rv != SECSuccess) {
       goto loser;
     } 
     CERT_SaveSMimeProfile(node->cert, nullptr, nullptr);
 
@@ -630,30 +648,34 @@ loser:
 }
 
 NS_IMETHODIMP
 nsNSSCertificateDB::ImportServerCertificate(uint8_t * data, uint32_t length, 
                                             nsIInterfaceRequestor *ctx)
 
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   SECStatus srv = SECFailure;
   nsresult nsrv = NS_OK;
   ScopedCERTCertificate cert;
   SECItem **rawCerts = nullptr;
   int numcerts;
   int i;
   nsNSSCertTrust trust;
   char *serverNickname = nullptr;
  
   PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   if (!arena)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
+  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length, locker);
   if (!certCollection) {
     PORT_FreeArena(arena, false);
     return NS_ERROR_FAILURE;
   }
   cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts,
                                  nullptr, false, true);
   if (!cert) {
     nsrv = NS_ERROR_FAILURE;
@@ -689,17 +711,17 @@ nsNSSCertificateDB::ImportServerCertific
 loser:
   PORT_Free(rawCerts);
   if (arena) 
     PORT_FreeArena(arena, true);
   return nsrv;
 }
 
 nsresult
-nsNSSCertificateDB::ImportValidCACerts(int numCACerts, SECItem *CACerts, nsIInterfaceRequestor *ctx)
+nsNSSCertificateDB::ImportValidCACerts(int numCACerts, SECItem *CACerts, nsIInterfaceRequestor *ctx,  const nsNSSShutDownPreventionLock &proofOfLock)
 {
   ScopedCERTCertList certList;
   SECItem **rawArray;
 
   // build a CertList for filtering
   certList = CERT_NewCertList();
   if (!certList) {
     return NS_ERROR_FAILURE;
@@ -733,21 +755,22 @@ nsNSSCertificateDB::ImportValidCACerts(i
     if (cacert)
       cacert = CERT_DupCertificate(cacert);
     if (cacert)
       CERT_AddCertToListTail(certList, cacert);
   }
 
   CERT_DestroyCertArray(certArray, numCACerts);
 
-  return ImportValidCACertsInList(certList, ctx);
+  return ImportValidCACertsInList(certList, ctx, proofOfLock);
 }
 
 nsresult
-nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx)
+nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx,
+                                             const nsNSSShutDownPreventionLock &proofOfLock)
 {
   RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
   if (!certVerifier)
     return NS_ERROR_UNEXPECTED;
 
   /* filter out the certs we don't want */
   SECStatus srv = CERT_FilterCertListByUsage(certList, certUsageAnyCA, true);
   if (srv != SECSuccess) {
@@ -768,29 +791,30 @@ nsNSSCertificateDB::ImportValidCACertsIn
 
     SECStatus rv = certVerifier->VerifyCert(node->cert, certificateUsageVerifyCA,
                                             PR_Now(), ctx, 0, &verifyCertChain);
 
     ScopedCERTCertList certChain(verifyCertChain);
 
     if (rv != SECSuccess) {
       nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
-      DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
+      DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow, proofOfLock);
       continue;
     }
 
     ImportCertsIntoPermanentStorage(certChain, certUsageAnyCA, true);
   }
   
   return NS_OK;
 }
 
 void nsNSSCertificateDB::DisplayCertificateAlert(nsIInterfaceRequestor *ctx, 
                                                  const char *stringID, 
-                                                 nsIX509Cert *certToShow)
+                                                 nsIX509Cert *certToShow,
+                                                 const nsNSSShutDownPreventionLock &/*proofOfLock*/)
 {
   if (!NS_IsMainThread()) {
     NS_ERROR("nsNSSCertificateDB::DisplayCertificateAlert called off the main thread");
     return;
   }
 
   nsPSMUITracker tracker;
   if (!tracker.isUIForbidden()) {
@@ -822,96 +846,103 @@ NS_IMETHODIMP
 nsNSSCertificateDB::ImportUserCertificate(uint8_t *data, uint32_t length, nsIInterfaceRequestor *ctx)
 {
   if (!NS_IsMainThread()) {
     NS_ERROR("nsNSSCertificateDB::ImportUserCertificate called off the main thread");
     return NS_ERROR_NOT_SAME_THREAD;
   }
   
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   ScopedPK11SlotInfo slot;
   nsAutoCString nickname;
   nsresult rv = NS_ERROR_FAILURE;
   int numCACerts;
   SECItem *CACerts;
   CERTDERCerts * collectArgs;
   PLArenaPool *arena;
   ScopedCERTCertificate cert;
 
   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   if (!arena) {
     goto loser;
   }
 
-  collectArgs = getCertsFromPackage(arena, data, length);
+  collectArgs = getCertsFromPackage(arena, data, length, locker);
   if (!collectArgs) {
     goto loser;
   }
 
   cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts,
                                  nullptr, false, true);
   if (!cert) {
     goto loser;
   }
 
   slot = PK11_KeyForCertExists(cert, nullptr, ctx);
   if (!slot) {
     nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert);
-    DisplayCertificateAlert(ctx, "UserCertIgnoredNoPrivateKey", certToShow);
+    DisplayCertificateAlert(ctx, "UserCertIgnoredNoPrivateKey", certToShow, locker);
     goto loser;
   }
   slot = nullptr;
 
   /* pick a nickname for the cert */
   if (cert->nickname) {
 	/* sigh, we need a call to look up other certs with this subject and
 	 * identify nicknames from them. We can no longer walk down internal
 	 * database structures  rjr */
   	nickname = cert->nickname;
   }
   else {
-    get_default_nickname(cert, ctx, nickname);
+    get_default_nickname(cert, ctx, nickname, locker);
   }
 
   /* user wants to import the cert */
   {
     char *cast_const_away = const_cast<char*>(nickname.get());
     slot = PK11_ImportCertForKey(cert, cast_const_away, ctx);
   }
   if (!slot) {
     goto loser;
   }
   slot = nullptr;
 
   {
     nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert);
-    DisplayCertificateAlert(ctx, "UserCertImported", certToShow);
+    DisplayCertificateAlert(ctx, "UserCertImported", certToShow, locker);
   }
   rv = NS_OK;
 
   numCACerts = collectArgs->numcerts - 1;
   if (numCACerts) {
     CACerts = collectArgs->rawCerts+1;
-    rv = ImportValidCACerts(numCACerts, CACerts, ctx);
+    rv = ImportValidCACerts(numCACerts, CACerts, ctx, locker);
   }
   
 loser:
   if (arena) {
     PORT_FreeArena(arena, false);
   }
   return rv;
 }
 
 /*
  * void deleteCertificate(in nsIX509Cert aCert);
  */
 NS_IMETHODIMP 
 nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert)
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
   nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert);
   ScopedCERTCertificate cert(nssCert->GetCert());
   if (!cert) return NS_ERROR_FAILURE;
   SECStatus srv = SECSuccess;
 
   uint32_t certType;
   nssCert->GetCertType(&certType);
   if (NS_FAILED(nssCert->MarkForPermDeletion()))
@@ -941,16 +972,19 @@ nsNSSCertificateDB::DeleteCertificate(ns
  *                   in unsigned long trust);
  */
 NS_IMETHODIMP 
 nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert, 
                                  uint32_t type,
                                  uint32_t trusted)
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
   SECStatus srv;
   nsNSSCertTrust trust;
   nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
   if (!pipCert)
     return NS_ERROR_FAILURE;
   ScopedCERTCertificate nsscert(pipCert->GetCert());
 
   if (type == nsIX509Cert::CA_CERT) {
@@ -988,16 +1022,19 @@ nsNSSCertificateDB::IsCertTrusted(nsIX50
                                   uint32_t certType,
                                   uint32_t trustType,
                                   bool *_isTrusted)
 {
   NS_ENSURE_ARG_POINTER(_isTrusted);
   *_isTrusted = false;
 
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
   SECStatus srv;
   nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
   ScopedCERTCertificate nsscert(pipCert->GetCert());
   CERTCertTrust nsstrust;
   srv = CERT_GetCertTrust(nsscert, &nsstrust);
   if (srv != SECSuccess)
     return NS_ERROR_FAILURE;
 
@@ -1037,16 +1074,21 @@ nsNSSCertificateDB::IsCertTrusted(nsIX50
 }
 
 
 NS_IMETHODIMP 
 nsNSSCertificateDB::ImportCertsFromFile(nsISupports *aToken, 
                                         nsIFile *aFile,
                                         uint32_t aType)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   NS_ENSURE_ARG(aFile);
   switch (aType) {
     case nsIX509Cert::CA_CERT:
     case nsIX509Cert::EMAIL_CERT:
     case nsIX509Cert::SERVER_CERT:
       // good
       break;
     
@@ -1101,16 +1143,21 @@ nsNSSCertificateDB::ImportCertsFromFile(
   delete [] buf;
   return rv;  
 }
 
 NS_IMETHODIMP 
 nsNSSCertificateDB::ImportPKCS12File(nsISupports *aToken, 
                                      nsIFile *aFile)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   NS_ENSURE_ARG(aFile);
   nsPKCS12Blob blob;
   nsCOMPtr<nsIPK11Token> token = do_QueryInterface(aToken);
   if (token) {
     blob.SetToken(token);
   }
   return blob.ImportFromFile(aFile);
 }
@@ -1118,16 +1165,20 @@ nsNSSCertificateDB::ImportPKCS12File(nsI
 NS_IMETHODIMP 
 nsNSSCertificateDB::ExportPKCS12File(nsISupports     *aToken, 
                                      nsIFile          *aFile,
                                      uint32_t          count,
                                      nsIX509Cert     **certs)
                                      //const PRUnichar **aCertNames)
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   NS_ENSURE_ARG(aFile);
   nsPKCS12Blob blob;
   if (count == 0) return NS_OK;
   nsCOMPtr<nsIPK11Token> localRef;
   if (!aToken) {
     ScopedPK11SlotInfo keySlot(PK11_GetInternalKeySlot());
     NS_ASSERTION(keySlot,"Failed to get the internal key slot");
     localRef = new nsPK11Token(keySlot);
@@ -1151,22 +1202,23 @@ nsNSSCertificateDB::ExportPKCS12File(nsI
  * GetSortedNameList
  *
  * Converts a CERTCertList to a list of certificate names
  */
 void
 nsNSSCertificateDB::getCertNames(CERTCertList *certList,
                                  uint32_t      type, 
                                  uint32_t     *_count,
-                                 PRUnichar  ***_certNames)
+                                 PRUnichar  ***_certNames,
+                                 const nsNSSShutDownPreventionLock &/*proofOfLock*/)
 {
-  nsNSSShutDownPreventionLock locker;
   CERTCertListNode *node;
   uint32_t numcerts = 0, i=0;
   PRUnichar **tmpArray = nullptr;
+
   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("List of certs %d:\n", type));
   for (node = CERT_LIST_HEAD(certList);
        !CERT_LIST_END(node, certList);
        node = CERT_LIST_NEXT(node)) {
     if (getCertType(node->cert) == type) {
       numcerts++;
     }
   }
@@ -1213,16 +1265,20 @@ nsNSSCertificateDB::FindEmailEncryptionC
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nullptr;
 
   if (aNickname.IsEmpty())
     return NS_OK;
 
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
   char *asciiname = nullptr;
   NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
   asciiname = const_cast<char*>(aUtf8Nickname.get());
 
   /* Find a good cert in the user's database */
   ScopedCERTCertificate cert;
   cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), asciiname, 
@@ -1245,16 +1301,20 @@ nsNSSCertificateDB::FindEmailSigningCert
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nullptr;
 
   if (aNickname.IsEmpty())
     return NS_OK;
 
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   ScopedCERTCertificate cert;
   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
   char *asciiname = nullptr;
   NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
   asciiname = const_cast<char*>(aUtf8Nickname.get());
 
   /* Find a good cert in the user's database */
   cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), asciiname, 
@@ -1270,16 +1330,19 @@ nsNSSCertificateDB::FindEmailSigningCert
   nssCert.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNSSCertificateDB::FindCertByEmailAddress(nsISupports *aToken, const char *aEmailAddress, nsIX509Cert **_retval)
 {
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
   
   RefPtr<CertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
   ScopedCERTCertList certlist(
       PK11_FindCertsFromEmailAddress(aEmailAddress, nullptr));
   if (!certlist)
     return NS_ERROR_FAILURE;  
@@ -1343,16 +1406,20 @@ nsNSSCertificateDB::ConstructX509FromBas
   uint32_t lengthDER = (len * 3) / 4;
   if (base64[len-1] == '=') {
     lengthDER--;
     if (base64[len-2] == '=')
       lengthDER--;
   }
 
   nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   SECItem secitem_cert;
   secitem_cert.type = siDERCertBuffer;
   secitem_cert.data = (unsigned char*)certDER;
   secitem_cert.len = lengthDER;
 
   ScopedCERTCertificate cert;
   cert =
     CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &secitem_cert,
@@ -1369,21 +1436,21 @@ nsNSSCertificateDB::ConstructX509FromBas
   }
   nssCert.forget(_retval);
   return NS_OK;
 }
 
 void
 nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert, 
                                          nsIInterfaceRequestor* ctx,
-                                         nsCString &nickname)
+                                         nsCString &nickname,
+                                         const nsNSSShutDownPreventionLock &/*proofOfLock*/)
 {
   nickname.Truncate();
 
-  nsNSSShutDownPreventionLock locker;
   nsresult rv;
   CK_OBJECT_HANDLE keyHandle;
 
   CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
   if (NS_FAILED(rv))
     return;
 
@@ -1486,16 +1553,21 @@ nsNSSCertificateDB::get_default_nickname
   }
 }
 
 NS_IMETHODIMP nsNSSCertificateDB::AddCertFromBase64(const char *aBase64, const char *aTrust, const char *aName)
 {
   NS_ENSURE_ARG_POINTER(aBase64);
   nsCOMPtr <nsIX509Cert> newCert;
 
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   nsNSSCertTrust trust;
 
   // need to calculate the trust bits from the aTrust string.
   SECStatus stat = CERT_DecodeTrustString(trust.GetTrust(),
     /* this is const, but not declared that way */(char *) aTrust);
   NS_ENSURE_STATE(stat == SECSuccess); // if bad trust passed in, return error.
 
 
@@ -1546,16 +1618,21 @@ nsNSSCertificateDB::AddCert(const nsACSt
   nsresult rv = Base64Encode(aCertDER, base64);
   NS_ENSURE_SUCCESS(rv, rv);
   return AddCertFromBase64(base64.get(), aTrust, aName);
 }
 
 NS_IMETHODIMP 
 nsNSSCertificateDB::GetCerts(nsIX509CertList **_retval)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   CERTCertList *certList;
 
   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
   nsCOMPtr<nsIX509CertList> nssCertList;
   certList = PK11_ListCerts(PK11CertListUnique, ctx);
 
   // nsNSSCertList 1) adopts certList, and 2) handles the nullptr case fine.
   // (returns an empty list) 
@@ -1564,16 +1641,21 @@ nsNSSCertificateDB::GetCerts(nsIX509Cert
   *_retval = nssCertList;
   NS_ADDREF(*_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNSSCertificateDB::GetRecentBadCerts(bool isPrivate, nsIRecentBadCerts** result)
 {
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown()) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
   MutexAutoLock lock(mBadCertsLock);
   if (isPrivate) {
     if (!mPrivateRecentBadCerts) {
       mPrivateRecentBadCerts = new nsRecentBadCerts;
     }
     NS_ADDREF(*result = mPrivateRecentBadCerts);
   } else {
     if (!mPublicRecentBadCerts) {
--- a/security/manager/ssl/src/nsNSSCertificateDB.h
+++ b/security/manager/ssl/src/nsNSSCertificateDB.h
@@ -2,64 +2,78 @@
  * 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 __NSNSSCERTIFICATEDB_H__
 #define __NSNSSCERTIFICATEDB_H__
 
 #include "nsIX509CertDB.h"
 #include "nsIX509CertDB2.h"
+#include "nsNSSShutDown.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Mutex.h"
 #include "certt.h"
 
 class nsCString;
 class nsIArray;
 class nsRecentBadCerts;
 
-class nsNSSCertificateDB : public nsIX509CertDB, public nsIX509CertDB2
+class nsNSSCertificateDB : public nsIX509CertDB
+                         , public nsIX509CertDB2
+                         , public nsNSSShutDownObject
+
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIX509CERTDB
   NS_DECL_NSIX509CERTDB2
 
   nsNSSCertificateDB(); 
   virtual ~nsNSSCertificateDB();
 
   // Use this function to generate a default nickname for a user
   // certificate that is to be imported onto a token.
   static void
   get_default_nickname(CERTCertificate *cert, nsIInterfaceRequestor* ctx,
-                       nsCString &nickname);
+                       nsCString &nickname,
+                       const nsNSSShutDownPreventionLock &proofOfLock);
 
   static nsresult 
-  ImportValidCACerts(int numCACerts, SECItem *CACerts, nsIInterfaceRequestor *ctx);
+  ImportValidCACerts(int numCACerts, SECItem *CACerts, nsIInterfaceRequestor *ctx,
+                     const nsNSSShutDownPreventionLock &proofOfLock);
 
 private:
 
   static nsresult
-  ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx);
+  ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx,
+                           const nsNSSShutDownPreventionLock &proofOfLock);
 
   static void DisplayCertificateAlert(nsIInterfaceRequestor *ctx, 
-                                      const char *stringID, nsIX509Cert *certToShow);
+                                      const char *stringID, nsIX509Cert *certToShow,
+                                      const nsNSSShutDownPreventionLock &proofOfLock);
 
   void getCertNames(CERTCertList *certList,
                     uint32_t      type, 
                     uint32_t     *_count,
-                    PRUnichar  ***_certNameList);
+                    PRUnichar  ***_certNameList,
+                    const nsNSSShutDownPreventionLock &proofOfLock);
 
   CERTDERCerts *getCertsFromPackage(PLArenaPool *arena, uint8_t *data, 
-                                    uint32_t length);
+                                    uint32_t length,
+                                    const nsNSSShutDownPreventionLock &proofOfLock);
   nsresult handleCACertDownload(nsIArray *x509Certs, 
-                                nsIInterfaceRequestor *ctx);
+                                nsIInterfaceRequestor *ctx,
+                                const nsNSSShutDownPreventionLock &proofOfLock);
 
   mozilla::Mutex mBadCertsLock;
   mozilla::RefPtr<nsRecentBadCerts> mPublicRecentBadCerts;
   mozilla::RefPtr<nsRecentBadCerts> mPrivateRecentBadCerts;
+
+  // We don't own any NSS objects here, so no need to clean up
+  virtual void virtualDestroyNSSReference() { };
 };
 
 #define NS_X509CERTDB_CID { /* fb0bbc5c-452e-4783-b32c-80124693d871 */ \
     0xfb0bbc5c,                                                        \
     0x452e,                                                            \
     0x4783,                                                            \
     {0xb3, 0x2c, 0x80, 0x12, 0x46, 0x93, 0xd8, 0x71}                   \
   }
--- a/testing/marionette/marionette-server.js
+++ b/testing/marionette/marionette-server.js
@@ -2176,17 +2176,17 @@ MarionetteServerConnection.prototype = {
       case "Marionette:register":
         // This code processes the content listener's registration information
         // and either accepts the listener, or ignores it
         let nullPrevious = (this.curBrowser.curFrameId == null);
         let listenerWindow = 
                             Services.wm.getOuterWindowWithId(message.json.value);
 
         //go in here if we're already in a remote frame.
-        if (!listenerWindow || (listenerWindow.location.href != message.json.href) &&
+        if ((!listenerWindow || listenerWindow.location.href != message.json.href) &&
             (this.curBrowser.frameManager.currentRemoteFrame !== null)) {
           // The outerWindowID from an OOP frame will not be meaningful to
           // the parent process here, since each process maintains its own
           // independent window list.  So, it will either be null (!listenerWindow)
           // if we're already in a remote frame,
           // or it will point to some random window, which will hopefully 
           // cause an href mismatch.  Currently this only happens
           // in B2G for OOP frames registered in Marionette:switchToFrame, so
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -84,17 +84,17 @@ STATIC_LIBS += \
 ifdef MOZ_CONTENT_SANDBOX #{
 STATIC_LIBS += sandbox_s
 endif #}
 
 ifdef MOZ_B2G_RIL #{
 STATIC_LIBS += mozril_s
 endif #}
 
-ifdef MOZ_B2G_BT_BLUEZ #{
+ifdef MOZ_B2G_BT #{
 STATIC_LIBS += mozdbus_s
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 OS_LIBS += -ldbus
 endif
 endif #}
 
 ifneq ($(strip $(MOZ_B2G_RIL)$(MOZ_B2G_BT)),) #{
 STATIC_LIBS += mozipcunixsocket_s mozkeystore_s
--- a/widget/gtk/nsColorPicker.cpp
+++ b/widget/gtk/nsColorPicker.cpp
@@ -66,19 +66,21 @@ NS_IMETHODIMP nsColorPicker::Open(nsICol
     return NS_ERROR_FAILURE;
   }
   mCallback = aColorPickerShownCallback;
 
   nsXPIDLCString title;
   title.Adopt(ToNewUTF8String(mTitle));
   GtkWidget *color_chooser = gtk_color_selection_dialog_new(title);
 
+  GtkWindow *window = GTK_WINDOW(color_chooser);
+  gtk_window_set_modal(window, TRUE);
+
   GtkWindow *parent_window = GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET));
   if (parent_window) {
-    GtkWindow *window = GTK_WINDOW(color_chooser);
     gtk_window_set_transient_for(window, parent_window);
     gtk_window_set_destroy_with_parent(window, TRUE);
   }
 
   gtk_color_selection_set_current_color(
       GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(
         GTK_COLOR_SELECTION_DIALOG(color_chooser))),
       &mDefaultColor);