Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 30 Oct 2012 18:36:05 -0400
changeset 111918 bed18790882febf4419e5ae3e968e8e137a69452
parent 111887 a5ab93cf9feaaecd2d983536d3c29830ea00c48a (current diff)
parent 111917 553fb59b9ca0a1815b27092a36c1e3114e2ce0a2 (diff)
child 111919 de98ab14e7464e6e4250511415aed4c1e45b319c
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
milestone19.0a1
Merge the last PGO-green inbound changeset to m-c.
dom/system/gonk/TimeSetting.cpp
dom/system/gonk/TimeSetting.h
mfbt/double-conversion/more-architectures.patch
--- a/content/base/src/nsDOMDataChannel.cpp
+++ b/content/base/src/nsDOMDataChannel.cpp
@@ -7,20 +7,20 @@
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG
 #endif
 
 #include "base/basictypes.h"
 #include "prlog.h"
 
 #ifdef PR_LOGGING
-extern PRLogModuleInfo* dataChannelLog;
+extern PRLogModuleInfo* GetDataChannelLog();
 #endif
 #undef LOG
-#define LOG(args) PR_LOG(dataChannelLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetDataChannelLog(), PR_LOG_DEBUG, args)
 
 
 #include "nsDOMDataChannel.h"
 #include "nsIDOMFile.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsIDOMDataChannel.h"
 #include "nsIDOMMessageEvent.h"
 #include "nsDOMClassInfo.h"
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -656,17 +656,18 @@ GK_ATOM(oncompositionupdate, "oncomposit
 GK_ATOM(onconnected, "onconnected")
 GK_ATOM(onconnecting, "onconnecting")
 GK_ATOM(oncontextmenu, "oncontextmenu")
 GK_ATOM(oncopy, "oncopy")
 GK_ATOM(oncut, "oncut")
 GK_ATOM(ondatachange, "ondatachange")
 GK_ATOM(ondataerror, "ondataerror")
 GK_ATOM(ondblclick, "ondblclick")
-GK_ATOM(ondelivered, "ondelivered")
+GK_ATOM(ondeliverysuccess, "ondeliverysuccess")
+GK_ATOM(ondeliveryerror, "ondeliveryerror")
 GK_ATOM(ondevicecreated, "ondevicecreated")
 GK_ATOM(ondevicedisappeared, "ondevicedisappeared")
 GK_ATOM(ondevicefound, "ondevicefound")
 GK_ATOM(ondialing, "ondialing")
 GK_ATOM(ondisabled, "ondisabled")
 GK_ATOM(ondischargingtimechange, "ondischargingtimechange")
 GK_ATOM(ondisconnected, "ondisconnected")
 GK_ATOM(ondisconnecting, "ondisconnecting")
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -70,21 +70,28 @@
 #include "nsObjectFrame.h"
 #include "nsDOMClassInfo.h"
 
 #include "nsWidgetsCID.h"
 #include "nsContentCID.h"
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
+static PRLogModuleInfo*
+GetObjectLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("objlc");
+  return sLog;
+}
 #endif
 
-#define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
-#define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
+#define LOG(args) PR_LOG(GetObjectLog(), PR_LOG_DEBUG, args)
+#define LOG_ENABLED() PR_LOG_TEST(GetObjectLog(), PR_LOG_DEBUG)
 
 static bool
 InActiveDocument(nsIContent *aContent)
 {
   if (!aContent->IsInDoc()) {
     return false;
   }
   nsIDocument *doc = aContent->OwnerDoc();
--- a/content/media/webrtc/MediaEngineWebRTC.cpp
+++ b/content/media/webrtc/MediaEngineWebRTC.cpp
@@ -8,21 +8,28 @@
 
 #if defined(PR_LOG)
 #error "This file must be #included before any IPDL-generated files or other files that #include prlog.h"
 #endif
 
 #include "prlog.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo* GetUserMediaLog = PR_NewLogModule("GetUserMedia");
+static PRLogModuleInfo*
+GetUserMediaLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("GetUserMedia");
+  return sLog;
+}
 #endif
 
 #undef LOG
-#define LOG(args) PR_LOG(GetUserMediaLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetUserMediaLog(), PR_LOG_DEBUG, args)
 
 #include "MediaEngineWebRTC.h"
 #include "ImageContainer.h"
 
 namespace mozilla {
 
 void
 MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >* aVSources)
--- a/content/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -10,18 +10,18 @@
 
 #define SAMPLE_RATE 256000
 #define SAMPLE_FREQUENCY 16000
 #define SAMPLE_LENGTH ((SAMPLE_FREQUENCY*10)/1000)
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
-extern PRLogModuleInfo* gMediaManagerLog;
-#define LOG(msg) PR_LOG(gMediaManagerLog, PR_LOG_DEBUG, msg)
+extern PRLogModuleInfo* GetMediaManagerLog();
+#define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
 #else
 #define LOG(msg)
 #endif
 
 /**
  * Webrtc audio source.
  */
 NS_IMPL_THREADSAFE_ISUPPORTS0(MediaEngineWebRTCAudioSource)
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -5,18 +5,18 @@
 #include "MediaEngineWebRTC.h"
 #include "Layers.h"
 #include "ImageTypes.h"
 #include "ImageContainer.h"
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
-extern PRLogModuleInfo* gMediaManagerLog;
-#define LOG(msg) PR_LOG(gMediaManagerLog, PR_LOG_DEBUG, msg)
+extern PRLogModuleInfo* GetMediaManagerLog();
+#define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
 #else
 #define LOG(msg)
 #endif
 
 /**
  * Webrtc video source.
  */
 NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineWebRTCVideoSource, nsIRunnable)
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -820,20 +820,16 @@ nsDocShell::~nsDocShell()
 #ifdef DEBUG
     // We're counting the number of |nsDocShells| to help find leaks
     --gNumberOfDocShells;
     if (!PR_GetEnv("MOZ_QUIET")) {
         printf("--DOCSHELL %p == %ld [id = %llu]\n", (void*) this,
                gNumberOfDocShells, mHistoryID);
     }
 #endif
-
-    if (mInPrivateBrowsing) {
-        DecreasePrivateDocShellCount();
-    }
 }
 
 nsresult
 nsDocShell::Init()
 {
     nsresult rv = nsDocLoader::Init();
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -4910,16 +4906,22 @@ nsDocShell::Destroy()
     SetTreeOwner(nullptr);
 
     // required to break ref cycle
     mSecurityUI = nullptr;
 
     // Cancel any timers that were set for this docshell; this is needed
     // to break the cycle between us and the timers.
     CancelRefreshURITimers();
+
+    if (mInPrivateBrowsing) {
+        mInPrivateBrowsing = false;
+        DecreasePrivateDocShellCount();
+    }
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
 {
     if (mParentWidget) {
         *aScale = mParentWidget->GetDefaultScale();
--- a/docshell/shistory/src/nsSHistory.cpp
+++ b/docshell/shistory/src/nsSHistory.cpp
@@ -55,28 +55,35 @@ static PRCList gSHistoryList;
 // Max viewers allowed total, across all SHistory objects - negative default
 // means we will calculate how many viewers to cache based on total memory
 int32_t nsSHistory::sHistoryMaxTotalViewers = -1;
 
 // A counter that is used to be able to know the order in which
 // entries were touched, so that we can evict older entries first.
 static uint32_t gTouchCounter = 0;
 
-static PRLogModuleInfo* gLogModule = PR_NewLogModule("nsSHistory");
-#define LOG(format) PR_LOG(gLogModule, PR_LOG_DEBUG, format)
+static PRLogModuleInfo*
+GetSHistoryLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsSHistory");
+  return sLog;
+}
+#define LOG(format) PR_LOG(GetSHistoryLog(), PR_LOG_DEBUG, format)
 
 // This macro makes it easier to print a log message which includes a URI's
 // spec.  Example use:
 //
 //  nsIURI *uri = [...];
 //  LOG_SPEC(("The URI is %s.", _spec), uri);
 //
 #define LOG_SPEC(format, uri)                              \
   PR_BEGIN_MACRO                                           \
-    if (PR_LOG_TEST(gLogModule, PR_LOG_DEBUG)) {           \
+    if (PR_LOG_TEST(GetSHistoryLog(), PR_LOG_DEBUG)) {     \
       nsAutoCString _specStr(NS_LITERAL_CSTRING("(null)"));\
       if (uri) {                                           \
         uri->GetSpec(_specStr);                            \
       }                                                    \
       const char* _spec = _specStr.get();                  \
       LOG(format);                                         \
     }                                                      \
   PR_END_MACRO
@@ -84,17 +91,17 @@ static PRLogModuleInfo* gLogModule = PR_
 // This macro makes it easy to log a message including an SHEntry's URI.
 // For example:
 //
 //  nsCOMPtr<nsISHEntry> shentry = [...];
 //  LOG_SHENTRY_SPEC(("shentry %p has uri %s.", shentry.get(), _spec), shentry);
 //
 #define LOG_SHENTRY_SPEC(format, shentry)                  \
   PR_BEGIN_MACRO                                           \
-    if (PR_LOG_TEST(gLogModule, PR_LOG_DEBUG)) {           \
+    if (PR_LOG_TEST(GetSHistoryLog(), PR_LOG_DEBUG)) {     \
       nsCOMPtr<nsIURI> uri;                                \
       shentry->GetURI(getter_AddRefs(uri));                \
       LOG_SPEC(format, uri);                               \
     }                                                      \
   PR_END_MACRO
 
 // Iterates over all registered session history listeners.
 #define ITERATE_LISTENERS(body)                            \
--- a/dom/camera/CameraCommon.h
+++ b/dom/camera/CameraCommon.h
@@ -19,18 +19,18 @@
 #define NAN std::numeric_limits<double>::quiet_NaN()
 #endif
 
 #include "nsThreadUtils.h"
 #include "nsIDOMCameraManager.h"
 #include "prlog.h"
 
 #ifdef PR_LOGGING
-extern PRLogModuleInfo* gCameraLog;
-#define DOM_CAMERA_LOG( type, ... ) PR_LOG(gCameraLog, (PRLogModuleLevel)type, ( __VA_ARGS__ ))
+extern PRLogModuleInfo* GetCameraLog();
+#define DOM_CAMERA_LOG( type, ... ) PR_LOG(GetCameraLog(), (PRLogModuleLevel)type, ( __VA_ARGS__ ))
 #else
 #define DOM_CAMERA_LOG( type, ... )
 #endif
 
 #define DOM_CAMERA_LOGA( ... )      DOM_CAMERA_LOG( 0, __VA_ARGS__ )
 
 /**
  * From the least to the most output.
@@ -46,17 +46,17 @@ enum {
 
 /**
  * DOM_CAMERA_LOGR() can be called before 'gCameraLog' is set, so
  * we need to handle this one a little differently.
  */
 #ifdef PR_LOGGING
 #define DOM_CAMERA_LOGR( ... )                                  \
   do {                                                          \
-    if (gCameraLog) {                                           \
+    if (GetCameraLog()) {                                       \
       DOM_CAMERA_LOG( DOM_CAMERA_LOG_REFERENCES, __VA_ARGS__ ); \
     }                                                           \
   } while (0)
 #else
 #define DOM_CAMERA_LOGR( ... )
 #endif
 #define DOM_CAMERA_LOGT( ... )      DOM_CAMERA_LOG( DOM_CAMERA_LOG_TRACE, __VA_ARGS__ )
 #define DOM_CAMERA_LOGI( ... )      DOM_CAMERA_LOG( DOM_CAMERA_LOG_INFO, __VA_ARGS__ )
--- a/dom/camera/DOMCameraManager.cpp
+++ b/dom/camera/DOMCameraManager.cpp
@@ -39,17 +39,24 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCam
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCameraManager)
 
 /**
  * Global camera logging object
  *
  * Set the NSPR_LOG_MODULES environment variable to enable logging
  * in a debug build, e.g. NSPR_LOG_MODULES=Camera:5
  */
-PRLogModuleInfo* gCameraLog = PR_NewLogModule("Camera");
+PRLogModuleInfo*
+GetCameraLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("Camera");
+  return sLog;
+}
 
 /**
  * nsDOMCameraManager::GetListOfCameras
  * is implementation-specific, and can be found in (e.g.)
  * GonkCameraManager.cpp and FallbackCameraManager.cpp.
  */
 
 WindowTable nsDOMCameraManager::sActiveWindows;
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -48,19 +48,26 @@ static bool sInitialized = false;
 
 // Enable logging by setting
 //
 //   NSPR_LOG_MODULES=ProcessPriorityManager:5
 //
 // in your environment.
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo* logModule = PR_NewLogModule("ProcessPriorityManager");
+static PRLogModuleInfo*
+GetPPMLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("ProcessPriorityManager");
+  return sLog;
+}
 #define LOG(fmt, ...) \
-  PR_LOG(logModule, PR_LOG_DEBUG, \
+  PR_LOG(GetPPMLog(), PR_LOG_DEBUG,                                     \
          ("[%d] ProcessPriorityManager - " fmt, getpid(), ##__VA_ARGS__))
 #else
 #define LOG(fmt, ...)
 #endif
 
 /**
  * This class listens to window creation and visibilitychange events and
  * informs the hal back-end when this process transitions between having no
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -24,18 +24,25 @@
 #include "MediaEngineDefault.h"
 #if defined(MOZ_WEBRTC)
 #include "MediaEngineWebRTC.h"
 #endif
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
-PRLogModuleInfo* gMediaManagerLog = PR_NewLogModule("MediaManager");
-#define LOG(msg) PR_LOG(gMediaManagerLog, PR_LOG_DEBUG, msg)
+PRLogModuleInfo*
+GetMediaManagerLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("MediaManager");
+  return sLog;
+}
+#define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
 #else
 #define LOG(msg)
 #endif
 
 
 /**
  * Send an error back to content. The error is the form a string.
  * Do this only on the main thread. The success callback is also passed here
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -14,18 +14,18 @@
 #include "nsPIDOMWindow.h"
 #include "nsIDOMNavigatorUserMedia.h"
 #include "mozilla/Attributes.h"
 #include "prlog.h"
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
-extern PRLogModuleInfo* gMediaManagerLog;
-#define MM_LOG(msg) PR_LOG(gMediaManagerLog, PR_LOG_DEBUG, msg)
+extern PRLogModuleInfo* GetMediaManagerLog();
+#define MM_LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
 #else
 #define MM_LOG(msg)
 #endif
 
 // We only support 1 audio and 1 video track for now.
 enum {
   kVideoTrack = 1,
   kAudioTrack = 2
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -449,17 +449,17 @@ PluginInstanceChild::NPN_GetValue(NPNVar
     case NPNVasdEnabledBool:
     case NPNVisOfflineBool:
     case NPNVSupportsXEmbedBool:
     case NPNVSupportsWindowless:
         NS_NOTREACHED("NPNVariable should be handled in PluginModuleChild.");
 #endif
 
     default:
-        PR_LOG(gPluginLog, PR_LOG_WARNING,
+        PR_LOG(GetPluginLog(), PR_LOG_WARNING,
                ("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)",
                 (int) aVar, NPNVariableToString(aVar)));
         return NPERR_GENERIC_ERROR;
     }
 
 }
 
 #ifdef MOZ_WIDGET_COCOA
@@ -478,17 +478,17 @@ PluginInstanceChild::Invalidate()
 
     InvalidateRect(&windowRect);
 }
 #endif
 
 NPError
 PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
 {
-    PR_LOG(gPluginLog, PR_LOG_DEBUG, ("%s (aVar=%i, aValue=%p)",
+    PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s (aVar=%i, aValue=%p)",
                                       FULLFUNCTION, (int) aVar, aValue));
 
     AssertPluginThread();
 
     switch (aVar) {
     case NPPVpluginWindowBool: {
         NPError rv;
         bool windowed = (NPBool) (intptr_t) aValue;
@@ -582,17 +582,17 @@ PluginInstanceChild::NPN_SetValue(NPPVar
         PLUGIN_LOG_DEBUG(("  Plugin requested event model id # %i\n",
             eventModel));
 
         return rv;
     }
 #endif
 
     default:
-        PR_LOG(gPluginLog, PR_LOG_WARNING,
+        PR_LOG(GetPluginLog(), PR_LOG_WARNING,
                ("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)",
                 (int) aVar, NPPVariableToString(aVar)));
         return NPERR_GENERIC_ERROR;
     }
 }
 
 bool
 PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(
@@ -2170,17 +2170,17 @@ PluginInstanceChild::FlashThrottleMessag
         task, kFlashWMUSERMessageThrottleDelayMs);
 }
 
 #endif // OS_WIN
 
 bool
 PluginInstanceChild::AnswerSetPluginFocus()
 {
-    PR_LOG(gPluginLog, PR_LOG_DEBUG, ("%s", FULLFUNCTION));
+    PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s", FULLFUNCTION));
 
 #if defined(OS_WIN)
     // Parent is letting us know the dom set focus to the plugin. Note,
     // focus can change during transit in certain edge cases, for example
     // when a button click brings up a full screen window. Since we send
     // this in response to a WM_SETFOCUS event on our parent, the parent
     // should have focus when we receive this. If not, ignore the call.
     if (::GetFocus() == mPluginWindowHWND ||
@@ -2193,17 +2193,17 @@ PluginInstanceChild::AnswerSetPluginFocu
     NS_NOTREACHED("PluginInstanceChild::AnswerSetPluginFocus not implemented!");
     return false;
 #endif
 }
 
 bool
 PluginInstanceChild::AnswerUpdateWindow()
 {
-    PR_LOG(gPluginLog, PR_LOG_DEBUG, ("%s", FULLFUNCTION));
+    PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s", FULLFUNCTION));
 
 #if defined(OS_WIN)
     if (mPluginWindowHWND) {
         RECT rect;
         if (GetUpdateRect(GetParent(mPluginWindowHWND), &rect, FALSE)) {
             ::InvalidateRect(mPluginWindowHWND, &rect, FALSE); 
         }
         UpdateWindow(mPluginWindowHWND);
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -1142,17 +1142,17 @@ PluginInstanceParent::NPP_GetValue(NPPVa
         }
 
         (*(nsCString*)_retval) = plugId;
         return NPERR_NO_ERROR;
     }
 #endif
 
     default:
-        PR_LOG(gPluginLog, PR_LOG_WARNING,
+        PR_LOG(GetPluginLog(), PR_LOG_WARNING,
                ("In PluginInstanceParent::NPP_GetValue: Unhandled NPPVariable %i (%s)",
                 (int) aVariable, NPPVariableToString(aVariable)));
         return NPERR_GENERIC_ERROR;
     }
 }
 
 NPError
 PluginInstanceParent::NPP_SetValue(NPNVariable variable, void* value)
@@ -1163,17 +1163,17 @@ PluginInstanceParent::NPP_SetValue(NPNVa
         if (!CallNPP_SetValue_NPNVprivateModeBool(*static_cast<NPBool*>(value),
                                                   &result))
             return NPERR_GENERIC_ERROR;
 
         return result;
 
     default:
         NS_ERROR("Unhandled NPNVariable in NPP_SetValue");
-        PR_LOG(gPluginLog, PR_LOG_WARNING,
+        PR_LOG(GetPluginLog(), PR_LOG_WARNING,
                ("In PluginInstanceParent::NPP_SetValue: Unhandled NPNVariable %i (%s)",
                 (int) variable, NPNVariableToString(variable)));
         return NPERR_GENERIC_ERROR;
     }
 }
 
 void
 PluginInstanceParent::NPP_URLRedirectNotify(const char* url, int32_t status,
--- a/dom/plugins/ipc/PluginMessageUtils.cpp
+++ b/dom/plugins/ipc/PluginMessageUtils.cpp
@@ -118,17 +118,24 @@ UnmungePluginDsoPath(const string& munge
 #if defined(OS_LINUX)
   return ReplaceAll(munged, "netsc@pe", "netscape");
 #else
   return munged;
 #endif
 }
 
 
-PRLogModuleInfo* gPluginLog = PR_NewLogModule("IPCPlugins");
+PRLogModuleInfo*
+GetPluginLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("IPCPlugins");
+  return sLog;
+}
 
 void
 DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o)
 {
   if (!o)
     return;
 
   if (o->referenceCount > 1) {
--- a/dom/plugins/ipc/PluginMessageUtils.h
+++ b/dom/plugins/ipc/PluginMessageUtils.h
@@ -48,17 +48,17 @@ mozilla::ipc::RPCChannel::RacyRPCPolicy
 MediateRace(const mozilla::ipc::RPCChannel::Message& parent,
             const mozilla::ipc::RPCChannel::Message& child);
 
 std::string
 MungePluginDsoPath(const std::string& path);
 std::string
 UnmungePluginDsoPath(const std::string& munged);
 
-extern PRLogModuleInfo* gPluginLog;
+extern PRLogModuleInfo* GetPluginLog();
 
 const uint32_t kAllowAsyncDrawing = 0x1;
 
 inline bool IsDrawingModelAsync(int16_t aModel) {
   return aModel == NPDrawingModelAsyncBitmapSurface
 #ifdef XP_WIN
          || aModel == NPDrawingModelAsyncWindowsDXGISurface
 #endif
@@ -68,19 +68,19 @@ inline bool IsDrawingModelAsync(int16_t 
 #if defined(_MSC_VER)
 #define FULLFUNCTION __FUNCSIG__
 #elif (__GNUC__ >= 4)
 #define FULLFUNCTION __PRETTY_FUNCTION__
 #else
 #define FULLFUNCTION __FUNCTION__
 #endif
 
-#define PLUGIN_LOG_DEBUG(args) PR_LOG(gPluginLog, PR_LOG_DEBUG, args)
-#define PLUGIN_LOG_DEBUG_FUNCTION PR_LOG(gPluginLog, PR_LOG_DEBUG, ("%s", FULLFUNCTION))
-#define PLUGIN_LOG_DEBUG_METHOD PR_LOG(gPluginLog, PR_LOG_DEBUG, ("%s [%p]", FULLFUNCTION, (void*) this))
+#define PLUGIN_LOG_DEBUG(args) PR_LOG(GetPluginLog(), PR_LOG_DEBUG, args)
+#define PLUGIN_LOG_DEBUG_FUNCTION PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s", FULLFUNCTION))
+#define PLUGIN_LOG_DEBUG_METHOD PR_LOG(GetPluginLog(), PR_LOG_DEBUG, ("%s [%p]", FULLFUNCTION, (void*) this))
 
 /**
  * This is NPByteRange without the linked list.
  */
 struct IPCByteRange
 {
   int32_t offset;
   uint32_t length;
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -1049,17 +1049,17 @@ PluginModuleParent::NP_GetMIMEDescriptio
     *mimeDesc = "application/x-foobar";
     return NS_OK;
 }
 
 nsresult
 PluginModuleParent::NP_GetValue(void *future, NPPVariable aVariable,
                                    void *aValue, NPError* error)
 {
-    PR_LOG(gPluginLog, PR_LOG_WARNING, ("%s Not implemented, requested variable %i", __FUNCTION__,
+    PR_LOG(GetPluginLog(), PR_LOG_WARNING, ("%s Not implemented, requested variable %i", __FUNCTION__,
                                         (int) aVariable));
 
     //TODO: implement this correctly
     *error = NPERR_GENERIC_ERROR;
     return NS_OK;
 }
 
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2)
--- a/dom/sms/interfaces/nsIDOMSmsManager.idl
+++ b/dom/sms/interfaces/nsIDOMSmsManager.idl
@@ -3,17 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMEventListener;
 interface nsIDOMMozSmsRequest;
 interface nsIDOMMozSmsFilter;
 
-[scriptable, builtinclass, uuid(be78baf4-20ba-4ceb-be40-d9774a9388c4)]
+[scriptable, builtinclass, uuid(1bee1224-56a2-4935-af7b-0011746306cb)]
 interface nsIDOMMozSmsManager : nsIDOMEventTarget
 {
   unsigned short      getNumberOfMessagesForText(in DOMString text);
 
   // The first parameter can be either a DOMString (only one number) or an array
   // of DOMStrings.
   // The method returns a SmsRequest object if one number has been passed.
   // An array of SmsRequest objects otherwise.
@@ -25,10 +25,11 @@ interface nsIDOMMozSmsManager : nsIDOMEv
   nsIDOMMozSmsRequest delete(in jsval param);
 
   nsIDOMMozSmsRequest getMessages(in nsIDOMMozSmsFilter filter, in boolean reverse);
 
   nsIDOMMozSmsRequest markMessageRead(in long id, in boolean aValue);
 
   [implicit_jscontext] attribute jsval onreceived;
   [implicit_jscontext] attribute jsval onsent;
-  [implicit_jscontext] attribute jsval ondelivered;
+  [implicit_jscontext] attribute jsval ondeliverysuccess;
+  [implicit_jscontext] attribute jsval ondeliveryerror;
 };
--- a/dom/sms/interfaces/nsIDOMSmsMessage.idl
+++ b/dom/sms/interfaces/nsIDOMSmsMessage.idl
@@ -1,20 +1,26 @@
 /* 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"
 
-[scriptable, builtinclass, uuid(fc58ba6e-70de-4550-aa1e-790ecc19cf98)]
+[scriptable, builtinclass, uuid(5e3224dd-1ca3-43e6-861e-b7734656fd2f)]
 interface nsIDOMMozSmsMessage : nsISupports
 {
   // TODO: we should add SENT and RECEIVED DOMString constants, see bug 443316.
 
   readonly attribute long      id;
   readonly attribute DOMString delivery;  // Should be "sent" or "received".
+  /**
+   * For received messages, it is "success"; for sent messages, it can be
+   * "pending", "success", "error", or "not-applicable" if the message was sent
+   * without status report requisition.
+   */
+  readonly attribute DOMString deliveryStatus;
   readonly attribute DOMString sender;
   readonly attribute DOMString receiver;
   readonly attribute DOMString body;
   [implicit_jscontext]
   readonly attribute jsval     timestamp; // jsval is for Date.
   readonly attribute boolean   read;
 };
--- a/dom/sms/interfaces/nsISmsDatabaseService.idl
+++ b/dom/sms/interfaces/nsISmsDatabaseService.idl
@@ -8,23 +8,24 @@
 #define SMS_DATABASE_SERVICE_CID \
 { 0x2454c2a1, 0xefdd, 0x4d96,    \
 { 0x83, 0xbd, 0x51, 0xa2, 0x9a, 0x21, 0xf5, 0xab } }
 #define SMS_DATABASE_SERVICE_CONTRACTID "@mozilla.org/sms/smsdatabaseservice;1"
 %}
 
 interface nsIDOMMozSmsFilter;
 
-[scriptable, uuid(30e8cdfb-155d-44c7-8fb3-6bcd9c1c3f99)]
+[scriptable, uuid(d6318c22-1ebd-4262-b991-432f61a96237)]
 interface nsISmsDatabaseService : nsISupports
 {
   // Takes some information required to save the message and returns its id.
   long saveReceivedMessage(in DOMString aSender, in DOMString aBody, in unsigned long long aDate);
   // Takes some information required to save the message and returns its id.
   long saveSentMessage(in DOMString aReceiver, in DOMString aBody, in unsigned long long aDate);
+  void setMessageDeliveryStatus(in long aMessageId, in DOMString aDeliveryStatus);
 
   [binaryname(GetMessageMoz)] void getMessage(in long messageId, in long requestId, [optional] in unsigned long long processId);
   void deleteMessage(in long messageId, in long requestId, [optional] in unsigned long long processId);
 
   void createMessageList(in nsIDOMMozSmsFilter filter, in boolean reverse, in long requestId, [optional] in unsigned long long processId);
   void getNextMessageInList(in long listId, in long requestId, [optional] in unsigned long long processId);
   void clearMessageList(in long listId);
   void markMessageRead(in long messageId, in boolean value, in long requestId, [optional] in unsigned long long processId);
--- a/dom/sms/interfaces/nsISmsService.idl
+++ b/dom/sms/interfaces/nsISmsService.idl
@@ -6,25 +6,26 @@
 
 interface nsIDOMMozSmsMessage;
 
 %{C++
 #define SMS_SERVICE_CID { 0xbada3cb8, 0xa568, 0x4dff, { 0xb5, 0x43, 0x52, 0xbb, 0xb3, 0x14, 0x31, 0x21 } }
 #define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
 %}
 
-[scriptable, builtinclass, uuid(00d23a50-6ed1-48b4-b1e9-5987b155e54b)]
+[scriptable, builtinclass, uuid(a1367149-c09f-4e8c-a890-5812406bed61)]
 interface nsISmsService : nsISupports
 {
   boolean        hasSupport();
   unsigned short getNumberOfMessagesForText(in DOMString text);
             void send(in DOMString number, in DOMString message,
                       in long requestId, [optional] in unsigned long long processId);
 
   [implicit_jscontext]
   nsIDOMMozSmsMessage createSmsMessage(in long      id,
                                        in DOMString delivery,
+                                       in DOMString deliveryStatus,
                                        in DOMString sender,
                                        in DOMString receiver,
                                        in DOMString body,
                                        in jsval     timestamp,
                                        in bool      read);
 };
--- a/dom/sms/src/Constants.cpp
+++ b/dom/sms/src/Constants.cpp
@@ -2,15 +2,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
-const char* kSmsReceivedObserverTopic  = "sms-received";
-const char* kSmsSentObserverTopic      = "sms-sent";
-const char* kSmsDeliveredObserverTopic = "sms-delivered";
+const char* kSmsReceivedObserverTopic        = "sms-received";
+const char* kSmsSentObserverTopic            = "sms-sent";
+const char* kSmsDeliverySuccessObserverTopic = "sms-delivery-success";
+const char* kSmsDeliveryErrorObserverTopic   = "sms-delivery-error";
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/Constants.h
+++ b/dom/sms/src/Constants.h
@@ -5,20 +5,26 @@
 
 #ifndef mozilla_dom_sms_Constants_h
 #define mozilla_dom_sms_Constants_h
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
-extern const char* kSmsReceivedObserverTopic;  // Defined in the .cpp.
-extern const char* kSmsSentObserverTopic;      // Defined in the .cpp.
-extern const char* kSmsDeliveredObserverTopic; // Defined in the .cpp.
+extern const char* kSmsReceivedObserverTopic;        // Defined in the .cpp.
+extern const char* kSmsSentObserverTopic;            // Defined in the .cpp.
+extern const char* kSmsDeliverySuccessObserverTopic; // Defined in the .cpp.
+extern const char* kSmsDeliveryErrorObserverTopic;   // Defined in the .cpp.
 
 #define DELIVERY_RECEIVED NS_LITERAL_STRING("received")
 #define DELIVERY_SENT     NS_LITERAL_STRING("sent")
 
+#define DELIVERY_STATUS_NOT_APPLICABLE NS_LITERAL_STRING("not-applicable")
+#define DELIVERY_STATUS_SUCCESS        NS_LITERAL_STRING("success")
+#define DELIVERY_STATUS_PENDING        NS_LITERAL_STRING("pending")
+#define DELIVERY_STATUS_ERROR          NS_LITERAL_STRING("error")
+
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_sms_Constants_h
--- a/dom/sms/src/SmsManager.cpp
+++ b/dom/sms/src/SmsManager.cpp
@@ -20,19 +20,20 @@
 #include "nsISmsDatabaseService.h"
 #include "nsIXPConnect.h"
 #include "nsIPermissionManager.h"
 
 /**
  * We have to use macros here because our leak analysis tool things we are
  * leaking strings when we have |static const nsString|. Sad :(
  */
-#define RECEIVED_EVENT_NAME  NS_LITERAL_STRING("received")
-#define SENT_EVENT_NAME      NS_LITERAL_STRING("sent")
-#define DELIVERED_EVENT_NAME NS_LITERAL_STRING("delivered")
+#define RECEIVED_EVENT_NAME         NS_LITERAL_STRING("received")
+#define SENT_EVENT_NAME             NS_LITERAL_STRING("sent")
+#define DELIVERY_SUCCESS_EVENT_NAME NS_LITERAL_STRING("deliverysuccess")
+#define DELIVERY_ERROR_EVENT_NAME   NS_LITERAL_STRING("deliveryerror")
 
 DOMCI_DATA(MozSmsManager, mozilla::dom::sms::SmsManager)
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(SmsManager)
@@ -52,17 +53,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozSmsManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(SmsManager, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SmsManager, nsDOMEventTargetHelper)
 
 NS_IMPL_EVENT_HANDLER(SmsManager, received)
 NS_IMPL_EVENT_HANDLER(SmsManager, sent)
-NS_IMPL_EVENT_HANDLER(SmsManager, delivered)
+NS_IMPL_EVENT_HANDLER(SmsManager, deliverysuccess)
+NS_IMPL_EVENT_HANDLER(SmsManager, deliveryerror)
 
 /* static */already_AddRefed<SmsManager>
 SmsManager::CreateInstanceIfAllowed(nsPIDOMWindow* aWindow)
 {
   NS_ASSERTION(aWindow, "Null pointer!");
 
 #ifndef MOZ_WEBSMS_BACKEND
   return nullptr;
@@ -108,31 +110,33 @@ SmsManager::Init(nsPIDOMWindow *aWindow)
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   // GetObserverService() can return null is some situations like shutdown.
   if (!obs) {
     return;
   }
 
   obs->AddObserver(this, kSmsReceivedObserverTopic, false);
   obs->AddObserver(this, kSmsSentObserverTopic, false);
-  obs->AddObserver(this, kSmsDeliveredObserverTopic, false);
+  obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
+  obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
 }
 
 void
 SmsManager::Shutdown()
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   // GetObserverService() can return null is some situations like shutdown.
   if (!obs) {
     return;
   }
 
   obs->RemoveObserver(this, kSmsReceivedObserverTopic);
   obs->RemoveObserver(this, kSmsSentObserverTopic);
-  obs->RemoveObserver(this, kSmsDeliveredObserverTopic);
+  obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
+  obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
 }
 
 NS_IMETHODIMP
 SmsManager::GetNumberOfMessagesForText(const nsAString& aText, uint16_t* aResult)
 {
   nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsService, NS_OK);
 
@@ -376,24 +380,35 @@ SmsManager::Observe(nsISupports* aSubjec
       NS_ERROR("Got a 'sms-sent' topic without a valid message!");
       return NS_OK;
     }
 
     DispatchTrustedSmsEventToSelf(SENT_EVENT_NAME, message);
     return NS_OK;
   }
 
-  if (!strcmp(aTopic, kSmsDeliveredObserverTopic)) {
+  if (!strcmp(aTopic, kSmsDeliverySuccessObserverTopic)) {
     nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
     if (!message) {
-      NS_ERROR("Got a 'sms-delivered' topic without a valid message!");
+      NS_ERROR("Got a 'sms-delivery-success' topic without a valid message!");
       return NS_OK;
     }
 
-    DispatchTrustedSmsEventToSelf(DELIVERED_EVENT_NAME, message);
+    DispatchTrustedSmsEventToSelf(DELIVERY_SUCCESS_EVENT_NAME, message);
+    return NS_OK;
+  }
+
+  if (!strcmp(aTopic, kSmsDeliveryErrorObserverTopic)) {
+    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
+    if (!message) {
+      NS_ERROR("Got a 'sms-delivery-error' topic without a valid message!");
+      return NS_OK;
+    }
+
+    DispatchTrustedSmsEventToSelf(DELIVERY_ERROR_EVENT_NAME, message);
     return NS_OK;
   }
 
   return NS_OK;
 }
 
 } // namespace sms
 } // namespace dom
--- a/dom/sms/src/SmsMessage.cpp
+++ b/dom/sms/src/SmsMessage.cpp
@@ -19,31 +19,38 @@ NS_INTERFACE_MAP_BEGIN(SmsMessage)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozSmsMessage)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozSmsMessage)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(SmsMessage)
 NS_IMPL_RELEASE(SmsMessage)
 
-SmsMessage::SmsMessage(int32_t aId, DeliveryState aDelivery,
-                       const nsString& aSender, const nsString& aReceiver,
-                       const nsString& aBody, uint64_t aTimestamp, bool aRead)
-  : mData(aId, aDelivery, aSender, aReceiver, aBody, aTimestamp, aRead)
+SmsMessage::SmsMessage(int32_t aId,
+                       DeliveryState aDelivery,
+                       DeliveryStatus aDeliveryStatus,
+                       const nsString& aSender,
+                       const nsString& aReceiver,
+                       const nsString& aBody,
+                       uint64_t aTimestamp,
+                       bool aRead)
+  : mData(aId, aDelivery, aDeliveryStatus, aSender, aReceiver, aBody,
+          aTimestamp, aRead)
 {
 }
 
 SmsMessage::SmsMessage(const SmsMessageData& aData)
   : mData(aData)
 {
 }
 
 /* static */ nsresult
 SmsMessage::Create(int32_t aId,
                    const nsAString& aDelivery,
+                   const nsAString& aDeliveryStatus,
                    const nsAString& aSender,
                    const nsAString& aReceiver,
                    const nsAString& aBody,
                    const jsval& aTimestamp,
                    const bool aRead,
                    JSContext* aCx,
                    nsIDOMMozSmsMessage** aMessage)
 {
@@ -61,16 +68,28 @@ SmsMessage::Create(int32_t aId,
   if (aDelivery.Equals(DELIVERY_RECEIVED)) {
     data.delivery() = eDeliveryState_Received;
   } else if (aDelivery.Equals(DELIVERY_SENT)) {
     data.delivery() = eDeliveryState_Sent;
   } else {
     return NS_ERROR_INVALID_ARG;
   }
 
+  if (aDeliveryStatus.Equals(DELIVERY_STATUS_NOT_APPLICABLE)) {
+    data.deliveryStatus() = eDeliveryStatus_NotApplicable;
+  } else if (aDeliveryStatus.Equals(DELIVERY_STATUS_SUCCESS)) {
+    data.deliveryStatus() = eDeliveryStatus_Success;
+  } else if (aDeliveryStatus.Equals(DELIVERY_STATUS_PENDING)) {
+    data.deliveryStatus() = eDeliveryStatus_Pending;
+  } else if (aDeliveryStatus.Equals(DELIVERY_STATUS_ERROR)) {
+    data.deliveryStatus() = eDeliveryStatus_Error;
+  } else {
+    return NS_ERROR_INVALID_ARG;
+  }
+
   // We support both a Date object and a millisecond timestamp as a number.
   if (aTimestamp.isObject()) {
     JSObject& obj = aTimestamp.toObject();
     if (!JS_ObjectIsDate(aCx, &obj)) {
       return NS_ERROR_INVALID_ARG;
     }
     data.timestamp() = js_DateGetMsecSinceEpoch(&obj);
   } else {
@@ -110,17 +129,42 @@ SmsMessage::GetDelivery(nsAString& aDeli
       aDelivery = DELIVERY_RECEIVED;
       break;
     case eDeliveryState_Sent:
       aDelivery = DELIVERY_SENT;
       break;
     case eDeliveryState_Unknown:
     case eDeliveryState_EndGuard:
     default:
-      NS_ASSERTION(true, "We shouldn't get any other delivery state!");
+      MOZ_NOT_REACHED("We shouldn't get any other delivery state!");
+      return NS_ERROR_UNEXPECTED;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+SmsMessage::GetDeliveryStatus(nsAString& aDeliveryStatus)
+{
+  switch (mData.deliveryStatus()) {
+    case eDeliveryStatus_NotApplicable:
+      aDeliveryStatus = DELIVERY_STATUS_NOT_APPLICABLE;
+      break;
+    case eDeliveryStatus_Success:
+      aDeliveryStatus = DELIVERY_STATUS_SUCCESS;
+      break;
+    case eDeliveryStatus_Pending:
+      aDeliveryStatus = DELIVERY_STATUS_PENDING;
+      break;
+    case eDeliveryStatus_Error:
+      aDeliveryStatus = DELIVERY_STATUS_ERROR;
+      break;
+    case eDeliveryStatus_EndGuard:
+    default:
+      MOZ_NOT_REACHED("We shouldn't get any other delivery status!");
       return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsMessage::GetSender(nsAString& aSender)
--- a/dom/sms/src/SmsMessage.h
+++ b/dom/sms/src/SmsMessage.h
@@ -18,23 +18,29 @@ namespace dom {
 namespace sms {
 
 class SmsMessage MOZ_FINAL : public nsIDOMMozSmsMessage
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMOZSMSMESSAGE
 
-  SmsMessage(int32_t aId, DeliveryState aDelivery, const nsString& aSender,
-             const nsString& aReceiver, const nsString& aBody,
-             uint64_t aTimestamp, bool aRead);
+  SmsMessage(int32_t aId,
+             DeliveryState aDelivery,
+             DeliveryStatus aDeliveryStatus,
+             const nsString& aSender,
+             const nsString& aReceiver,
+             const nsString& aBody,
+             uint64_t aTimestamp,
+             bool aRead);
   SmsMessage(const SmsMessageData& aData);
 
   static nsresult Create(int32_t aId,
                          const nsAString& aDelivery,
+                         const nsAString& aDeliveryStatus,
                          const nsAString& aSender,
                          const nsAString& aReceiver,
                          const nsAString& aBody,
                          const JS::Value& aTimestamp,
                          const bool aRead,
                          JSContext* aCx,
                          nsIDOMMozSmsMessage** aMessage);
   const SmsMessageData& GetData() const;
--- a/dom/sms/src/Types.h
+++ b/dom/sms/src/Types.h
@@ -18,16 +18,26 @@ namespace sms {
 enum DeliveryState {
   eDeliveryState_Sent = 0,
   eDeliveryState_Received,
   eDeliveryState_Unknown,
   // This state should stay at the end.
   eDeliveryState_EndGuard
 };
 
+// For SmsMessageData.deliveryStatus.
+enum DeliveryStatus {
+  eDeliveryStatus_NotApplicable = 0,
+  eDeliveryStatus_Success,
+  eDeliveryStatus_Pending,
+  eDeliveryStatus_Error,
+  // This state should stay at the end.
+  eDeliveryStatus_EndGuard
+};
+
 // For SmsFilterData.read
 enum ReadState {
   eReadState_Unknown = -1,
   eReadState_Unread,
   eReadState_Read,
   // This state should stay at the end.
   eReadState_EndGuard
 };
@@ -44,16 +54,26 @@ namespace IPC {
 template <>
 struct ParamTraits<mozilla::dom::sms::DeliveryState>
   : public EnumSerializer<mozilla::dom::sms::DeliveryState,
                           mozilla::dom::sms::eDeliveryState_Sent,
                           mozilla::dom::sms::eDeliveryState_EndGuard>
 {};
 
 /**
+ * Delivery status serializer.
+ */
+template <>
+struct ParamTraits<mozilla::dom::sms::DeliveryStatus>
+  : public EnumSerializer<mozilla::dom::sms::DeliveryStatus,
+                          mozilla::dom::sms::eDeliveryStatus_NotApplicable,
+                          mozilla::dom::sms::eDeliveryStatus_EndGuard>
+{};
+
+/**
  * Read state serializer.
  */
 template <>
 struct ParamTraits<mozilla::dom::sms::ReadState>
   : public EnumSerializer<mozilla::dom::sms::ReadState,
                           mozilla::dom::sms::eReadState_Unknown,
                           mozilla::dom::sms::eReadState_EndGuard>
 {};
--- a/dom/sms/src/android/SmsDatabaseService.cpp
+++ b/dom/sms/src/android/SmsDatabaseService.cpp
@@ -34,16 +34,24 @@ SmsDatabaseService::SaveSentMessage(cons
     return NS_OK;
   }
 
   *aId = AndroidBridge::Bridge()->SaveSentMessage(aReceiver, aBody, aDate);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+SmsDatabaseService::SetMessageDeliveryStatus(int32_t aMessageId,
+                                             const nsAString& aDeliveryStatus)
+{
+  // TODO: Bug 803828: update delivery status for sent messages in Android.
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 SmsDatabaseService::GetMessageMoz(int32_t aMessageId, int32_t aRequestId,
                                   uint64_t aProcessId)
 {
   if (!AndroidBridge::Bridge()) {
     return NS_OK;
   }
 
   AndroidBridge::Bridge()->GetMessage(aMessageId, aRequestId, aProcessId);
--- a/dom/sms/src/android/SmsService.cpp
+++ b/dom/sms/src/android/SmsService.cpp
@@ -44,23 +44,26 @@ SmsService::Send(const nsAString& aNumbe
   AndroidBridge::Bridge()->SendMessage(aNumber, aMessage, aRequestId,
                                        aProcessId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
+                             const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
-  return SmsMessage::Create(aId, aDelivery, aSender, aReceiver, aBody,
-                            aTimestamp, aRead, aCx, aMessage);
+  return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
+                            aSender, aReceiver,
+                            aBody, aTimestamp, aRead,
+                            aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/fallback/SmsDatabaseService.cpp
+++ b/dom/sms/src/fallback/SmsDatabaseService.cpp
@@ -27,16 +27,24 @@ SmsDatabaseService::SaveSentMessage(cons
                                     uint64_t aDate, int32_t* aId)
 {
   *aId = -1;
   NS_ERROR("We should not be here!");
   return NS_OK;
 }
 
 NS_IMETHODIMP
+SmsDatabaseService::SetMessageDeliveryStatus(int32_t aMessageId,
+                                             const nsAString& aDeliveryStatus)
+{
+  NS_ERROR("We should not be here!");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 SmsDatabaseService::GetMessageMoz(int32_t aMessageId, int32_t aRequestId,
                                   uint64_t aProcessId)
 {
   NS_ERROR("We should not be here!");
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/dom/sms/src/fallback/SmsService.cpp
+++ b/dom/sms/src/fallback/SmsService.cpp
@@ -34,23 +34,26 @@ SmsService::Send(const nsAString& aNumbe
 {
   NS_ERROR("We should not be here!");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
+                             const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
-  return SmsMessage::Create(aId, aDelivery, aSender, aReceiver, aBody,
-                            aTimestamp, aRead, aCx, aMessage);
+  return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
+                            aSender, aReceiver,
+                            aBody, aTimestamp, aRead,
+                            aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/src/ipc/PSms.ipdl
+++ b/dom/sms/src/ipc/PSms.ipdl
@@ -3,30 +3,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PContent;
 include "mozilla/dom/sms/Types.h";
 
 using DeliveryState;
+using DeliveryStatus;
 using ReadState;
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 struct SmsMessageData {
-  int32_t       id;
-  DeliveryState delivery;
-  nsString      sender;
-  nsString      receiver;
-  nsString      body;
-  uint64_t      timestamp; // ms since epoch.
-  bool          read;
+  int32_t        id;
+  DeliveryState  delivery;
+  DeliveryStatus deliveryStatus;
+  nsString       sender;
+  nsString       receiver;
+  nsString       body;
+  uint64_t       timestamp; // ms since epoch.
+  bool           read;
 };
 
 struct SmsFilterData {
   uint64_t      startDate;
   uint64_t      endDate;
   nsString[]    numbers;
   DeliveryState delivery;
   ReadState     read;  
@@ -35,17 +37,19 @@ struct SmsFilterData {
 sync protocol PSms {
     manager PContent;
 
 child:
     NotifyReceivedMessage(SmsMessageData aMessageData);
 
     NotifySentMessage(SmsMessageData aMessageData);
 
-    NotifyDeliveredMessage(SmsMessageData aMessageData);
+    NotifyDeliverySuccessMessage(SmsMessageData aMessageData);
+
+    NotifyDeliveryErrorMessage(SmsMessageData aMessageData);
 
     NotifyRequestSmsSent(SmsMessageData aMessageData, int32_t aRequestId,
                          uint64_t aProcessId);
 
     NotifyRequestSmsSendFailed(int32_t aError, int32_t aRequestId,
                                uint64_t aProcessId);
 
     NotifyRequestGotSms(SmsMessageData aMessageData, int32_t aRequestId,
@@ -84,16 +88,18 @@ parent:
                 uint64_t aProcessId);
 
     sync SaveReceivedMessage(nsString aSender, nsString aBody, uint64_t aDate)
         returns (int32_t aId);
 
     sync SaveSentMessage(nsString aReceiver, nsString aBody, uint64_t aDate)
         returns (int32_t aId);
 
+    SetMessageDeliveryStatus(int32_t aMessageId, nsString aDeliveryStatus);
+
     GetMessage(int32_t aMessageId, int32_t aRequestId, uint64_t aProcessId);
 
     DeleteMessage(int32_t aMessageId, int32_t aRequestId, uint64_t aProcessId);
 
     CreateMessageList(SmsFilterData aFilter, bool aReverse, int32_t aRequestId, uint64_t aProcessId);
 
     GetNextMessageInList(int32_t aListId, int32_t aRequestId, uint64_t aProcessId);
 
--- a/dom/sms/src/ipc/SmsChild.cpp
+++ b/dom/sms/src/ipc/SmsChild.cpp
@@ -7,59 +7,65 @@
 #include "SmsMessage.h"
 #include "Constants.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/ContentChild.h"
 #include "SmsRequestManager.h"
 #include "SmsRequest.h"
 
+using namespace mozilla;
+using namespace mozilla::dom::sms;
+
+namespace {
+
+void
+NotifyObserversWithSmsMessage(const char* aEventName,
+                              const SmsMessageData& aMessageData)
+{
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  if (!obs) {
+    return;
+  }
+
+  nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
+  obs->NotifyObservers(message, aEventName, nullptr);
+}
+
+} // anonymous namespace
+
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 bool
 SmsChild::RecvNotifyReceivedMessage(const SmsMessageData& aMessageData)
 {
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return true;
-  }
-
-  nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
-  obs->NotifyObservers(message, kSmsReceivedObserverTopic, nullptr);
-
+  NotifyObserversWithSmsMessage(kSmsReceivedObserverTopic, aMessageData);
   return true;
 }
 
 bool
 SmsChild::RecvNotifySentMessage(const SmsMessageData& aMessageData)
 {
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return true;
-  }
-
-  nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
-  obs->NotifyObservers(message, kSmsSentObserverTopic, nullptr);
-
+  NotifyObserversWithSmsMessage(kSmsSentObserverTopic, aMessageData);
   return true;
 }
 
 bool
-SmsChild::RecvNotifyDeliveredMessage(const SmsMessageData& aMessageData)
+SmsChild::RecvNotifyDeliverySuccessMessage(const SmsMessageData& aMessageData)
 {
-  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  if (!obs) {
-    return true;
-  }
+  NotifyObserversWithSmsMessage(kSmsDeliverySuccessObserverTopic, aMessageData);
+  return true;
+}
 
-  nsCOMPtr<SmsMessage> message = new SmsMessage(aMessageData);
-  obs->NotifyObservers(message, kSmsDeliveredObserverTopic, nullptr);
-
+bool
+SmsChild::RecvNotifyDeliveryErrorMessage(const SmsMessageData& aMessageData)
+{
+  NotifyObserversWithSmsMessage(kSmsDeliveryErrorObserverTopic, aMessageData);
   return true;
 }
 
 bool
 SmsChild::RecvNotifyRequestSmsSent(const SmsMessageData& aMessage,
                                    const int32_t& aRequestId,
                                    const uint64_t& aProcessId)
 {
--- a/dom/sms/src/ipc/SmsChild.h
+++ b/dom/sms/src/ipc/SmsChild.h
@@ -12,17 +12,18 @@ namespace mozilla {
 namespace dom {
 namespace sms {
 
 class SmsChild : public PSmsChild
 {
 public:
   virtual bool RecvNotifyReceivedMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
   virtual bool RecvNotifySentMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
-  virtual bool RecvNotifyDeliveredMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
+  virtual bool RecvNotifyDeliverySuccessMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
+  virtual bool RecvNotifyDeliveryErrorMessage(const SmsMessageData& aMessage) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestSmsSent(const SmsMessageData& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestSmsSendFailed(const int32_t& aError, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestGotSms(const SmsMessageData& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestGetSmsFailed(const int32_t& aError, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestSmsDeleted(const bool& aDeleted, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestSmsDeleteFailed(const int32_t& aError, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestNoMessageInList(const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvNotifyRequestCreateMessageList(const int32_t& aListId, const SmsMessageData& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
--- a/dom/sms/src/ipc/SmsIPCService.cpp
+++ b/dom/sms/src/ipc/SmsIPCService.cpp
@@ -56,26 +56,29 @@ SmsIPCService::Send(const nsAString& aNu
                                  aRequestId, ContentChild::GetSingleton()->GetID());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsIPCService::CreateSmsMessage(int32_t aId,
                                 const nsAString& aDelivery,
+                                const nsAString& aDeliveryStatus,
                                 const nsAString& aSender,
                                 const nsAString& aReceiver,
                                 const nsAString& aBody,
                                 const jsval& aTimestamp,
                                 const bool aRead,
                                 JSContext* aCx,
                                 nsIDOMMozSmsMessage** aMessage)
 {
-  return SmsMessage::Create(aId, aDelivery, aSender, aReceiver, aBody,
-                            aTimestamp, aRead, aCx, aMessage);
+  return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
+                            aSender, aReceiver,
+                            aBody, aTimestamp, aRead,
+                            aCx, aMessage);
 }
 
 /*
  * Implementation of nsISmsDatabaseService.
  */
 NS_IMETHODIMP
 SmsIPCService::SaveReceivedMessage(const nsAString& aSender,
                                    const nsAString& aBody,
@@ -94,16 +97,26 @@ SmsIPCService::SaveSentMessage(const nsA
 {
   GetSmsChild()->SendSaveSentMessage(nsString(aReceiver), nsString(aBody),
                                      aDate, aId);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+SmsIPCService::SetMessageDeliveryStatus(int32_t aMessageId,
+                                        const nsAString& aDeliveryStatus)
+{
+  GetSmsChild()->SendSetMessageDeliveryStatus(aMessageId,
+                                              nsString(aDeliveryStatus));
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 SmsIPCService::GetMessageMoz(int32_t aMessageId, int32_t aRequestId,
                              uint64_t aProcessId)
 {
   GetSmsChild()->SendGetMessage(aMessageId, aRequestId,
                                 ContentChild::GetSingleton()->GetID());
   return NS_OK;
 }
 
--- a/dom/sms/src/ipc/SmsParent.cpp
+++ b/dom/sms/src/ipc/SmsParent.cpp
@@ -43,30 +43,32 @@ SmsParent::SmsParent()
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (!obs) {
     return;
   }
 
   obs->AddObserver(this, kSmsReceivedObserverTopic, false);
   obs->AddObserver(this, kSmsSentObserverTopic, false);
-  obs->AddObserver(this, kSmsDeliveredObserverTopic, false);
+  obs->AddObserver(this, kSmsDeliverySuccessObserverTopic, false);
+  obs->AddObserver(this, kSmsDeliveryErrorObserverTopic, false);
 }
 
 void
 SmsParent::ActorDestroy(ActorDestroyReason why)
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (!obs) {
     return;
   }
 
   obs->RemoveObserver(this, kSmsReceivedObserverTopic);
   obs->RemoveObserver(this, kSmsSentObserverTopic);
-  obs->RemoveObserver(this, kSmsDeliveredObserverTopic);
+  obs->RemoveObserver(this, kSmsDeliverySuccessObserverTopic);
+  obs->RemoveObserver(this, kSmsDeliveryErrorObserverTopic);
 
   NS_ASSERTION(gSmsParents, "gSmsParents can't be null at that point!");
   gSmsParents->RemoveElement(this);
   if (gSmsParents->Length() == 0) {
     delete gSmsParents;
     gSmsParents = nullptr;
   }
 }
@@ -92,24 +94,35 @@ SmsParent::Observe(nsISupports* aSubject
       NS_ERROR("Got a 'sms-sent' topic without a valid message!");
       return NS_OK;
     }
 
     unused << SendNotifySentMessage(static_cast<SmsMessage*>(message.get())->GetData());
     return NS_OK;
   }
 
-  if (!strcmp(aTopic, kSmsDeliveredObserverTopic)) {
+  if (!strcmp(aTopic, kSmsDeliverySuccessObserverTopic)) {
     nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
     if (!message) {
-      NS_ERROR("Got a 'sms-delivered' topic without a valid message!");
+      NS_ERROR("Got a 'sms-delivery-success' topic without a valid message!");
       return NS_OK;
     }
 
-    unused << SendNotifyDeliveredMessage(static_cast<SmsMessage*>(message.get())->GetData());
+    unused << SendNotifyDeliverySuccessMessage(static_cast<SmsMessage*>(message.get())->GetData());
+    return NS_OK;
+  }
+
+  if (!strcmp(aTopic, kSmsDeliveryErrorObserverTopic)) {
+    nsCOMPtr<nsIDOMMozSmsMessage> message = do_QueryInterface(aSubject);
+    if (!message) {
+      NS_ERROR("Got a 'sms-delivery-error' topic without a valid message!");
+      return NS_OK;
+    }
+
+    unused << SendNotifyDeliveryErrorMessage(static_cast<SmsMessage*>(message.get())->GetData());
     return NS_OK;
   }
 
   return NS_OK;
 }
 
 bool
 SmsParent::RecvHasSupport(bool* aHasSupport)
@@ -172,16 +185,28 @@ SmsParent::RecvSaveSentMessage(const nsS
     do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsDBService, true);
 
   smsDBService->SaveSentMessage(aRecipient, aBody, aDate, aId);
   return true;
 }
 
 bool
+SmsParent::RecvSetMessageDeliveryStatus(const int32_t& aMessageId,
+                                        const nsString& aDeliveryStatus)
+{
+  nsCOMPtr<nsISmsDatabaseService> smsDBService =
+    do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(smsDBService, true);
+
+  smsDBService->SetMessageDeliveryStatus(aMessageId, aDeliveryStatus);
+  return true;
+}
+
+bool
 SmsParent::RecvGetMessage(const int32_t& aMessageId, const int32_t& aRequestId,
                           const uint64_t& aProcessId)
 {
   nsCOMPtr<nsISmsDatabaseService> smsDBService =
     do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsDBService, true);
 
   smsDBService->GetMessageMoz(aMessageId, aRequestId, aProcessId);
--- a/dom/sms/src/ipc/SmsParent.h
+++ b/dom/sms/src/ipc/SmsParent.h
@@ -24,16 +24,17 @@ public:
 
   SmsParent();
 
   virtual bool RecvHasSupport(bool* aHasSupport) MOZ_OVERRIDE;
   virtual bool RecvGetNumberOfMessagesForText(const nsString& aText, uint16_t* aResult) MOZ_OVERRIDE;
   virtual bool RecvSendMessage(const nsString& aNumber, const nsString& aMessage, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvSaveReceivedMessage(const nsString& aSender, const nsString& aBody, const uint64_t& aDate, int32_t* aId) MOZ_OVERRIDE;
   virtual bool RecvSaveSentMessage(const nsString& aRecipient, const nsString& aBody, const uint64_t& aDate, int32_t* aId) MOZ_OVERRIDE;
+  virtual bool RecvSetMessageDeliveryStatus(const int32_t& aMessageId, const nsString& aDeliveryStatus) MOZ_OVERRIDE;
   virtual bool RecvGetMessage(const int32_t& aMessageId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvDeleteMessage(const int32_t& aMessageId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvCreateMessageList(const SmsFilterData& aFilter, const bool& aReverse, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvGetNextMessageInList(const int32_t& aListId, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
   virtual bool RecvClearMessageList(const int32_t& aListId) MOZ_OVERRIDE;
   virtual bool RecvMarkMessageRead(const int32_t& aMessageId, const bool& aValue, const int32_t& aRequestId, const uint64_t& aProcessId) MOZ_OVERRIDE;
 
 protected:
--- a/dom/sms/src/ril/SmsDatabaseService.js
+++ b/dom/sms/src/ril/SmsDatabaseService.js
@@ -15,16 +15,21 @@ const RIL_SMSDATABASESERVICE_CID = Compo
 const DEBUG = false;
 const DB_NAME = "sms";
 const DB_VERSION = 2;
 const STORE_NAME = "sms";
 
 const DELIVERY_SENT = "sent";
 const DELIVERY_RECEIVED = "received";
 
+const DELIVERY_STATUS_NOT_APPLICABLE = "not-applicable";
+const DELIVERY_STATUS_SUCCESS = "success";
+const DELIVERY_STATUS_PENDING = "pending";
+const DELIVERY_STATUS_ERROR = "error";
+
 const FILTER_TIMESTAMP = "timestamp";
 const FILTER_NUMBERS = "numbers";
 const FILTER_DELIVERY = "delivery";
 const FILTER_READ = "read";
 
 // We canĀ“t create an IDBKeyCursor with a boolean, so we need to use numbers
 // instead.
 const FILTER_READ_UNREAD = 0;
@@ -312,16 +317,17 @@ SmsDatabaseService.prototype = {
           gSmsRequestManager.notifyReadMessageListFailed(
             requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
           return;
         }
         self.lastMessageListId += 1;
         self.messageLists[self.lastMessageListId] = messageList;
         let sms = gSmsService.createSmsMessage(message.id,
                                                message.delivery,
+                                               message.deliveryStatus,
                                                message.sender,
                                                message.receiver,
                                                message.body,
                                                message.timestamp,
                                                message.read);
         gSmsRequestManager.notifyCreateMessageList(requestId,
                                                    self.lastMessageListId,
                                                    sms);
@@ -346,37 +352,87 @@ SmsDatabaseService.prototype = {
 
   /**
    * nsISmsDatabaseService API
    */
 
   saveReceivedMessage: function saveReceivedMessage(sender, body, date) {
     let receiver = this.mRIL.rilContext.icc ? this.mRIL.rilContext.icc.msisdn : null;
 
-    let message = {delivery:  DELIVERY_RECEIVED,
-                   sender:    sender,
-                   receiver:  receiver,
-                   body:      body,
-                   timestamp: date,
-                   read:      FILTER_READ_UNREAD};
+    let message = {delivery:       DELIVERY_RECEIVED,
+                   deliveryStatus: DELIVERY_STATUS_SUCCESS,
+                   sender:         sender,
+                   receiver:       receiver,
+                   body:           body,
+                   timestamp:      date,
+                   read:           FILTER_READ_UNREAD};
     return this.saveMessage(message);
   },
 
   saveSentMessage: function saveSentMessage(receiver, body, date) {
     let sender = this.mRIL.rilContext.icc ? this.mRIL.rilContext.icc.msisdn : null;
 
-    let message = {delivery:  DELIVERY_SENT,
-                   sender:    sender,
-                   receiver:  receiver,
-                   body:      body,
-                   timestamp: date,
-                   read:      FILTER_READ_READ};
+    let message = {delivery:       DELIVERY_SENT,
+                   deliveryStatus: DELIVERY_STATUS_PENDING,
+                   sender:         sender,
+                   receiver:       receiver,
+                   body:           body,
+                   timestamp:      date,
+                   read:           FILTER_READ_READ};
     return this.saveMessage(message);
   },
 
+  setMessageDeliveryStatus: function setMessageDeliveryStatus(messageId, deliveryStatus) {
+    if ((deliveryStatus != DELIVERY_STATUS_SUCCESS)
+        && (deliveryStatus != DELIVERY_STATUS_ERROR)) {
+      if (DEBUG) {
+        debug("Setting message " + messageId + " deliveryStatus to values other"
+              + " than 'success' and 'error'");
+      }
+      return;
+    }
+    if (DEBUG) {
+      debug("Setting message " + messageId + " deliveryStatus to "
+            + deliveryStatus);
+    }
+    this.newTxn(READ_WRITE, function (error, txn, store) {
+      if (error) {
+        if (DEBUG) debug(error);
+        return;
+      }
+
+      let getRequest = store.get(messageId);
+      getRequest.onsuccess = function onsuccess(event) {
+        let message = event.target.result;
+        if (!message) {
+          if (DEBUG) debug("Message ID " + messageId + " not found");
+          return;
+        }
+        if (message.id != messageId) {
+          if (DEBUG) {
+            debug("Retrieve message ID (" + messageId + ") is " +
+                  "different from the one we got");
+          }
+          return;
+        }
+        // Only updates messages that are still waiting for its delivery status.
+        if (message.deliveryStatus != DELIVERY_STATUS_PENDING) {
+          if (DEBUG) {
+            debug("The value of message.deliveryStatus is not 'pending' but "
+                  + message.deliveryStatus);
+          }
+          return;
+        }
+        message.deliveryStatus = deliveryStatus;
+        if (DEBUG) debug("Message.deliveryStatus set to: " + deliveryStatus);
+        store.put(message);
+      };
+    });
+  },
+
   getMessage: function getMessage(messageId, requestId) {
     if (DEBUG) debug("Retrieving message with ID " + messageId);
     this.newTxn(READ_ONLY, function (error, txn, store) {
       if (error) {
         if (DEBUG) debug(error);
         gSmsRequestManager.notifyGetSmsFailed(
           requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
         return;
@@ -404,16 +460,17 @@ SmsDatabaseService.prototype = {
                   "different from the one we got");
           }
           gSmsRequestManager.notifyGetSmsFailed(
             requestId, Ci.nsISmsRequestManager.UNKNOWN_ERROR);
           return;
         }
         let message = gSmsService.createSmsMessage(data.id,
                                                    data.delivery,
+                                                   data.deliveryStatus,
                                                    data.sender,
                                                    data.receiver,
                                                    data.body,
                                                    data.timestamp,
                                                    data.read);
         gSmsRequestManager.notifyGotSms(requestId, message);
       };
 
@@ -628,16 +685,17 @@ SmsDatabaseService.prototype = {
         if (DEBUG) debug("Transaction " + txn + " completed.");
         if (!message) {
           if (DEBUG) debug("Could not get message id " + messageId);
           gSmsRequestManager.notifyReadMessageListFailed(
             requestId, Ci.nsISmsRequestManager.NOT_FOUND_ERROR);
         }
         let sms = gSmsService.createSmsMessage(message.id,
                                                message.delivery,
+                                               message.deliveryStatus,
                                                message.sender,
                                                message.receiver,
                                                message.body,
                                                message.timestamp,
                                                message.read);
         gSmsRequestManager.notifyGotNextMessage(requestId, sms);
       };
 
--- a/dom/sms/src/ril/SmsService.cpp
+++ b/dom/sms/src/ril/SmsService.cpp
@@ -59,23 +59,26 @@ SmsService::Send(const nsAString& aNumbe
 
   mRIL->SendSMS(aNumber, aMessage, aRequestId, aProcessId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(int32_t aId,
                              const nsAString& aDelivery,
+                             const nsAString& aDeliveryStatus,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
                              const nsAString& aBody,
                              const jsval& aTimestamp,
                              const bool aRead,
                              JSContext* aCx,
                              nsIDOMMozSmsMessage** aMessage)
 {
-  return SmsMessage::Create(aId, aDelivery, aSender, aReceiver, aBody,
-                            aTimestamp, aRead, aCx, aMessage);
+  return SmsMessage::Create(aId, aDelivery, aDeliveryStatus,
+                            aSender, aReceiver,
+                            aBody, aTimestamp, aRead,
+                            aCx, aMessage);
 }
 
 } // namespace sms
 } // namespace dom
 } // namespace mozilla
--- a/dom/sms/tests/marionette/test_getmessage.js
+++ b/dom/sms/tests/marionette/test_getmessage.js
@@ -31,16 +31,17 @@ function simulateIncomingSms() {
     log("Received 'onreceived' smsmanager event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     inSmsId = incomingSms.id;
     log("Received SMS (id: " + inSmsId + ").");
     is(incomingSms.body, inText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
+    is(incomingSms.deliveryStatus, "success", "deliveryStatus");
     is(incomingSms.read, false, "read");
     is(incomingSms.receiver, null, "receiver");
     is(incomingSms.sender, remoteNumber, "sender");
     ok(incomingSms.timestamp instanceof Date, "timestamp is instanceof date");
     inSmsTimeStamp = incomingSms.timestamp;
     sendSms();
   };
   // Simulate incoming sms sent from remoteNumber to our emulator
@@ -56,16 +57,17 @@ function sendSms() {
     gotSmsOnsent = true;
     let sentSms = event.message;
     ok(sentSms, "outgoing sms");
     ok(sentSms.id, "sms id");
     outSmsId = sentSms.id;
     log("Sent SMS (id: " + outSmsId + ").");
     is(sentSms.body, outText, "msg body");
     is(sentSms.delivery, "sent", "delivery");
+    is(sentSms.deliveryStatus, "pending", "deliveryStatus");
     is(sentSms.read, true, "read");
     is(sentSms.receiver, remoteNumber, "receiver");
     is(sentSms.sender, null, "sender");
     ok(sentSms.timestamp instanceof Date, "timestamp is instanceof date");  
     outSmsTimeStamp = sentSms.timestamp;
 
     if (gotSmsOnsent && gotReqOnsuccess) { getReceivedSms(); }
   };
@@ -103,16 +105,17 @@ function getReceivedSms() {
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, inSmsId, "SMS id matches");
     log("Got SMS (id: " + foundSms.id + ").");
     is(foundSms.body, inText, "SMS msg text matches");
     is(foundSms.delivery, "received", "delivery");
+    is(foundSms.deliveryStatus, "success", "deliveryStatus");
     is(foundSms.read, false, "read");
     is(foundSms.receiver, myNumber, "receiver");
     is(foundSms.sender, remoteNumber, "sender");
     ok(foundSms.timestamp instanceof Date, "timestamp is instanceof date");
     is(foundSms.timestamp.getTime(), inSmsTimeStamp.getTime(), "timestamp matches");
     getSentSms();
   };
 
@@ -134,16 +137,17 @@ function getSentSms() {
   requestRet.onsuccess = function(event) {
     log("Received 'onsuccess' smsrequest event.");
     ok(event.target.result, "smsrequest event.target.result");
     let foundSms = event.target.result;
     is(foundSms.id, outSmsId, "SMS id matches");
     log("Got SMS (id: " + foundSms.id + ").");
     is(foundSms.body, outText, "SMS msg text matches");
     is(foundSms.delivery, "sent", "delivery");
+    is(foundSms.deliveryStatus, "pending", "deliveryStatus");
     is(foundSms.read, true, "read");
     is(foundSms.receiver, remoteNumber, "receiver");
     is(foundSms.sender, myNumber, "sender");
     ok(foundSms.timestamp instanceof Date, "timestamp is instanceof date");
     is(foundSms.timestamp.getTime(), outSmsTimeStamp.getTime(), "timestamp matches");
     deleteMsgs();
   };
 
--- a/dom/sms/tests/marionette/test_incoming.js
+++ b/dom/sms/tests/marionette/test_incoming.js
@@ -20,16 +20,17 @@ runEmulatorCmd("sms send " + sender + " 
 
 sms.onreceived = function onreceived(event) {
   log("Received an SMS!");
 
   let message = event.message;
   ok(message instanceof MozSmsMessage);
 
   is(message.delivery, "received");
+  is(message.deliveryStatus, "success");
   is(message.sender, sender);
   is(message.receiver, null);
   is(message.body, body);
   ok(message.timestamp instanceof Date);
   // SMSC timestamp is in seconds.
   ok(Math.floor(message.timestamp.getTime() / 1000) >= Math.floor(now / 1000));
 
   cleanUp();
--- a/dom/sms/tests/marionette/test_incoming_delete.js
+++ b/dom/sms/tests/marionette/test_incoming_delete.js
@@ -22,16 +22,17 @@ function simulateIncomingSms() {
   sms.onreceived = function onreceived(event) {
     log("Received 'onreceived' smsmanager event.");
     let incomingSms = event.message;
     ok(incomingSms, "incoming sms");
     ok(incomingSms.id, "sms id");
     log("Received SMS (id: " + incomingSms.id + ").");
     is(incomingSms.body, msgText, "msg body");
     is(incomingSms.delivery, "received", "delivery");
+    is(incomingSms.deliveryStatus, "success", "deliveryStatus");
     is(incomingSms.read, false, "read");
     is(incomingSms.receiver, null, "receiver");
     is(incomingSms.sender, fromNumber, "sender");
     ok(incomingSms.timestamp instanceof Date, "timestamp is istanceof date");
 
     verifySmsExists(incomingSms);
   };
   runEmulatorCmd("sms send " + fromNumber + " " + msgText, function(result) {
--- a/dom/sms/tests/marionette/test_message_classes.js
+++ b/dom/sms/tests/marionette/test_message_classes.js
@@ -35,16 +35,17 @@ function checkMessage(message, id) {
   ok(message instanceof MozSmsMessage,
      "message is instanceof " + message.constructor);
   if (id == null) {
     ok(message.id > 0, "message.id");
   } else {
     is(message.id, -1, "message.id");
   }
   is(message.delivery, "received", "message.delivery");
+  is(message.deliveryStatus, "success", "message.deliveryStatus");
   is(message.sender, "+1", "message.sender");
   is(message.body, "A", "message.body");
   ok(message.timestamp instanceof Date,
      "message.timestamp is instanceof " + message.timestamp.constructor);
   is(message.timestamp.getTime(), TIMESTAMP, "message.timestamp");
   is(message.read, false, "message.read");
 }
 
--- a/dom/sms/tests/marionette/test_outgoing.js
+++ b/dom/sms/tests/marionette/test_outgoing.js
@@ -28,16 +28,17 @@ const LONG_BODY = "Let me not to the mar
 
 function checkSentMessage(message, body, sentDate) {
   ok(message, "message is valid");
   ok(message instanceof MozSmsMessage,
      "message is instanceof " + message.constructor);
 
   ok(message.id, "message.id is valid");
   is(message.delivery, "sent", "message.delivery");
+  is(message.deliveryStatus, "pending", "message.deliveryStatus");
   is(message.sender, null, "message.sender");
   is(message.receiver, receiver, "message.receiver");
   is(message.body, body, "message.body");
   ok(message.timestamp instanceof Date,
      "message.timestamp is instanceof " + message.timestamp.constructor);
   // SMSC timestamp is in seconds.
   ok(Math.floor(message.timestamp.getTime() / 1000) >= Math.floor(sentDate / 1000),
      "sent timestamp is valid");
--- a/dom/sms/tests/marionette/test_outgoing_delete.js
+++ b/dom/sms/tests/marionette/test_outgoing_delete.js
@@ -27,16 +27,17 @@ function sendSms() {
     gotSmsOnsent = true;
     let sentSms = event.message;
     ok(sentSms, "outgoing sms");
     ok(sentSms.id, "sms id");
     smsId = sentSms.id;
     log("Sent SMS (id: " + smsId + ").");
     is(sentSms.body, msgText, "msg body");
     is(sentSms.delivery, "sent", "delivery");
+    is(sentSms.deliveryStatus, "pending", "deliveryStatus");
     is(sentSms.read, true, "read");
     is(sentSms.receiver, destNumber, "receiver");
     is(sentSms.sender, null, "sender");
     ok(sentSms.timestamp instanceof Date, "timestamp is istanceof date");
 
     if (gotSmsOnsent && gotReqOnsuccess) { verifySmsExists(smsId); }
   };
 
--- a/dom/sms/tests/test_smsservice_createsmsmessage.js
+++ b/dom/sms/tests/test_smsservice_createsmsmessage.js
@@ -27,40 +27,46 @@ function newMessage() {
 function run_test() {
   run_next_test();
 }
 
 /**
  * Ensure an SmsMessage object created has sensible initial values.
  */
 add_test(function test_interface() {
-  let sms = newMessage(null, "sent", null, null, null, new Date(), true);
+  let sms = newMessage(null, "sent", "pending", null, null, null, new Date(),
+                       true);
   do_check_true(sms instanceof Ci.nsIDOMMozSmsMessage);
   do_check_eq(sms.id, 0);
   do_check_eq(sms.delivery, "sent");
+  do_check_eq(sms.deliveryStatus, "pending");
   do_check_eq(sms.receiver, null);
   do_check_eq(sms.sender, null);
   do_check_eq(sms.body, null);
   do_check_true(sms.timestamp instanceof Date);
   do_check_true(sms.read);
   run_next_test();
 });
 
 /**
  * Verify that attributes are read-only.
  */
 add_test(function test_readonly_attributes() {
-  let sms = newMessage(null, "received", null, null, null, new Date(), true);
+  let sms = newMessage(null, "received", "success", null, null, null,
+                       new Date(), true);
 
   sms.id = 1;
   do_check_eq(sms.id, 0);
 
   sms.delivery = "sent";
   do_check_eq(sms.delivery, "received");
 
+  sms.deliveryStatus = "pending";
+  do_check_eq(sms.deliveryStatus, "success");
+
   sms.receiver = "a receiver";
   do_check_eq(sms.receiver, null);
 
   sms.sender = "a sender";
   do_check_eq(sms.sender, null);
 
   sms.body = "a body";
   do_check_eq(sms.body, null);
@@ -75,102 +81,128 @@ add_test(function test_readonly_attribut
   run_next_test();
 });
 
 /**
  * Test supplying the timestamp as a number of milliseconds.
  */
 add_test(function test_timestamp_number() {
   let ts = Date.now();
-  let sms = newMessage(42, "sent", "the sender", "the receiver", "the body", ts,
-                       true);
+  let sms = newMessage(42, "sent", "pending", "the sender", "the receiver",
+                       "the body", ts, true);
   do_check_eq(sms.id, 42);
   do_check_eq(sms.delivery, "sent");
+  do_check_eq(sms.deliveryStatus, "pending");
   do_check_eq(sms.sender, "the sender");
   do_check_eq(sms.receiver, "the receiver");
   do_check_eq(sms.body, "the body");
   do_check_true(sms.timestamp instanceof Date);
   do_check_eq(sms.timestamp.getTime(), ts);
   do_check_true(sms.read);
   run_next_test();
 });
 
 /**
  * Test supplying the timestamp as a Date object.
  */
 add_test(function test_timestamp_date() {
   let date = new Date();
-  let sms = newMessage(42, "sent", "the sender", "the receiver", "the body",
-                       date, true);
+  let sms = newMessage(42, "sent", "pending", "the sender", "the receiver",
+                       "the body", date, true);
   do_check_eq(sms.id, 42);
   do_check_eq(sms.delivery, "sent");
+  do_check_eq(sms.deliveryStatus, "pending");
   do_check_eq(sms.sender, "the sender");
   do_check_eq(sms.receiver, "the receiver");
   do_check_eq(sms.body, "the body");
   do_check_true(sms.timestamp instanceof Date);
   do_check_eq(sms.timestamp.getTime(), date.getTime());
   do_check_true(sms.read);
   run_next_test();
 });
 
 /**
  * Test that a floating point number for the timestamp is not allowed.
  */
 add_test(function test_invalid_timestamp_float() {
   do_check_throws(function() {
-    newMessage(42, "sent", "the sender", "the receiver", "the body", 3.1415,
-               true);
+    newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
+               3.1415, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a null value for the timestamp is not allowed.
  */
 add_test(function test_invalid_timestamp_null() {
   do_check_throws(function() {
-    newMessage(42, "sent", "the sender", "the receiver", "the body", null,
-               true);
+    newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
+               null, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that undefined for the timestamp is not allowed.
  */
 add_test(function test_invalid_timestamp_undefined() {
   do_check_throws(function() {
-    newMessage(42, "sent", "the sender", "the receiver", "the body", undefined,
-               true);
+    newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
+               undefined, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a random object for the timestamp is not allowed.
  */
 add_test(function test_invalid_timestamp_object() {
   do_check_throws(function() {
-    newMessage(42, "sent", "the sender", "the receiver", "the body", {}, true);
+    newMessage(42, "sent", "pending", "the sender", "the receiver", "the body",
+               {}, true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that an invalid delivery string is not accepted.
  */
 add_test(function test_invalid_delivery_string() {
   do_check_throws(function() {
-    newMessage(42, "this is invalid", "the sender", "the receiver", "the body",
-               new Date(), true);
+    newMessage(42, "this is invalid", "pending", "the sender", "the receiver",
+               "the body", new Date(), true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
 
 /**
  * Test that a number is not accepted for the 'delivery' argument.
  */
 add_test(function test_invalid_delivery_string() {
   do_check_throws(function() {
-    newMessage(42, 1, "the sender", "the receiver", "the body", new Date(), true);
+    newMessage(42, 1, "pending", "the sender", "the receiver", "the body",
+               new Date(), true);
   }, Cr.NS_ERROR_INVALID_ARG);
   run_next_test();
 });
+
+/**
+ * Test that an invalid delivery status string is not accepted.
+ */
+add_test(function test_invalid_delivery_status_string() {
+  do_check_throws(function() {
+    newMessage(42, "sent", "this is invalid", "the sender", "the receiver",
+               "the body", new Date(), true);
+  }, Cr.NS_ERROR_INVALID_ARG);
+  run_next_test();
+});
+
+/**
+ * Test that a number is not accepted for the 'deliveryStatus' argument.
+ */
+add_test(function test_invalid_delivery_status_string() {
+  do_check_throws(function() {
+    newMessage(42, "sent", 1, "the sender", "the receiver", "the body",
+               new Date(), true);
+  }, Cr.NS_ERROR_INVALID_ARG);
+  run_next_test();
+});
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -20,32 +20,37 @@
 #include "GonkGPSGeolocationProvider.h"
 #include "SystemWorkerManager.h"
 #include "mozilla/Preferences.h"
 #include "nsGeoPosition.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsINetworkManager.h"
 #include "nsIRadioInterfaceLayer.h"
 #include "nsIDOMMobileConnection.h"
+#include "nsJSUtils.h"
+#include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
 #ifdef AGPS_TYPE_INVALID
 #define AGPS_HAVE_DUAL_APN
 #endif
 
 #define DEBUG_GPS 0
 
 using namespace mozilla;
 
 static const int kDefaultPeriod = 1000; // ms
 
 // While most methods of GonkGPSGeolocationProvider should only be
 // called from main thread, we deliberately put the Init and ShutdownGPS
 // methods off main thread to avoid blocking.
-NS_IMPL_THREADSAFE_ISUPPORTS2(GonkGPSGeolocationProvider, nsIGeolocationProvider, nsIRILDataCallback)
+NS_IMPL_THREADSAFE_ISUPPORTS3(GonkGPSGeolocationProvider,
+                              nsIGeolocationProvider,
+                              nsIRILDataCallback,
+                              nsISettingsServiceCallback)
 
 GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton;
 GpsCallbacks GonkGPSGeolocationProvider::mCallbacks = {
   sizeof(GpsCallbacks),
   LocationCallback,
   StatusCallback,
   SvStatusCallback,
   NmeaCallback,
@@ -301,36 +306,82 @@ GonkGPSGeolocationProvider::GetGPSInterf
   const GpsInterface* result = gps_device->get_gps_interface(gps_device);
 
   if (result->size != sizeof(GpsInterface)) {
     return nullptr;
   }
   return result;
 }
 
+int32_t
+GonkGPSGeolocationProvider::GetDataConnectionState()
+{
+  if (!mRIL) {
+    return nsINetworkInterface::NETWORK_STATE_UNKNOWN;
+  }
+
+  int32_t state;
+  mRIL->GetDataCallStateByType(NS_LITERAL_STRING("supl"), &state);
+  return state;
+}
+
+void
+GonkGPSGeolocationProvider::SetAGpsDataConn(nsAString& aApn)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mAGpsInterface);
+
+  int32_t connectionState = GetDataConnectionState();
+  if (connectionState == nsINetworkInterface::NETWORK_STATE_CONNECTED) {
+    NS_ConvertUTF16toUTF8 apn(aApn);
+#ifdef AGPS_HAVE_DUAL_APN
+    mAGpsInterface->data_conn_open(AGPS_TYPE_SUPL,
+                                   apn.get(),
+                                   AGPS_APN_BEARER_IPV4);
+#else
+    mAGpsInterface->data_conn_open(apn.get());
+#endif
+  } else if (connectionState == nsINetworkInterface::NETWORK_STATE_DISCONNECTED) {
+#ifdef AGPS_HAVE_DUAL_APN
+    mAGpsInterface->data_conn_closed(AGPS_TYPE_SUPL);
+#else
+    mAGpsInterface->data_conn_closed();
+#endif
+  }
+}
+
+void
+GonkGPSGeolocationProvider::RequestSettingValue(char* aKey)
+{
+  MOZ_ASSERT(aKey);
+  nsCOMPtr<nsISettingsService> ss = do_GetService("@mozilla.org/settingsService;1");
+  if (!ss) {
+    MOZ_ASSERT(ss);
+    return;
+  }
+  nsCOMPtr<nsISettingsServiceLock> lock;
+  ss->CreateLock(getter_AddRefs(lock));
+  lock->Get(aKey, this);
+}
+
 void
 GonkGPSGeolocationProvider::RequestDataConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   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 */);
+  if (GetDataConnectionState() == nsINetworkInterface::NETWORK_STATE_CONNECTED) {
+    // Connection is already established, we don't need to setup again.
+    // We just get supl APN and make AGPS data connection state updated.
+    RequestSettingValue("ril.supl.apn");
+  } else {
+    mRIL->SetupDataCallByType(NS_LITERAL_STRING("supl"));
   }
 }
 
 void
 GonkGPSGeolocationProvider::ReleaseDataConnection()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -583,55 +634,50 @@ GonkGPSGeolocationProvider::SetHighAccur
 
 /** nsIRILDataCallback interface **/
 
 NS_IMETHODIMP
 GonkGPSGeolocationProvider::DataCallStateChanged(nsIRILDataCallInfo* aDataCall)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aDataCall);
-  MOZ_ASSERT(mAGpsInterface);
-  nsCOMPtr<nsIRILDataCallInfo> datacall = aDataCall;
 
-  uint32_t callState;
-  nsresult rv = datacall->GetState(&callState);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoString apn;
-  rv = datacall->GetApn(apn);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = datacall->GetCid(mCid);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ConvertUTF16toUTF8 currentApn(apn);
-  const nsAdoptingCString& agpsApn = Preferences::GetCString("geo.gps.apn.name");
-
-  // TODO: Bug 772748 - handle data call failed case.
-  if (currentApn == agpsApn) {
-    switch (callState) {
-      case nsINetworkInterface::NETWORK_STATE_CONNECTED:
-#ifdef AGPS_HAVE_DUAL_APN
-        mAGpsInterface->data_conn_open(AGPS_TYPE_SUPL,
-                                       agpsApn.get(),
-                                       AGPS_APN_BEARER_IPV4);
-#else
-        mAGpsInterface->data_conn_open(agpsApn.get());
-#endif
-        break;
-      case nsINetworkInterface::NETWORK_STATE_DISCONNECTED:
-#ifdef AGPS_HAVE_DUAL_APN
-        mAGpsInterface->data_conn_closed(AGPS_TYPE_SUPL);
-#else
-        mAGpsInterface->data_conn_closed();
-#endif
-        break;
-    }
-  }
+  // We call Setting Service before we get the state of supl data connection
+  // since it is possible that state of supl data connection haven't been
+  // updated and will be updated after we finished this function (code that
+  // updates the state is in another dataCallStateChanged callback).
+  RequestSettingValue("ril.supl.apn");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GonkGPSGeolocationProvider::ReceiveDataCallList(nsIRILDataCallInfo** aDataCalls,
                                                 uint32_t aLength)
 {
   return NS_OK;
 }
+
+/** nsISettingsServiceCallback **/
+
+NS_IMETHODIMP
+GonkGPSGeolocationProvider::Handle(const nsAString& aName,
+                                   const JS::Value& aResult,
+                                   JSContext* cx)
+{
+  if (aName.EqualsLiteral("ril.supl.apn")) {
+    // When we get the APN, we attempt to call data_call_open of AGPS.
+    if (aResult.isString()) {
+      nsDependentJSString apn;
+      apn.init(cx, aResult.toString());
+      if (!apn.IsEmpty()) {
+        SetAGpsDataConn(apn);
+      }
+    }
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+GonkGPSGeolocationProvider::HandleError(const nsAString& aErrorMessage,
+                                        JSContext* cx)
+{
+  return NS_OK;
+}
--- a/dom/system/gonk/GonkGPSGeolocationProvider.h
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.h
@@ -17,32 +17,35 @@
 #ifndef GonkGPSGeolocationProvider_h
 #define GonkGPSGeolocationProvider_h
 
 #include <hardware/gps.h> // for GpsInterface
 #include "nsCOMPtr.h"
 #include "nsIGeolocationProvider.h"
 #include "nsIRadioInterfaceLayer.h"
 #include "nsString.h"
+#include "nsISettingsService.h"
 
 class nsIThread;
 
 #define GONK_GPS_GEOLOCATION_PROVIDER_CID \
 { 0x48525ec5, 0x5a7f, 0x490a, { 0x92, 0x77, 0xba, 0x66, 0xe0, 0xd2, 0x2c, 0x8b } }
 
 #define GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID \
 "@mozilla.org/gonk-gps-geolocation-provider;1"
 
 class GonkGPSGeolocationProvider : public nsIGeolocationProvider
                                  , public nsIRILDataCallback
+                                 , public nsISettingsServiceCallback
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIGEOLOCATIONPROVIDER
   NS_DECL_NSIRILDATACALLBACK
+  NS_DECL_NSISETTINGSSERVICECALLBACK
 
   static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
 
 private:
 
   /* Client should use GetSingleton() to get the provider instance. */
   GonkGPSGeolocationProvider();
   GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &);
@@ -61,16 +64,19 @@ private:
   static void AGPSStatusCallback(AGpsStatus* status);
   static void AGPSRILSetIDCallback(uint32_t flags);
   static void AGPSRILRefLocCallback(uint32_t flags);
 
   static GpsCallbacks mCallbacks;
   static AGpsCallbacks mAGPSCallbacks;
   static AGpsRilCallbacks mAGPSRILCallbacks;
 
+  int32_t GetDataConnectionState();
+  void SetAGpsDataConn(nsAString& aApn);
+  void RequestSettingValue(char* aKey);
   void Init();
   void SetupAGPS();
   void StartGPS();
   void ShutdownGPS();
   void RequestDataConnection();
   void ReleaseDataConnection();
   void RequestSetID(uint32_t flags);
   void SetReferenceLocation();
--- a/dom/system/gonk/Makefile.in
+++ b/dom/system/gonk/Makefile.in
@@ -57,17 +57,17 @@ ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += \
   AudioManager.cpp \
   AutoMounter.cpp \
   AutoMounterSetting.cpp \
   GonkGPSGeolocationProvider.cpp \
   nsVolume.cpp \
   nsVolumeService.cpp \
   nsVolumeStat.cpp \
-  TimeSetting.cpp \
+  TimeZoneSettingObserver.cpp \
   Volume.cpp \
   VolumeCommand.cpp \
   VolumeManager.cpp \
   VolumeServiceIOThread.cpp \
   VolumeServiceTest.cpp \
   $(NULL)
 # for our local copy of AudioSystem.h
 LOCAL_INCLUDES += -I$(topsrcdir)/media/libsydneyaudio/src
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -32,21 +32,23 @@ const RILNETWORKINTERFACE_CID =
   Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
 
 const nsIAudioManager = Ci.nsIAudioManager;
 const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
 
 const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
 const kSmsReceivedObserverTopic          = "sms-received";
 const kSmsSentObserverTopic              = "sms-sent";
-const kSmsDeliveredObserverTopic         = "sms-delivered";
+const kSmsDeliverySuccessObserverTopic   = "sms-delivery-success";
+const kSmsDeliveryErrorObserverTopic     = "sms-delivery-error";
 const kMozSettingsChangedObserverTopic   = "mozsettings-changed";
 const kSysMsgListenerReadyObserverTopic  = "system-message-listener-ready";
 const kSysClockChangeObserverTopic       = "system-clock-change";
 const kTimeNitzAutomaticUpdateEnabled    = "time.nitz.automatic-update.enabled";
+
 const DOM_SMS_DELIVERY_RECEIVED          = "received";
 const DOM_SMS_DELIVERY_SENT              = "sent";
 
 const RIL_IPC_TELEPHONY_MSG_NAMES = [
   "RIL:EnumerateCalls",
   "RIL:GetMicrophoneMuted",
   "RIL:SetMicrophoneMuted",
   "RIL:GetSpeakerEnabled",
@@ -504,18 +506,18 @@ RadioInterfaceLayer.prototype = {
         this.handleCallWaitingStatusChange(message);
         break;
       case "sms-received":
         this.handleSmsReceived(message);
         return;
       case "sms-sent":
         this.handleSmsSent(message);
         return;
-      case "sms-delivered":
-        this.handleSmsDelivered(message);
+      case "sms-delivery":
+        this.handleSmsDelivery(message);
         return;
       case "sms-send-failed":
         this.handleSmsSendFailed(message);
         return;
       case "datacallstatechange":
         this.handleDataCallState(message);
         break;
       case "datacalllist":
@@ -1230,25 +1232,27 @@ RadioInterfaceLayer.prototype = {
     let id = -1;
     if (message.messageClass != RIL.PDU_DCS_MSG_CLASS_0) {
       id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
                                                    message.fullBody || null,
                                                    message.timestamp);
     }
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_RECEIVED,
+                                           RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
                                            message.sender || null,
                                            message.receiver || null,
                                            message.fullBody || null,
                                            message.timestamp,
                                            false);
 
     gSystemMessenger.broadcastMessage("sms-received",
                                       {id: id,
                                        delivery: DOM_SMS_DELIVERY_RECEIVED,
+                                       deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
                                        sender: message.sender || null,
                                        receiver: message.receiver || null,
                                        body: message.fullBody || null,
                                        timestamp: message.timestamp,
                                        read: false});
     Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
   },
 
@@ -1276,44 +1280,60 @@ RadioInterfaceLayer.prototype = {
     }
 
     let timestamp = Date.now();
     let id = gSmsDatabaseService.saveSentMessage(options.number,
                                                  options.fullBody,
                                                  timestamp);
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_SENT,
+                                           RIL.GECKO_SMS_DELIVERY_STATUS_PENDING,
                                            null,
                                            options.number,
                                            options.fullBody,
                                            timestamp,
                                            true);
 
     if (!options.requestStatusReport) {
       // No more used if STATUS-REPORT not requested.
       delete this._sentSmsEnvelopes[message.envelopeId];
     } else {
-      options.sms = sms;
+      options.id = id;
+      options.timestamp = timestamp;
     }
 
     gSmsRequestManager.notifySmsSent(options.requestId, sms);
 
-    Services.obs.notifyObservers(options.sms, kSmsSentObserverTopic, null);
+    Services.obs.notifyObservers(sms, kSmsSentObserverTopic, null);
   },
 
-  handleSmsDelivered: function handleSmsDelivered(message) {
-    debug("handleSmsDelivered: " + JSON.stringify(message));
+  handleSmsDelivery: function handleSmsDelivery(message) {
+    debug("handleSmsDelivery: " + JSON.stringify(message));
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
     }
     delete this._sentSmsEnvelopes[message.envelopeId];
 
-    Services.obs.notifyObservers(options.sms, kSmsDeliveredObserverTopic, null);
+    gSmsDatabaseService.setMessageDeliveryStatus(options.id,
+                                                 message.deliveryStatus);
+    let sms = gSmsService.createSmsMessage(options.id,
+                                           DOM_SMS_DELIVERY_SENT,
+                                           message.deliveryStatus,
+                                           null,
+                                           options.number,
+                                           options.fullBody,
+                                           options.timestamp,
+                                           true);
+
+    let topic = (message.deliveryStatus == RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS)
+                ? kSmsDeliverySuccessObserverTopic
+                : kSmsDeliveryErrorObserverTopic;
+    Services.obs.notifyObservers(sms, topic, null);
   },
 
   handleSmsSendFailed: function handleSmsSendFailed(message) {
     debug("handleSmsSendFailed: " + JSON.stringify(message));
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ b/dom/system/gonk/SystemWorkerManager.cpp
@@ -12,37 +12,35 @@
  * 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 "SystemWorkerManager.h"
 
-#include "nsIObserverService.h"
 #include "nsIJSContextStack.h"
 #include "nsINetworkManager.h"
 #include "nsIWifi.h"
 #include "nsIWorkerHolder.h"
 #include "nsIXPConnect.h"
 
 #include "jsfriendapi.h"
 #include "mozilla/dom/workers/Workers.h"
 #ifdef MOZ_WIDGET_GONK
 #include "mozilla/ipc/Netd.h"
 #include "AutoMounter.h"
-#include "TimeSetting.h"
+#include "TimeZoneSettingObserver.h"
 #endif
 #include "mozilla/ipc/Ril.h"
 #include "nsContentUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsRadioInterfaceLayer.h"
 #include "WifiWorker.h"
-#include "mozilla/StaticPtr.h"
 
 USING_WORKERS_NAMESPACE
 
 using namespace mozilla::dom::gonk;
 using namespace mozilla::ipc;
 #ifdef MOZ_WIDGET_GONK
 using namespace mozilla::system;
 #endif
@@ -344,20 +342,16 @@ SystemWorkerManager::SystemWorkerManager
 SystemWorkerManager::~SystemWorkerManager()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!gInstance || gInstance == this,
                "There should only be one instance!");
   gInstance = nullptr;
 }
 
-#ifdef MOZ_WIDGET_GONK
-static mozilla::StaticRefPtr<TimeSetting> sTimeSetting;
-#endif
-
 nsresult
 SystemWorkerManager::Init()
 {
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread");
@@ -380,17 +374,17 @@ SystemWorkerManager::Init()
   rv = InitWifi(cx);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to initialize WiFi Networking!");
     return rv;
   }
 
 #ifdef MOZ_WIDGET_GONK
   InitAutoMounter();
-  sTimeSetting = new TimeSetting();
+  InitializeTimeZoneSettingObserver();
   rv = InitNetd(cx);
   NS_ENSURE_SUCCESS(rv, rv);
 #endif
 
   nsCOMPtr<nsIObserverService> obs =
     do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
   if (!obs) {
     NS_WARNING("Failed to get observer service!");
@@ -410,17 +404,16 @@ void
 SystemWorkerManager::Shutdown()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   mShutdown = true;
 
 #ifdef MOZ_WIDGET_GONK
   ShutdownAutoMounter();
-  sTimeSetting = nullptr;
 #endif
 
   StopRil();
 
   mRIL = nullptr;
 
 #ifdef MOZ_WIDGET_GONK
   StopNetd();
rename from dom/system/gonk/TimeSetting.cpp
rename to dom/system/gonk/TimeZoneSettingObserver.cpp
--- a/dom/system/gonk/TimeSetting.cpp
+++ b/dom/system/gonk/TimeZoneSettingObserver.cpp
@@ -1,44 +1,59 @@
 /* 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 "base/message_loop.h"
 #include "jsapi.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Hal.h"
 #include "mozilla/Services.h"
+#include "mozilla/StaticPtr.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsIJSContextStack.h"
+#include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
 #include "nsJSUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
-#include "TimeSetting.h"
+#include "TimeZoneSettingObserver.h"
 #include "xpcpublic.h"
 
 #undef LOG
-#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Time Setting" , ## args)
-#define ERR(args...)  __android_log_print(ANDROID_LOG_ERROR, "Time Setting" , ## args)
+#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Time Zone Setting" , ## args)
+#define ERR(args...)  __android_log_print(ANDROID_LOG_ERROR, "Time Zone Setting" , ## args)
 
 #define TIME_TIMEZONE       "time.timezone"
 #define MOZSETTINGS_CHANGED "mozsettings-changed"
 
-namespace mozilla {
-namespace system {
+using namespace mozilla;
+
+namespace {
 
-class InitTimezoneCb MOZ_FINAL : public nsISettingsServiceCallback
+class TimeZoneSettingObserver : public nsIObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  TimeZoneSettingObserver();
+  virtual ~TimeZoneSettingObserver();
+  static nsresult SetTimeZone(const JS::Value &aValue, JSContext *aContext);
+};
+
+class TimeZoneSettingCb MOZ_FINAL : public nsISettingsServiceCallback
 {
 public:
   NS_DECL_ISUPPORTS
 
-  InitTimezoneCb() {}
+  TimeZoneSettingCb() {}
 
   NS_IMETHOD Handle(const nsAString &aName, const JS::Value &aResult, JSContext *aContext) {
     // If we don't have time.timezone value in the settings, we need
     // to initialize the settings based on the current system timezone
     // to make settings consistent with system. This usually happens
     // at the very first boot. After that, settings must have a value.
     if (aResult.isNull()) {
       // Get the current system timezone and convert it to a JS string.
@@ -56,31 +71,31 @@ public:
       }
       settingsService->CreateLock(getter_AddRefs(lock));
       lock->Set(TIME_TIMEZONE, STRING_TO_JSVAL(jsStr), nullptr, nullptr);
       return NS_OK;
     }
 
     // Set the system timezone based on the current settings.
     if (aResult.isString()) {
-      return TimeSetting::SetTimezone(aResult, aContext);
+      return TimeZoneSettingObserver::SetTimeZone(aResult, aContext);
     }
 
     return NS_OK;
   }
 
   NS_IMETHOD HandleError(const nsAString &aName, JSContext *aContext) {
-    ERR("InitTimezoneCb::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
+    ERR("TimeZoneSettingCb::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
     return NS_OK;
   }
 };
 
-NS_IMPL_ISUPPORTS1(InitTimezoneCb, nsISettingsServiceCallback)
+NS_IMPL_ISUPPORTS1(TimeZoneSettingCb, nsISettingsServiceCallback)
 
-TimeSetting::TimeSetting()
+TimeZoneSettingObserver::TimeZoneSettingObserver()
 {
   // Setup an observer to watch changes to the setting.
   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
   if (!observerService) {
     ERR("GetObserverService failed");
     return;
   }
   nsresult rv;
@@ -95,21 +110,21 @@ TimeSetting::TimeSetting()
   nsCOMPtr<nsISettingsServiceLock> lock;
   nsCOMPtr<nsISettingsService> settingsService =
     do_GetService("@mozilla.org/settingsService;1");
   if (!settingsService) {
     ERR("Failed to get settingsLock service!");
     return;
   }
   settingsService->CreateLock(getter_AddRefs(lock));
-  nsCOMPtr<nsISettingsServiceCallback> callback = new InitTimezoneCb();
+  nsCOMPtr<nsISettingsServiceCallback> callback = new TimeZoneSettingCb();
   lock->Get(TIME_TIMEZONE, callback);
 }
 
-nsresult TimeSetting::SetTimezone(const JS::Value &aValue, JSContext *aContext)
+nsresult TimeZoneSettingObserver::SetTimeZone(const JS::Value &aValue, JSContext *aContext)
 {
   // Convert the JS value to a nsCString type.
   nsDependentJSString valueStr;
   if (!valueStr.init(aContext, aValue.toString())) {
     ERR("Failed to convert JS value to nsCString");
     return NS_ERROR_FAILURE;
   }
   nsCString newTimezone = NS_ConvertUTF16toUTF8(valueStr);
@@ -118,28 +133,28 @@ nsresult TimeSetting::SetTimezone(const 
   nsCString curTimezone = hal::GetTimezone();
   if (!curTimezone.Equals(newTimezone)) {
     hal::SetTimezone(newTimezone);
   }
 
   return NS_OK;
 }
 
-TimeSetting::~TimeSetting()
+TimeZoneSettingObserver::~TimeZoneSettingObserver()
 {
   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
   if (observerService) {
     observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
   }
 }
 
-NS_IMPL_ISUPPORTS1(TimeSetting, nsIObserver)
+NS_IMPL_ISUPPORTS1(TimeZoneSettingObserver, nsIObserver)
 
 NS_IMETHODIMP
-TimeSetting::Observe(nsISupports *aSubject,
+TimeZoneSettingObserver::Observe(nsISupports *aSubject,
                      const char *aTopic,
                      const PRUnichar *aData)
 {
   if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
     return NS_OK;
   }
 
   // Note that this function gets called for any and all settings changes,
@@ -185,13 +200,25 @@ TimeSetting::Observe(nsISupports *aSubje
   // Get the value, which should be a JS string like "America/Chicago".
   JS::Value value;
   if (!JS_GetProperty(cx, &obj, "value", &value) ||
       !value.isString()) {
     return NS_OK;
   }
 
   // Set the system timezone.
-  return SetTimezone(value, cx);
+  return SetTimeZone(value, cx);
+}
+
+} // anonymous namespace
+
+static mozilla::StaticRefPtr<TimeZoneSettingObserver> sTimeZoneSettingObserver;
+namespace mozilla {
+namespace system {
+void
+InitializeTimeZoneSettingObserver()
+{
+  sTimeZoneSettingObserver = new TimeZoneSettingObserver();
+  ClearOnShutdown(&sTimeZoneSettingObserver);
 }
 
 } // namespace system
 } // namespace mozilla
rename from dom/system/gonk/TimeSetting.h
rename to dom/system/gonk/TimeZoneSettingObserver.h
--- a/dom/system/gonk/TimeSetting.h
+++ b/dom/system/gonk/TimeZoneSettingObserver.h
@@ -1,31 +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/. */
 
 #ifndef mozilla_system_timesetting_h__
 #define mozilla_system_timesetting_h__
 
-#include "jspubtd.h"
-#include "nsIObserver.h"
-
 namespace mozilla {
 namespace system {
 
-class ResultListener;
-
-class TimeSetting : public nsIObserver
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
-
-  TimeSetting();
-  virtual ~TimeSetting();
-  static nsresult SetTimezone(const JS::Value &aValue, JSContext *aContext);
-};
+// Initialize TimeZoneSettingObserver which observes the time zone change
+// event from settings service. When receiving the event, it modifies the
+// system time zone.
+void InitializeTimeZoneSettingObserver();
 
 } // namespace system
 } // namespace mozilla
 
 #endif // mozilla_system_timesetting_h__
 
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -925,16 +925,21 @@ const PDU_ST_3_SME_BUSY          = 0x61;
 const PDU_ST_3_SME_NO_RESPONSE   = 0x62;
 const PDU_ST_3_SERVICE_REJECTED  = 0x63;
 const PDU_ST_3_QOS_UNAVAILABLE   = 0x64;
 const PDU_ST_3_SME_ERROR         = 0x65;
 const PDU_ST_3_RESERVED_BEGIN    = 0x66;
 const PDU_ST_3_SC_SPECIFIC_BEGIN = 0x70;
 const PDU_ST_3_SC_SPECIFIC_END   = 0x7F;
 
+const GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE = "not-applicable";
+const GECKO_SMS_DELIVERY_STATUS_SUCCESS        = "success";
+const GECKO_SMS_DELIVERY_STATUS_PENDING        = "pending";
+const GECKO_SMS_DELIVERY_STATUS_ERROR          = "error";
+
 // User Data max length in septets
 const PDU_MAX_USER_DATA_7BIT = 160;
 // User Data max length in octets
 const PDU_MAX_USER_DATA_8BIT = 140;
 // User Data max length in chars
 const PDU_MAX_USER_DATA_UCS2 = 70;
 
 // PID - Protocol Indicator
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -3859,31 +3859,30 @@ let RIL = {
     // Pending. Waiting for next status report.
     if ((status >>> 5) == 0x01) {
       if (DEBUG) debug("SMS-STATUS-REPORT: delivery still pending");
       return PDU_FCS_OK;
     }
 
     delete this._pendingSentSmsMap[message.messageRef];
 
-    if ((status >>> 5) != 0x00) {
-      if (DEBUG) debug("SMS-STATUS-REPORT: delivery failed");
-      // It seems unlikely to get a result code for a failure to deliver.
-      // Even if, we don't want to do anything with this.
+    if ((options.segmentMaxSeq > 1)
+        && (options.segmentSeq < options.segmentMaxSeq)) {
+      // Not the last segment.
       return PDU_FCS_OK;
     }
 
-    if ((options.segmentMaxSeq == 1)
-        && (options.segmentSeq == options.segmentMaxSeq)) {
-      // Last segment delivered with success. Report it.
-      this.sendDOMMessage({
-        rilMessageType: "sms-delivered",
-        envelopeId: options.envelopeId,
-      });
-    }
+    let deliveryStatus = ((status >>> 5) == 0x00)
+                       ? GECKO_SMS_DELIVERY_STATUS_SUCCESS
+                       : GECKO_SMS_DELIVERY_STATUS_ERROR;
+    this.sendDOMMessage({
+      rilMessageType: "sms-delivery",
+      envelopeId: options.envelopeId,
+      deliveryStatus: deliveryStatus
+    });
 
     return PDU_FCS_OK;
   },
 
   /**
    * Helper for processing received multipart SMS.
    *
    * @return null for handled segments, and an object containing full message
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -87,25 +87,25 @@ public class GeckoAppShell
 
     public static native void processNextNativeEvent();
 
     public static native void notifyBatteryChange(double aLevel, boolean aCharging, double aRemainingTime);
 
     public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
     public static native int  saveMessageInSentbox(String aReceiver, String aBody, long aTimestamp);
     public static native void notifySmsSent(int aId, String aReceiver, String aBody, long aTimestamp, int aRequestId, long aProcessId);
-    public static native void notifySmsDelivered(int aId, String aReceiver, String aBody, long aTimestamp);
+    public static native void notifySmsDelivery(int aId, int aDeliveryStatus, String aReceiver, String aBody, long aTimestamp);
     public static native void notifySmsSendFailed(int aError, int aRequestId, long aProcessId);
-    public static native void notifyGetSms(int aId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
+    public static native void notifyGetSms(int aId, int aDeliveryStatus, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifyGetSmsFailed(int aError, int aRequestId, long aProcessId);
     public static native void notifySmsDeleted(boolean aDeleted, int aRequestId, long aProcessId);
     public static native void notifySmsDeleteFailed(int aError, int aRequestId, long aProcessId);
     public static native void notifyNoMessageInList(int aRequestId, long aProcessId);
-    public static native void notifyListCreated(int aListId, int aMessageId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
-    public static native void notifyGotNextMessage(int aMessageId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
+    public static native void notifyListCreated(int aListId, int aMessageId, int aDeliveryStatus, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
+    public static native void notifyGotNextMessage(int aMessageId, int aDeliveryStatus, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifyReadingMessageListFailed(int aError, int aRequestId, long aProcessId);
     public static native void onSurfaceTextureFrameAvailable(Object surfaceTexture, int id);
 
     // A looper thread, accessed by GeckoAppShell.getHandler
     private static class LooperThread extends Thread {
         public SynchronousQueue<Handler> mHandlerQueue =
             new SynchronousQueue<Handler>();
         
--- a/embedding/android/GeckoSmsManager.java
+++ b/embedding/android/GeckoSmsManager.java
@@ -309,25 +309,43 @@ public class GeckoSmsManager
 
   private final static Uri kSmsContentUri     = Uri.parse("content://sms");
   private final static Uri kSmsSentContentUri = Uri.parse("content://sms/sent");
 
   private final static int kSmsTypeInbox      = 1;
   private final static int kSmsTypeSentbox    = 2;
 
   /*
-   * Keep the following error codes in syng with |DeliveryState| in:
+   * Keep the following state codes in syng with |DeliveryState| in:
    * dom/sms/src/Types.h
    */
   private final static int kDeliveryStateSent     = 0;
   private final static int kDeliveryStateReceived = 1;
   private final static int kDeliveryStateUnknown  = 2;
   private final static int kDeliveryStateEndGuard = 3;
 
-  private final static String[] kRequiredMessageRows = new String[] { "_id", "address", "body", "date", "type" };
+  /*
+   * Keep the following status codes in sync with |DeliveryStatus| in:
+   * dom/sms/src/Types.h
+   */
+  private final static int kDeliveryStatusNotApplicable = 0;
+  private final static int kDeliveryStatusSuccess       = 1;
+  private final static int kDeliveryStatusPending       = 2;
+  private final static int kDeliveryStatusError         = 3;
+
+  /*
+   * android.provider.Telephony.Sms.STATUS_*. Duplicated because they're not
+   * part of Android public API.
+   */
+  private final static int kInternalDeliveryStatusNone     = -1;
+  private final static int kInternalDeliveryStatusComplete = 0;
+  private final static int kInternalDeliveryStatusPending  = 32;
+  private final static int kInternalDeliveryStatusFailed   = 64;
+
+  private final static String[] kRequiredMessageRows = new String[] { "_id", "address", "body", "date", "type", "status" };
 
   public GeckoSmsManager() {
     SmsIOThread.getInstance().start();
   }
 
   public void start() {
     IntentFilter smsFilter = new IntentFilter();
     smsFilter.addAction(GeckoSmsManager.ACTION_SMS_RECEIVED);
@@ -415,19 +433,22 @@ public class GeckoSmsManager
 
       if (envelope.isFailing(part)) {
         if (part == Envelope.SubParts.SENT_PART) {
           GeckoAppShell.notifySmsSendFailed(envelope.getError(),
                                             bundle.getInt("requestId"),
                                             bundle.getLong("processId"));
           Log.i("GeckoSmsManager", "SMS sending failed!");
         } else {
-          // It seems unlikely to get a result code for a failure to deliver.
-          // Even if, we don't want to do anything with this.
-          Log.e("GeckoSmsManager", "SMS failed to be delivered... is that even possible?");
+          GeckoAppShell.notifySmsDelivery(envelope.getMessageId(),
+                                          kDeliveryStatusError,
+                                          bundle.getString("number"),
+                                          bundle.getString("message"),
+                                          envelope.getMessageTimestamp());
+          Log.i("GeckoSmsManager", "SMS delivery failed!");
         }
       } else {
         if (part == Envelope.SubParts.SENT_PART) {
           String number = bundle.getString("number");
           String message = bundle.getString("message");
           long timestamp = System.currentTimeMillis();
 
           int id = GeckoAppShell.saveMessageInSentbox(number, message, timestamp);
@@ -436,20 +457,21 @@ public class GeckoSmsManager
                                       bundle.getInt("requestId"),
                                       bundle.getLong("processId"));
 
           envelope.setMessageId(id);
           envelope.setMessageTimestamp(timestamp);
 
           Log.i("GeckoSmsManager", "SMS sending was successfull!");
         } else {
-          GeckoAppShell.notifySmsDelivered(envelope.getMessageId(),
-                                           bundle.getString("number"),
-                                           bundle.getString("message"),
-                                           envelope.getMessageTimestamp());
+          GeckoAppShell.notifySmsDelivery(envelope.getMessageId(),
+                                          kDeliveryStatusSuccess,
+                                          bundle.getString("number"),
+                                          bundle.getString("message"),
+                                          envelope.getMessageTimestamp());
           Log.i("GeckoSmsManager", "SMS succesfully delivered!");
         }
       }
 
       // Destroy the envelope object only if the SMS has been sent and delivered.
       if (!envelope.arePartsRemaining(Envelope.SubParts.SENT_PART) &&
           !envelope.arePartsRemaining(Envelope.SubParts.DELIVERED_PART)) {
         postman.destroyEnvelope(envelopeId);
@@ -550,16 +572,18 @@ public class GeckoSmsManager
   }
 
   public int saveSentMessage(String aRecipient, String aBody, long aDate) {
     try {
       ContentValues values = new ContentValues();
       values.put("address", aRecipient);
       values.put("body", aBody);
       values.put("date", aDate);
+      // Always 'PENDING' because we always request status report.
+      values.put("status", kInternalDeliveryStatusPending);
 
       ContentResolver cr = GeckoApp.mAppContext.getContentResolver();
       Uri uri = cr.insert(kSmsSentContentUri, values);
 
       long id = ContentUris.parseId(uri);
 
       // The DOM API takes a 32bits unsigned int for the id. It's unlikely that
       // we happen to need more than that but it doesn't cost to check.
@@ -608,28 +632,32 @@ public class GeckoSmsManager
 
           cursor.moveToFirst();
 
           if (cursor.getInt(cursor.getColumnIndex("_id")) != mMessageId) {
             throw new UnmatchingIdException();
           }
 
           int type = cursor.getInt(cursor.getColumnIndex("type"));
+          int deliveryStatus;
           String sender = "";
           String receiver = "";
 
           if (type == kSmsTypeInbox) {
+            deliveryStatus = kDeliveryStatusSuccess;
             sender = cursor.getString(cursor.getColumnIndex("address"));
           } else if (type == kSmsTypeSentbox) {
+            deliveryStatus = getGeckoDeliveryStatus(cursor.getInt(cursor.getColumnIndex("status")));
             receiver = cursor.getString(cursor.getColumnIndex("address"));
           } else {
             throw new InvalidTypeException();
           }
 
           GeckoAppShell.notifyGetSms(cursor.getInt(cursor.getColumnIndex("_id")),
+                                     deliveryStatus,
                                      receiver, sender,
                                      cursor.getString(cursor.getColumnIndex("body")),
                                      cursor.getLong(cursor.getColumnIndex("date")),
                                      mRequestId, mProcessId);
         } catch (NotFoundException e) {
           Log.i("GeckoSmsManager", "Message id " + mMessageId + " not found");
           GeckoAppShell.notifyGetSmsFailed(kNotFoundError, mRequestId, mProcessId);
         } catch (UnmatchingIdException e) {
@@ -773,31 +801,35 @@ public class GeckoSmsManager
           if (cursor.getCount() == 0) {
             GeckoAppShell.notifyNoMessageInList(mRequestId, mProcessId);
             return;
           }
 
           cursor.moveToFirst();
 
           int type = cursor.getInt(cursor.getColumnIndex("type"));
+          int deliveryStatus;
           String sender = "";
           String receiver = "";
 
           if (type == kSmsTypeInbox) {
+            deliveryStatus = kDeliveryStatusSuccess;
             sender = cursor.getString(cursor.getColumnIndex("address"));
           } else if (type == kSmsTypeSentbox) {
+            deliveryStatus = getGeckoDeliveryStatus(cursor.getInt(cursor.getColumnIndex("status")));
             receiver = cursor.getString(cursor.getColumnIndex("address"));
           } else {
             throw new UnexpectedDeliveryStateException();
           }
 
           int listId = MessagesListManager.getInstance().add(cursor);
           closeCursor = false;
           GeckoAppShell.notifyListCreated(listId,
                                           cursor.getInt(cursor.getColumnIndex("_id")),
+                                          deliveryStatus,
                                           receiver, sender,
                                           cursor.getString(cursor.getColumnIndex("body")),
                                           cursor.getLong(cursor.getColumnIndex("date")),
                                           mRequestId, mProcessId);
         } catch (UnexpectedDeliveryStateException e) {
           Log.e("GeckoSmsManager", "Unexcepted delivery state type: " + e);
           GeckoAppShell.notifyReadingMessageListFailed(kUnknownError, mRequestId, mProcessId);
         } catch (Exception e) {
@@ -839,29 +871,33 @@ public class GeckoSmsManager
 
           if (!cursor.moveToNext()) {
             MessagesListManager.getInstance().remove(mListId);
             GeckoAppShell.notifyNoMessageInList(mRequestId, mProcessId);
             return;
           }
 
           int type = cursor.getInt(cursor.getColumnIndex("type"));
+          int deliveryStatus;
           String sender = "";
           String receiver = "";
 
           if (type == kSmsTypeInbox) {
+            deliveryStatus = kDeliveryStatusSuccess;
             sender = cursor.getString(cursor.getColumnIndex("address"));
           } else if (type == kSmsTypeSentbox) {
+            deliveryStatus = getGeckoDeliveryStatus(cursor.getInt(cursor.getColumnIndex("status")));
             receiver = cursor.getString(cursor.getColumnIndex("address"));
           } else {
             throw new UnexpectedDeliveryStateException();
           }
 
           int listId = MessagesListManager.getInstance().add(cursor);
           GeckoAppShell.notifyGotNextMessage(cursor.getInt(cursor.getColumnIndex("_id")),
+                                             deliveryStatus,
                                              receiver, sender,
                                              cursor.getString(cursor.getColumnIndex("body")),
                                              cursor.getLong(cursor.getColumnIndex("date")),
                                              mRequestId, mProcessId);
         } catch (UnexpectedDeliveryStateException e) {
           Log.e("GeckoSmsManager", "Unexcepted delivery state type: " + e);
           GeckoAppShell.notifyReadingMessageListFailed(kUnknownError, mRequestId, mProcessId);
         } catch (Exception e) {
@@ -885,16 +921,29 @@ public class GeckoSmsManager
     GeckoApp.mAppContext.unregisterReceiver(this);
   }
 
   public void shutdown() {
     SmsIOThread.getInstance().interrupt();
     MessagesListManager.getInstance().clear();
   }
 
+  private int getGeckoDeliveryStatus(int aDeliveryStatus) {
+    if (aDeliveryStatus == kInternalDeliveryStatusNone) {
+      return kDeliveryStatusNotApplicable;
+    }
+    if (aDeliveryStatus >= kInternalDeliveryStatusFailed) {
+      return kDeliveryStatusError;
+    }
+    if (aDeliveryStatus >= kInternalDeliveryStatusPending) {
+      return kDeliveryStatusPending;
+    }
+    return kDeliveryStatusSuccess;
+  }
+
   class IdTooHighException extends Exception {
     private static final long serialVersionUID = 395697882128640L;
   }
 
   class InvalidTypeException extends Exception {
     private static final long serialVersionUID = 23359904803795434L;
   }
 
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -42,17 +42,24 @@
 
 #include "SourceSurfaceRawData.h"
 
 #include "DrawEventRecorder.h"
 
 #include "Logging.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo *sGFX2DLog = PR_NewLogModule("gfx2d");
+PRLogModuleInfo *
+GetGFX2DLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("gfx2d");
+  return sLog;
+}
 #endif
 
 // The following code was largely taken from xpcom/glue/SSE.cpp and
 // made a little simpler.
 enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 };
 
 #ifdef HAVE_CPUID_H
 
--- a/gfx/2d/Logging.h
+++ b/gfx/2d/Logging.h
@@ -15,17 +15,17 @@
 
 #ifdef WIN32
 #include <windows.h>
 #endif
 
 #ifdef PR_LOGGING
 #include <prlog.h>
 
-extern PRLogModuleInfo *sGFX2DLog;
+extern PRLogModuleInfo *GetGFX2DLog();
 #endif
 
 namespace mozilla {
 namespace gfx {
 
 const int LOG_DEBUG = 1;
 const int LOG_WARNING = 2;
 
@@ -46,17 +46,17 @@ inline PRLogModuleLevel PRLogLevelForLev
 extern int sGfxLogLevel;
 
 static inline void OutputMessage(const std::string &aString, int aLevel) {
 #if defined(WIN32) && !defined(PR_LOGGING)
   if (aLevel >= sGfxLogLevel) {
     ::OutputDebugStringA(aString.c_str());
   }
 #elif defined(PR_LOGGING)
-  if (PR_LOG_TEST(sGFX2DLog, PRLogLevelForLevel(aLevel))) {
+  if (PR_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) {
     PR_LogPrint(aString.c_str());
   }
 #else
   if (aLevel >= sGfxLogLevel) {
     printf("%s", aString.c_str());
   }
 #endif
 }
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -57,22 +57,29 @@
 #ifdef XP_WIN
 #include "nsIWindowsRegKey.h"
 #include <windows.h>
 #endif
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *gFontInfoLog = PR_NewLogModule("fontInfoLog");
+static PRLogModuleInfo *
+GetFontInfoLog()
+{
+    static PRLogModuleInfo *sLog;
+    if (!sLog)
+        sLog = PR_NewLogModule("fontInfoLog");
+    return sLog;
+}
 #endif /* PR_LOGGING */
 
 #undef LOG
-#define LOG(args) PR_LOG(gFontInfoLog, PR_LOG_DEBUG, args)
-#define LOG_ENABLED() PR_LOG_TEST(gFontInfoLog, PR_LOG_DEBUG)
+#define LOG(args) PR_LOG(GetFontInfoLog(), PR_LOG_DEBUG, args)
+#define LOG_ENABLED() PR_LOG_TEST(GetFontInfoLog(), PR_LOG_DEBUG)
 
 static __inline void
 BuildKeyNameFromFontName(nsAString &aName)
 {
 #ifdef XP_WIN
     if (aName.Length() >= LF_FACESIZE)
         aName.Truncate(LF_FACESIZE - 1);
 #endif
--- a/gfx/thebes/gfxFT2Fonts.cpp
+++ b/gfx/thebes/gfxFT2Fonts.cpp
@@ -34,17 +34,24 @@
 #include "nsCRT.h"
 #include "nsXULAppAPI.h"
 
 #include "prlog.h"
 #include "prinit.h"
 
 #include "mozilla/Preferences.h"
 
-static PRLogModuleInfo *gFontLog = PR_NewLogModule("ft2fonts");
+static PRLogModuleInfo *
+GetFontLog()
+{
+    static PRLogModuleInfo *sLog;
+    if (!sLog)
+        sLog = PR_NewLogModule("ft2fonts");
+    return sLog;
+}
 
 // rounding and truncation functions for a Freetype floating point number
 // (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
 // part and low 6 bits for the fractional part.
 #define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
 #define MOZ_FT_TRUNC(x) ((x) >> 6)
 #define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
         MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
@@ -334,27 +341,27 @@ gfxFT2FontGroup::WhichPrefFontSupportsCh
     selectedFont = WhichFontSupportsChar(fonts, aCh);
 
     // otherwise search prefs
     if (!selectedFont) {
         uint32_t unicodeRange = FindCharUnicodeRange(aCh);
 
         /* special case CJK */
         if (unicodeRange == kRangeSetCJK) {
-            if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG)) {
-                PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
+            if (PR_LOG_TEST(GetFontLog(), PR_LOG_DEBUG)) {
+                PR_LOG(GetFontLog(), PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
             }
 
             nsAutoTArray<nsRefPtr<gfxFontEntry>, 15> fonts;
             GetCJKPrefFonts(fonts);
             selectedFont = WhichFontSupportsChar(fonts, aCh);
         } else {
             nsIAtom *langGroup = LangGroupFromUnicodeRange(unicodeRange);
             if (langGroup) {
-                PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", nsAtomCString(langGroup).get()));
+                PR_LOG(GetFontLog(), PR_LOG_DEBUG, (" - Trying to find fonts for: %s", nsAtomCString(langGroup).get()));
 
                 nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
                 GetPrefFonts(langGroup, fonts);
                 selectedFont = WhichFontSupportsChar(fonts, aCh);
             }
         }
     }
 
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -19,21 +19,28 @@
 #include "woff.h"
 
 #include "opentype-sanitiser.h"
 #include "ots-memory-stream.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-PRLogModuleInfo *gfxUserFontSet::sUserFontsLog = PR_NewLogModule("userfonts");
+PRLogModuleInfo *
+gfxUserFontSet::GetUserFontsLog()
+{
+    static PRLogModuleInfo *sLog;
+    if (!sLog)
+        sLog = PR_NewLogModule("userfonts");
+    return sLog;
+}
 #endif /* PR_LOGGING */
 
-#define LOG(args) PR_LOG(sUserFontsLog, PR_LOG_DEBUG, args)
-#define LOG_ENABLED() PR_LOG_TEST(sUserFontsLog, PR_LOG_DEBUG)
+#define LOG(args) PR_LOG(GetUserFontsLog(), PR_LOG_DEBUG, args)
+#define LOG_ENABLED() PR_LOG_TEST(GetUserFontsLog(), PR_LOG_DEBUG)
 
 static uint64_t sFontSetGeneration = LL_INIT(0, 0);
 
 // TODO: support for unicode ranges not yet implemented
 
 gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
              gfxMixedFontFamily *aFamily,
              uint32_t aWeight,
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -271,17 +271,17 @@ protected:
     static bool OTSMessage(void *aUserData, const char *format, ...);
 #endif
 
     // font families defined by @font-face rules
     nsRefPtrHashtable<nsStringHashKey, gfxMixedFontFamily> mFontFamilies;
 
     uint64_t        mGeneration;
 
-    static PRLogModuleInfo *sUserFontsLog;
+    static PRLogModuleInfo* GetUserFontsLog();
 
 private:
     static void CopyWOFFMetadata(const uint8_t* aFontData,
                                  uint32_t aLength,
                                  nsTArray<uint8_t>* aMetadata,
                                  uint32_t* aMetaOrigLen);
 };
 
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -50,17 +50,25 @@ using namespace mozilla::services;
     } else {                                      \
       return hal_impl::_call;                     \
     }                                             \
   } while (0)
 
 namespace mozilla {
 namespace hal {
 
-PRLogModuleInfo *sHalLog = PR_NewLogModule("hal");
+PRLogModuleInfo *
+GetHalLog()
+{
+  static PRLogModuleInfo *sHalLog;
+  if (!sHalLog) {
+    sHalLog = PR_NewLogModule("hal");
+  }
+  return sHalLog;
+}
 
 namespace {
 
 void
 AssertMainThread()
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -42,18 +42,18 @@ class Observer;
 
 namespace hal {
 
 typedef Observer<void_t> AlarmObserver;
 typedef Observer<ScreenConfiguration> ScreenConfigurationObserver;
 
 class WindowIdentifier;
 
-extern PRLogModuleInfo *sHalLog;
-#define HAL_LOG(msg) PR_LOG(mozilla::hal::sHalLog, PR_LOG_DEBUG, msg)
+extern PRLogModuleInfo *GetHalLog();
+#define HAL_LOG(msg) PR_LOG(mozilla::hal::GetHalLog(), PR_LOG_DEBUG, msg)
 
 typedef Observer<int64_t> SystemClockChangeObserver;
 typedef Observer<SystemTimezoneChangeInformation> SystemTimezoneChangeObserver;
 
 } // namespace hal
 
 namespace MOZ_HAL_NAMESPACE {
 
--- a/image/decoders/nsBMPDecoder.cpp
+++ b/image/decoders/nsBMPDecoder.cpp
@@ -16,17 +16,24 @@
 #include "nsIInputStream.h"
 #include "RasterImage.h"
 #include "imgIContainerObserver.h"
 
 namespace mozilla {
 namespace image {
 
 #ifdef PR_LOGGING
-PRLogModuleInfo *gBMPLog = PR_NewLogModule("BMPDecoder");
+static PRLogModuleInfo *
+GetBMPLog()
+{
+  static PRLogModuleInfo *sBMPLog;
+  if (!sBMPLog)
+    sBMPLog = PR_NewLogModule("BMPDecoder");
+  return sBMPLog;
+}
 #endif
 
 // Convert from row (1..height) to absolute line (0..height-1)
 #define LINE(row) ((mBIH.height < 0) ? (-mBIH.height - (row)) : ((row) - 1))
 #define PIXEL_OFFSET(row, col) (LINE(row) * mBIH.width + col)
 
 nsBMPDecoder::nsBMPDecoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
  : Decoder(aImage, aObserver)
@@ -216,17 +223,17 @@ nsBMPDecoder::WriteInternal(const char* 
         aBuffer += toCopy;
     }
 
     // GetNumFrames is called to ensure that if at this point mPos == mLOH but
     // we have no data left to process, the next time WriteInternal is called
     // we won't enter this condition again.
     if (mPos == mLOH && GetFrameCount() == 0) {
         ProcessInfoHeader();
-        PR_LOG(gBMPLog, PR_LOG_DEBUG, ("BMP is %lix%lix%lu. compression=%lu\n",
+        PR_LOG(GetBMPLog(), PR_LOG_DEBUG, ("BMP is %lix%lix%lu. compression=%lu\n",
                mBIH.width, mBIH.height, mBIH.bpp, mBIH.compression));
         // Verify we support this bit depth
         if (mBIH.bpp != 1 && mBIH.bpp != 4 && mBIH.bpp != 8 &&
             mBIH.bpp != 16 && mBIH.bpp != 24 && mBIH.bpp != 32) {
           PostDataError();
           return;
         }
 
@@ -278,30 +285,30 @@ nsBMPDecoder::WriteInternal(const char* 
             mBIH.compression != BI_RLE4 && mBIH.compression != BI_BITFIELDS) {
           PostDataError();
           return;
         }
 
         // If we have RLE4 or RLE8 or BI_ALPHABITFIELDS, then ensure we
         // have valid BPP values before adding the frame
         if (mBIH.compression == BI_RLE8 && mBIH.bpp != 8) {
-          PR_LOG(gBMPLog, PR_LOG_DEBUG, 
+          PR_LOG(GetBMPLog(), PR_LOG_DEBUG, 
                  ("BMP RLE8 compression only supports 8 bits per pixel\n"));
           PostDataError();
           return;
         }
         if (mBIH.compression == BI_RLE4 && mBIH.bpp != 4 && mBIH.bpp != 1) {
-          PR_LOG(gBMPLog, PR_LOG_DEBUG, 
+          PR_LOG(GetBMPLog(), PR_LOG_DEBUG, 
                  ("BMP RLE4 compression only supports 4 bits per pixel\n"));
           PostDataError();
           return;
         }
         if (mBIH.compression == BI_ALPHABITFIELDS && 
             mBIH.bpp != 16 && mBIH.bpp != 32) {
-          PR_LOG(gBMPLog, PR_LOG_DEBUG, 
+          PR_LOG(GetBMPLog(), PR_LOG_DEBUG, 
                  ("BMP ALPHABITFIELDS only supports 16 or 32 bits per pixel\n"));
           PostDataError();
           return;
         }
 
         uint32_t imageLength;
         if (mBIH.compression == BI_RLE8 || mBIH.compression == BI_RLE4 || 
             mBIH.compression == BI_ALPHABITFIELDS) {
@@ -506,17 +513,17 @@ nsBMPDecoder::WriteInternal(const char* 
                     mRowBytes = 0;
 
                 }
             } while (aCount > 0);
         }
         else if ((mBIH.compression == BI_RLE8) || (mBIH.compression == BI_RLE4)) {
             if (((mBIH.compression == BI_RLE8) && (mBIH.bpp != 8)) || 
                 ((mBIH.compression == BI_RLE4) && (mBIH.bpp != 4) && (mBIH.bpp != 1))) {
-              PR_LOG(gBMPLog, PR_LOG_DEBUG, ("BMP RLE8/RLE4 compression only supports 8/4 bits per pixel\n"));
+              PR_LOG(GetBMPLog(), PR_LOG_DEBUG, ("BMP RLE8/RLE4 compression only supports 8/4 bits per pixel\n"));
               PostDataError();
               return;
             }
 
             while (aCount > 0) {
                 uint8_t byte;
 
                 switch(mState) {
--- a/image/decoders/nsJPEGDecoder.cpp
+++ b/image/decoders/nsJPEGDecoder.cpp
@@ -30,21 +30,36 @@ extern "C" {
 #endif
 
 static void cmyk_convert_rgb(JSAMPROW row, JDIMENSION width);
 
 namespace mozilla {
 namespace image {
 
 #if defined(PR_LOGGING)
-PRLogModuleInfo *gJPEGlog = PR_NewLogModule("JPEGDecoder");
-static PRLogModuleInfo *gJPEGDecoderAccountingLog = PR_NewLogModule("JPEGDecoderAccounting");
+static PRLogModuleInfo *
+GetJPEGLog()
+{
+  static PRLogModuleInfo *sJPEGLog;
+  if (!sJPEGLog)
+    sJPEGLog = PR_NewLogModule("JPEGDecoder");
+  return sJPEGLog;
+}
+
+static PRLogModuleInfo *
+GetJPEGDecoderAccountingLog()
+{
+  static PRLogModuleInfo *sJPEGDecoderAccountingLog;
+  if (!sJPEGDecoderAccountingLog)
+    sJPEGDecoderAccountingLog = PR_NewLogModule("JPEGDecoderAccounting");
+  return sJPEGDecoderAccountingLog;
+}
 #else
-#define gJPEGlog
-#define gJPEGDecoderAccountingLog
+#define GetJPEGLog()
+#define GetJPEGDecoderAccountingLog()
 #endif
 
 static qcms_profile*
 GetICCProfile(struct jpeg_decompress_struct &info)
 {
   JOCTET* profilebuf;
   uint32_t profileLength;
   qcms_profile* profile = nullptr;
@@ -85,34 +100,34 @@ nsJPEGDecoder::nsJPEGDecoder(RasterImage
   mBackBuffer = nullptr;
   mBackBufferLen = mBackBufferSize = mBackBufferUnreadLen = 0;
 
   mInProfile = nullptr;
   mTransform = nullptr;
 
   mCMSMode = 0;
 
-  PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+  PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
          ("nsJPEGDecoder::nsJPEGDecoder: Creating JPEG decoder %p",
           this));
 }
 
 nsJPEGDecoder::~nsJPEGDecoder()
 {
   // Step 8: Release JPEG decompression object
   mInfo.src = nullptr;
   jpeg_destroy_decompress(&mInfo);
 
   PR_FREEIF(mBackBuffer);
   if (mTransform)
     qcms_transform_release(mTransform);
   if (mInProfile)
     qcms_profile_release(mInProfile);
 
-  PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+  PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
          ("nsJPEGDecoder::~nsJPEGDecoder: Destroying JPEG decoder %p",
           this));
 }
 
 Telemetry::ID
 nsJPEGDecoder::SpeedHistogram()
 {
   return Telemetry::IMAGE_DECODE_SPEED_JPEG;
@@ -185,42 +200,42 @@ nsJPEGDecoder::WriteInternal(const char 
   // This cast to nsresult makes sense because setjmp() returns whatever we
   // passed to longjmp(), which was actually an nsresult.
   if ((error_code = (nsresult)setjmp(mErr.setjmp_buffer)) != NS_OK) {
     if (error_code == NS_ERROR_FAILURE) {
       PostDataError();
       /* Error due to corrupt stream - return NS_OK and consume silently
          so that libpr0n doesn't throw away a partial image load */
       mState = JPEG_SINK_NON_JPEG_TRAILER;
-      PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+      PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
              ("} (setjmp returned NS_ERROR_FAILURE)"));
       return;
     } else {
       /* Error due to reasons external to the stream (probably out of
          memory) - let libpr0n attempt to clean up, even though
          mozilla is seconds away from falling flat on its face. */
       PostDecoderError(error_code);
       mState = JPEG_ERROR;
-      PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+      PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
              ("} (setjmp returned an error)"));
       return;
     }
   }
 
-  PR_LOG(gJPEGlog, PR_LOG_DEBUG,
+  PR_LOG(GetJPEGLog(), PR_LOG_DEBUG,
          ("[this=%p] nsJPEGDecoder::Write -- processing JPEG data\n", this));
 
   switch (mState) {
   case JPEG_HEADER:
   {
-    LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::Write -- entering JPEG_HEADER case");
+    LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::Write -- entering JPEG_HEADER case");
 
     /* Step 3: read file parameters with jpeg_read_header() */
     if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED) {
-      PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+      PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
              ("} (JPEG_SUSPENDED)"));
       return; /* I/O suspension */
     }
 
     // Post our size to the superclass
     PostSize(mInfo.image_width, mInfo.image_height);
     if (HasError()) {
       // Setting the size led to an error.
@@ -262,34 +277,34 @@ nsJPEGDecoder::WriteInternal(const char 
       case JCS_CMYK:
       case JCS_YCCK:
 	  // qcms doesn't support cmyk
           mismatch = true;
         break;
       default:
         mState = JPEG_ERROR;
         PostDataError();
-        PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+        PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
                ("} (unknown colorpsace (1))"));
         return;
       }
 
       if (!mismatch) {
         qcms_data_type type;
         switch (mInfo.out_color_space) {
         case JCS_GRAYSCALE:
           type = QCMS_DATA_GRAY_8;
           break;
         case JCS_RGB:
           type = QCMS_DATA_RGB_8;
           break;
         default:
           mState = JPEG_ERROR;
           PostDataError();
-          PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+          PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
                  ("} (unknown colorpsace (2))"));
           return;
         }
 #if 0
         /* We don't currently support CMYK profiles. The following
          * code dealt with lcms types. Add something like this
          * back when we gain support for CMYK.
          */
@@ -336,17 +351,17 @@ nsJPEGDecoder::WriteInternal(const char 
       case JCS_CMYK:
       case JCS_YCCK:
         /* libjpeg can convert from YCCK to CMYK, but not to RGB */
         mInfo.out_color_space = JCS_CMYK;
         break;
       default:
         mState = JPEG_ERROR;
         PostDataError();
-        PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+        PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
                ("} (unknown colorpsace (3))"));
         return;
         break;
       }
     }
 
     /*
      * Don't allocate a giant and superfluous memory buffer
@@ -358,83 +373,83 @@ nsJPEGDecoder::WriteInternal(const char 
     jpeg_calc_output_dimensions(&mInfo);
 
     uint32_t imagelength;
     if (NS_FAILED(mImage.EnsureFrame(0, 0, 0, mInfo.image_width, mInfo.image_height,
                                      gfxASurface::ImageFormatRGB24,
                                      &mImageData, &imagelength))) {
       mState = JPEG_ERROR;
       PostDecoderError(NS_ERROR_OUT_OF_MEMORY);
-      PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+      PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
              ("} (could not initialize image frame)"));
       return;
     }
 
-    PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+    PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
            ("        JPEGDecoderAccounting: nsJPEGDecoder::Write -- created image frame with %ux%u pixels",
             mInfo.image_width, mInfo.image_height));
 
     // Tell the superclass we're starting a frame
     PostFrameStart();
 
     mState = JPEG_START_DECOMPRESS;
   }
 
   case JPEG_START_DECOMPRESS:
   {
-    LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::Write -- entering JPEG_START_DECOMPRESS case");
+    LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::Write -- entering JPEG_START_DECOMPRESS case");
     /* Step 4: set parameters for decompression */
 
     /* FIXME -- Should reset dct_method and dither mode
      * for final pass of progressive JPEG
      */
     mInfo.dct_method =  JDCT_ISLOW;
     mInfo.dither_mode = JDITHER_FS;
     mInfo.do_fancy_upsampling = TRUE;
     mInfo.enable_2pass_quant = FALSE;
     mInfo.do_block_smoothing = TRUE;
 
     /* Step 5: Start decompressor */
     if (jpeg_start_decompress(&mInfo) == FALSE) {
-      PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+      PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
              ("} (I/O suspension after jpeg_start_decompress())"));
       return; /* I/O suspension */
     }
 
 
     /* If this is a progressive JPEG ... */
     mState = mInfo.buffered_image ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL;
   }
 
   case JPEG_DECOMPRESS_SEQUENTIAL:
   {
     if (mState == JPEG_DECOMPRESS_SEQUENTIAL)
     {
-      LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::Write -- JPEG_DECOMPRESS_SEQUENTIAL case");
+      LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::Write -- JPEG_DECOMPRESS_SEQUENTIAL case");
       
       bool suspend;
       OutputScanlines(&suspend);
       
       if (suspend) {
-        PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+        PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
                ("} (I/O suspension after OutputScanlines() - SEQUENTIAL)"));
         return; /* I/O suspension */
       }
       
       /* If we've completed image output ... */
       NS_ASSERTION(mInfo.output_scanline == mInfo.output_height, "We didn't process all of the data!");
       mState = JPEG_DONE;
     }
   }
 
   case JPEG_DECOMPRESS_PROGRESSIVE:
   {
     if (mState == JPEG_DECOMPRESS_PROGRESSIVE)
     {
-      LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::Write -- JPEG_DECOMPRESS_PROGRESSIVE case");
+      LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::Write -- JPEG_DECOMPRESS_PROGRESSIVE case");
 
       int status;
       do {
         status = jpeg_consume_input(&mInfo);
       } while ((status != JPEG_SUSPENDED) &&
                (status != JPEG_REACHED_EOI));
 
       for (;;) {
@@ -445,17 +460,17 @@ nsJPEGDecoder::WriteInternal(const char 
              and we have enough data for a complete scan, force output
              of the last full scan */
           if ((mInfo.output_scan_number == 0) &&
               (scan > 1) &&
               (status != JPEG_REACHED_EOI))
             scan--;
 
           if (!jpeg_start_output(&mInfo, scan)) {
-            PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+            PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
                    ("} (I/O suspension after jpeg_start_output() - PROGRESSIVE)"));
             return; /* I/O suspension */
           }
         }
 
         if (mInfo.output_scanline == 0xffffff)
           mInfo.output_scanline = 0;
 
@@ -463,25 +478,25 @@ nsJPEGDecoder::WriteInternal(const char 
         OutputScanlines(&suspend);
 
         if (suspend) {
           if (mInfo.output_scanline == 0) {
             /* didn't manage to read any lines - flag so we don't call
                jpeg_start_output() multiple times for the same scan */
             mInfo.output_scanline = 0xffffff;
           }
-          PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+          PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
                  ("} (I/O suspension after OutputScanlines() - PROGRESSIVE)"));
           return; /* I/O suspension */
         }
 
         if (mInfo.output_scanline == mInfo.output_height)
         {
           if (!jpeg_finish_output(&mInfo)) {
-            PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+            PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
                    ("} (I/O suspension after jpeg_finish_output() - PROGRESSIVE)"));
             return; /* I/O suspension */
           }
 
           if (jpeg_input_complete(&mInfo) &&
               (mInfo.input_scan_number == mInfo.output_scan_number))
             break;
 
@@ -490,42 +505,42 @@ nsJPEGDecoder::WriteInternal(const char 
       }
 
       mState = JPEG_DONE;
     }
   }
 
   case JPEG_DONE:
   {
-    LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::ProcessData -- entering JPEG_DONE case");
+    LOG_SCOPE(GetJPEGLog(), "nsJPEGDecoder::ProcessData -- entering JPEG_DONE case");
 
     /* Step 7: Finish decompression */
 
     if (jpeg_finish_decompress(&mInfo) == FALSE) {
-      PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+      PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
              ("} (I/O suspension after jpeg_finish_decompress() - DONE)"));
       return; /* I/O suspension */
     }
 
     mState = JPEG_SINK_NON_JPEG_TRAILER;
 
     /* we're done dude */
     break;
   }
   case JPEG_SINK_NON_JPEG_TRAILER:
-    PR_LOG(gJPEGlog, PR_LOG_DEBUG,
+    PR_LOG(GetJPEGLog(), PR_LOG_DEBUG,
            ("[this=%p] nsJPEGDecoder::ProcessData -- entering JPEG_SINK_NON_JPEG_TRAILER case\n", this));
 
     break;
 
   case JPEG_ERROR:
     NS_ABORT_IF_FALSE(0, "Should always return immediately after error and not re-enter decoder");
   }
 
-  PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
+  PR_LOG(GetJPEGDecoderAccountingLog(), PR_LOG_DEBUG,
          ("} (end of function)"));
   return;
 }
 
 void
 nsJPEGDecoder::NotifyDone()
 {
   PostFrameStop();
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -22,19 +22,33 @@
 #include "png.h"
 
 #include "gfxPlatform.h"
 
 namespace mozilla {
 namespace image {
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *gPNGLog = PR_NewLogModule("PNGDecoder");
-static PRLogModuleInfo *gPNGDecoderAccountingLog =
-                        PR_NewLogModule("PNGDecoderAccounting");
+static PRLogModuleInfo *
+GetPNGLog()
+{
+  static PRLogModuleInfo *sPNGLog;
+  if (!sPNGLog)
+    sPNGLog = PR_NewLogModule("PNGDecoder");
+  return sPNGLog;
+}
+
+static PRLogModuleInfo *
+GetPNGDecoderAccountingLog()
+{
+  static PRLogModuleInfo *sPNGDecoderAccountingLog;
+  if (!sPNGDecoderAccountingLog)
+    sPNGDecoderAccountingLog = PR_NewLogModule("PNGDecoderAccounting");
+  return sPNGDecoderAccountingLog;
+}
 #endif
 
 /* limit image dimensions (bug #251381) */
 #define MOZ_PNG_MAX_DIMENSION 1000000L
 
 // For size decodes
 #define WIDTH_OFFSET 16
 #define HEIGHT_OFFSET (WIDTH_OFFSET + 4)
@@ -94,17 +108,17 @@ void nsPNGDecoder::CreateFrame(png_uint_
 #ifdef PNG_APNG_SUPPORTED
   if (png_get_valid(mPNG, mInfo, PNG_INFO_acTL))
     SetAnimFrameInfo();
 #endif
 
   // Tell the superclass we're starting a frame
   PostFrameStart();
 
-  PR_LOG(gPNGDecoderAccountingLog, PR_LOG_DEBUG,
+  PR_LOG(GetPNGDecoderAccountingLog(), PR_LOG_DEBUG,
          ("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created "
           "image frame with %dx%d pixels in container %p",
           width, height,
           &mImage));
 
   mFrameHasNoAlpha = true;
 }
 
@@ -844,25 +858,25 @@ nsPNGDecoder::end_callback(png_structp p
   decoder->EndImageFrame();
   decoder->PostDecodeDone();
 }
 
 
 void
 nsPNGDecoder::error_callback(png_structp png_ptr, png_const_charp error_msg)
 {
-  PR_LOG(gPNGLog, PR_LOG_ERROR, ("libpng error: %s\n", error_msg));
+  PR_LOG(GetPNGLog(), PR_LOG_ERROR, ("libpng error: %s\n", error_msg));
   longjmp(png_jmpbuf(png_ptr), 1);
 }
 
 
 void
 nsPNGDecoder::warning_callback(png_structp png_ptr, png_const_charp warning_msg)
 {
-  PR_LOG(gPNGLog, PR_LOG_WARNING, ("libpng warning: %s\n", warning_msg));
+  PR_LOG(GetPNGLog(), PR_LOG_WARNING, ("libpng warning: %s\n", warning_msg));
 }
 
 Telemetry::ID
 nsPNGDecoder::SpeedHistogram()
 {
   return Telemetry::IMAGE_DECODE_SPEED_PNG;
 }
 
--- a/image/public/ImageLogging.h
+++ b/image/public/ImageLogging.h
@@ -18,17 +18,17 @@
 #endif
 
 #include "prlog.h"
 #include "prinrval.h"
 #include "nsString.h"
 
 #if defined(PR_LOGGING)
 // Declared in imgRequest.cpp.
-extern PRLogModuleInfo *gImgLog;
+extern PRLogModuleInfo *GetImgLog();
 
 #define GIVE_ME_MS_NOW() PR_IntervalToMilliseconds(PR_IntervalNow())
 
 class LogScope {
 public:
   LogScope(PRLogModuleInfo *aLog, void *from, const nsACString &fn) :
     mLog(aLog), mFrom(from), mFunc(fn)
   {
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -42,19 +42,26 @@ using namespace mozilla::image;
 using namespace mozilla::layers;
 
 // a mask for flags that will affect the decoding
 #define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION)
 #define DECODE_FLAGS_DEFAULT 0
 
 /* Accounting for compressed data */
 #if defined(PR_LOGGING)
-static PRLogModuleInfo *gCompressedImageAccountingLog = PR_NewLogModule ("CompressedImageAccounting");
+static PRLogModuleInfo *
+GetCompressedImageAccountingLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("CompressedImageAccounting");
+  return sLog;
+}
 #else
-#define gCompressedImageAccountingLog
+#define GetCompressedImageAccountingLog()
 #endif
 
 // Tweakable progressive decoding parameters.  These are initialized to 0 here
 // because otherwise, we have to initialize them in a static initializer, which
 // makes us slower to start up.
 static uint32_t gDecodeBytesAtATime = 0;
 static uint32_t gMaxMSBeforeYield = 0;
 static bool gHQDownscaling = false;
@@ -86,17 +93,17 @@ InitPrefCaches()
  *
  * So this macro should be called when the desired failure behavior
  * is to put the container into an error state and return failure.
  * It goes without saying that macro won't compile outside of a
  * non-static RasterImage method.
  */
 #define LOG_CONTAINER_ERROR                      \
   PR_BEGIN_MACRO                                 \
-  PR_LOG (gImgLog, PR_LOG_ERROR,                 \
+  PR_LOG (GetImgLog(), PR_LOG_ERROR,             \
           ("RasterImage: [this=%p] Error "      \
            "detected at line %u for image of "   \
            "type %s\n", this, __LINE__,          \
            mSourceDataMimeType.get()));          \
   PR_END_MACRO
 
 #define CONTAINER_ENSURE_SUCCESS(status)      \
   PR_BEGIN_MACRO                              \
@@ -382,17 +389,17 @@ RasterImage::RasterImage(imgStatusTracke
 //******************************************************************************
 RasterImage::~RasterImage()
 {
   // Discardable statistics
   if (mDiscardable) {
     num_discardable_containers--;
     discardable_source_bytes -= mSourceData.Length();
 
-    PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG,
+    PR_LOG (GetCompressedImageAccountingLog(), PR_LOG_DEBUG,
             ("CompressedImageAccounting: destroying RasterImage %p.  "
              "Total Containers: %d, Discardable containers: %d, "
              "Total source bytes: %lld, Source bytes for discardable containers %lld",
              this,
              num_containers,
              num_discardable_containers,
              total_source_bytes,
              discardable_source_bytes));
@@ -1737,17 +1744,17 @@ RasterImage::AddSourceData(const char *a
       DecodeWorker::Singleton()->RequestDecode(this);
     }
   }
 
   // Statistics
   total_source_bytes += aCount;
   if (mDiscardable)
     discardable_source_bytes += aCount;
-  PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG,
+  PR_LOG (GetCompressedImageAccountingLog(), PR_LOG_DEBUG,
           ("CompressedImageAccounting: Added compressed data to RasterImage %p (%s). "
            "Total Containers: %d, Discardable containers: %d, "
            "Total source bytes: %lld, Source bytes for discardable containers %lld",
            this,
            mSourceDataMimeType.get(),
            num_containers,
            num_discardable_containers,
            total_source_bytes,
@@ -1811,20 +1818,20 @@ RasterImage::SourceDataComplete()
   if (mDecoder) {
     DecodeWorker::Singleton()->RequestDecode(this);
   }
 
   // Free up any extra space in the backing buffer
   mSourceData.Compact();
 
   // Log header information
-  if (PR_LOG_TEST(gCompressedImageAccountingLog, PR_LOG_DEBUG)) {
+  if (PR_LOG_TEST(GetCompressedImageAccountingLog(), PR_LOG_DEBUG)) {
     char buf[9];
     get_header_str(buf, mSourceData.Elements(), mSourceData.Length());
-    PR_LOG (gCompressedImageAccountingLog, PR_LOG_DEBUG,
+    PR_LOG (GetCompressedImageAccountingLog(), PR_LOG_DEBUG,
             ("CompressedImageAccounting: RasterImage::SourceDataComplete() - data "
              "is done for container %p (%s) - header %p is 0x%s (length %d)",
              this,
              mSourceDataMimeType.get(),
              mSourceData.Elements(),
              buf,
              mSourceData.Length()));
   }
@@ -2422,17 +2429,17 @@ RasterImage::Discard(bool force)
   nsCOMPtr<imgIDecoderObserver> observer(do_QueryReferent(mObserver));
   if (observer)
     observer->OnDiscard();
 
   if (force)
     DiscardTracker::Remove(&mDiscardTrackerNode);
 
   // Log
-  PR_LOG(gCompressedImageAccountingLog, PR_LOG_DEBUG,
+  PR_LOG(GetCompressedImageAccountingLog(), PR_LOG_DEBUG,
          ("CompressedImageAccounting: discarded uncompressed image "
           "data from RasterImage %p (%s) - %d frames (cached count: %d); "
           "Total Containers: %d, Discardable containers: %d, "
           "Total source bytes: %lld, Source bytes for discardable containers %lld",
           this,
           mSourceDataMimeType.get(),
           old_frame_count,
           mFrames.Length(),
@@ -3078,17 +3085,17 @@ RasterImage::UnlockImage()
   mLockCount--;
 
   // If we've decoded this image once before, we're currently decoding again,
   // and our lock count is now zero (so nothing is forcing us to keep the
   // decoded data around), try to cancel the decode and throw away whatever
   // we've decoded.
   if (mHasBeenDecoded && mDecoder &&
       mLockCount == 0 && CanForciblyDiscard()) {
-    PR_LOG(gCompressedImageAccountingLog, PR_LOG_DEBUG,
+    PR_LOG(GetCompressedImageAccountingLog(), PR_LOG_DEBUG,
            ("RasterImage[0x%p] canceling decode because image "
             "is now unlocked.", this));
     ShutdownDecoder(eShutdownIntent_Interrupted);
     ForceDiscard();
     return NS_OK;
   }
 
   // Otherwise, we might still be a candidate for discarding in the future.  If
--- a/image/src/imgLoader.cpp
+++ b/image/src/imgLoader.cpp
@@ -540,22 +540,22 @@ imgCacheEntry::imgCacheEntry(imgLoader* 
    // will set this to false.
    mEvicted(true),
    mHasNoProxies(true),
    mForcePrincipalCheck(forcePrincipalCheck)
 {}
 
 imgCacheEntry::~imgCacheEntry()
 {
-  LOG_FUNC(gImgLog, "imgCacheEntry::~imgCacheEntry()");
+  LOG_FUNC(GetImgLog(), "imgCacheEntry::~imgCacheEntry()");
 }
 
 void imgCacheEntry::Touch(bool updateTime /* = true */)
 {
-  LOG_SCOPE(gImgLog, "imgCacheEntry::Touch");
+  LOG_SCOPE(GetImgLog(), "imgCacheEntry::Touch");
 
   if (updateTime)
     mTouchedTime = SecondsFromPRTime(PR_Now());
 
   UpdateCache();
 }
 
 void imgCacheEntry::UpdateCache(int32_t diff /* = 0 */)
@@ -573,19 +573,19 @@ void imgCacheEntry::SetHasNoProxies(bool
 {
 #if defined(PR_LOGGING)
   nsCOMPtr<nsIURI> uri;
   mRequest->GetURI(getter_AddRefs(uri));
   nsAutoCString spec;
   if (uri)
     uri->GetSpec(spec);
   if (hasNoProxies)
-    LOG_FUNC_WITH_PARAM(gImgLog, "imgCacheEntry::SetHasNoProxies true", "uri", spec.get());
+    LOG_FUNC_WITH_PARAM(GetImgLog(), "imgCacheEntry::SetHasNoProxies true", "uri", spec.get());
   else
-    LOG_FUNC_WITH_PARAM(gImgLog, "imgCacheEntry::SetHasNoProxies false", "uri", spec.get());
+    LOG_FUNC_WITH_PARAM(GetImgLog(), "imgCacheEntry::SetHasNoProxies false", "uri", spec.get());
 #endif
 
   mHasNoProxies = hasNoProxies;
 }
 
 imgCacheQueue::imgCacheQueue()
  : mDirty(false),
    mSize(0)
@@ -679,17 +679,17 @@ imgCacheQueue::const_iterator imgCacheQu
   return mQueue.end();
 }
 
 nsresult imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup,
                                              imgINotificationObserver *aObserver,
                                              nsLoadFlags aLoadFlags, imgIRequest *aProxyRequest,
                                              imgIRequest **_retval)
 {
-  LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::CreateNewProxyForRequest", "imgRequest", aRequest);
+  LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgLoader::CreateNewProxyForRequest", "imgRequest", aRequest);
 
   /* XXX If we move decoding onto separate threads, we should save off the
      calling thread here and pass it off to |proxyRequest| so that it call
      proxy calls to |aObserver|.
    */
 
   imgRequestProxy *proxyRequest;
   if (aProxyRequest) {
@@ -761,17 +761,17 @@ void imgCacheExpirationTracker::NotifyEx
 
 #if defined(PR_LOGGING)
   nsRefPtr<imgRequest> req(entry->GetRequest());
   if (req) {
     nsCOMPtr<nsIURI> uri;
     req->GetURI(getter_AddRefs(uri));
     nsAutoCString spec;
     uri->GetSpec(spec);
-    LOG_FUNC_WITH_PARAM(gImgLog, "imgCacheExpirationTracker::NotifyExpired", "entry", spec.get());
+    LOG_FUNC_WITH_PARAM(GetImgLog(), "imgCacheExpirationTracker::NotifyExpired", "entry", spec.get());
   }
 #endif
 
   // We can be called multiple times on the same entry. Don't do work multiple
   // times.
   if (!entry->Evicted())
     entry->Loader()->RemoveFromCache(entry);
 
@@ -1011,35 +1011,35 @@ void imgLoader::MinimizeCaches()
 
 bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry)
 {
   imgCacheTable &cache = GetCache(key);
 
   nsAutoCString spec;
   key->GetSpec(spec);
 
-  LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::PutIntoCache", "uri", spec.get());
+  LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::PutIntoCache", "uri", spec.get());
 
   // Check to see if this request already exists in the cache and is being
   // loaded on a different thread. If so, don't allow this entry to be added to
   // the cache.
   nsRefPtr<imgCacheEntry> tmpCacheEntry;
   if (cache.Get(spec, getter_AddRefs(tmpCacheEntry)) && tmpCacheEntry) {
-    PR_LOG(gImgLog, PR_LOG_DEBUG,
+    PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("[this=%p] imgLoader::PutIntoCache -- Element already in the cache", nullptr));
     nsRefPtr<imgRequest> tmpRequest = getter_AddRefs(tmpCacheEntry->GetRequest());
 
     // If it already exists, and we're putting the same key into the cache, we
     // should remove the old version.
-    PR_LOG(gImgLog, PR_LOG_DEBUG,
+    PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("[this=%p] imgLoader::PutIntoCache -- Replacing cached element", nullptr));
 
     RemoveFromCache(key);
   } else {
-    PR_LOG(gImgLog, PR_LOG_DEBUG,
+    PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("[this=%p] imgLoader::PutIntoCache -- Element NOT already in the cache", nullptr));
   }
 
   cache.Put(spec, entry);
 
   // We can be called to resurrect an evicted entry.
   if (entry->Evicted())
     entry->SetEvicted(false);
@@ -1065,17 +1065,17 @@ bool imgLoader::PutIntoCache(nsIURI *key
 }
 
 bool imgLoader::SetHasNoProxies(nsIURI *key, imgCacheEntry *entry)
 {
 #if defined(PR_LOGGING)
   nsAutoCString spec;
   key->GetSpec(spec);
 
-  LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::SetHasNoProxies", "uri", spec.get());
+  LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::SetHasNoProxies", "uri", spec.get());
 #endif
 
   if (entry->Evicted())
     return false;
 
   imgCacheQueue &queue = GetCacheQueue(key);
 
   nsresult addrv = NS_OK;
@@ -1098,17 +1098,17 @@ bool imgLoader::SetHasProxies(nsIURI *ke
 {
   VerifyCacheSizes();
 
   imgCacheTable &cache = GetCache(key);
 
   nsAutoCString spec;
   key->GetSpec(spec);
 
-  LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::SetHasProxies", "uri", spec.get());
+  LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::SetHasProxies", "uri", spec.get());
 
   nsRefPtr<imgCacheEntry> entry;
   if (cache.Get(spec, getter_AddRefs(entry)) && entry && entry->HasNoProxies()) {
     imgCacheQueue &queue = GetCacheQueue(key);
     queue.Remove(entry);
 
     if (mCacheTracker)
       mCacheTracker->RemoveObject(entry);
@@ -1143,17 +1143,17 @@ void imgLoader::CheckCacheLimits(imgCach
 
 #if defined(PR_LOGGING)
     nsRefPtr<imgRequest> req(entry->GetRequest());
     if (req) {
       nsCOMPtr<nsIURI> uri;
       req->GetURI(getter_AddRefs(uri));
       nsAutoCString spec;
       uri->GetSpec(spec);
-      LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::CheckCacheLimits", "entry", spec.get());
+      LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::CheckCacheLimits", "entry", spec.get());
     }
 #endif
 
     if (entry)
       RemoveFromCache(entry);
   }
 }
 
@@ -1289,17 +1289,17 @@ bool imgLoader::ValidateEntry(imgCacheEn
                                 nsLoadFlags aLoadFlags,
                                 bool aCanMakeNewChannel,
                                 imgIRequest *aExistingRequest,
                                 imgIRequest **aProxyRequest,
                                 nsIChannelPolicy *aPolicy,
                                 nsIPrincipal* aLoadingPrincipal,
                                 int32_t aCORSMode)
 {
-  LOG_SCOPE(gImgLog, "imgLoader::ValidateEntry");
+  LOG_SCOPE(GetImgLog(), "imgLoader::ValidateEntry");
 
   bool hasExpired;
   uint32_t expirationTime = aEntry->GetExpiryTime();
   if (expirationTime <= SecondsFromPRTime(PR_Now())) {
     hasExpired = true;
   } else {
     hasExpired = false;
   }
@@ -1346,51 +1346,51 @@ bool imgLoader::ValidateEntry(imgCacheEn
     // If we would need to revalidate this entry, but we're being told to
     // bypass the cache, we don't allow this entry to be used.
     if (aLoadFlags & nsIRequest::LOAD_BYPASS_CACHE)
       return false;
 
     // Determine whether the cache aEntry must be revalidated...
     validateRequest = ShouldRevalidateEntry(aEntry, aLoadFlags, hasExpired);
 
-    PR_LOG(gImgLog, PR_LOG_DEBUG,
+    PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("imgLoader::ValidateEntry validating cache entry. " 
             "validateRequest = %d", validateRequest));
   }
 #if defined(PR_LOGGING)
   else if (!key) {
     nsAutoCString spec;
     aURI->GetSpec(spec);
 
-    PR_LOG(gImgLog, PR_LOG_DEBUG,
+    PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("imgLoader::ValidateEntry BYPASSING cache validation for %s " 
             "because of NULL LoadID", spec.get()));
   }
 #endif
 
   // We can't use a cached request if it comes from a different
   // application cache than this load is expecting.
   nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
   nsCOMPtr<nsIApplicationCache> requestAppCache;
   nsCOMPtr<nsIApplicationCache> groupAppCache;
   if ((appCacheContainer = do_GetInterface(request->mRequest)))
     appCacheContainer->GetApplicationCache(getter_AddRefs(requestAppCache));
   if ((appCacheContainer = do_QueryInterface(aLoadGroup)))
     appCacheContainer->GetApplicationCache(getter_AddRefs(groupAppCache));
 
   if (requestAppCache != groupAppCache) {
-    PR_LOG(gImgLog, PR_LOG_DEBUG,
+    PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("imgLoader::ValidateEntry - Unable to use cached imgRequest "
             "[request=%p] because of mismatched application caches\n",
             address_of(request)));
     return false;
   }
 
   if (validateRequest && aCanMakeNewChannel) {
-    LOG_SCOPE(gImgLog, "imgLoader::ValidateRequest |cache hit| must validate");
+    LOG_SCOPE(GetImgLog(), "imgLoader::ValidateRequest |cache hit| must validate");
 
     return ValidateRequestWithNewChannel(request, aURI, aInitialDocumentURI,
                                          aReferrerURI, aLoadGroup, aObserver,
                                          aCX, aLoadFlags, aExistingRequest,
                                          aProxyRequest, aPolicy,
                                          aLoadingPrincipal, aCORSMode);
   }
 
@@ -1403,17 +1403,17 @@ bool imgLoader::RemoveFromCache(nsIURI *
   if (!aKey) return false;
 
   imgCacheTable &cache = GetCache(aKey);
   imgCacheQueue &queue = GetCacheQueue(aKey);
 
   nsAutoCString spec;
   aKey->GetSpec(spec);
 
-  LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::RemoveFromCache", "uri", spec.get());
+  LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::RemoveFromCache", "uri", spec.get());
 
   nsRefPtr<imgCacheEntry> entry;
   if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
     cache.Remove(spec);
 
     NS_ABORT_IF_FALSE(!entry->Evicted(), "Evicting an already-evicted cache entry!");
 
     // Entries with no proxies are in the tracker.
@@ -1431,33 +1431,33 @@ bool imgLoader::RemoveFromCache(nsIURI *
     return true;
   }
   else
     return false;
 }
 
 bool imgLoader::RemoveFromCache(imgCacheEntry *entry)
 {
-  LOG_STATIC_FUNC(gImgLog, "imgLoader::RemoveFromCache entry");
+  LOG_STATIC_FUNC(GetImgLog(), "imgLoader::RemoveFromCache entry");
 
   nsRefPtr<imgRequest> request(getter_AddRefs(entry->GetRequest()));
   if (request) {
     nsCOMPtr<nsIURI> key;
     if (NS_SUCCEEDED(request->GetURI(getter_AddRefs(key))) && key) {
       imgCacheTable &cache = GetCache(key);
       imgCacheQueue &queue = GetCacheQueue(key);
       nsAutoCString spec;
       key->GetSpec(spec);
 
-      LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::RemoveFromCache", "entry's uri", spec.get());
+      LOG_STATIC_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::RemoveFromCache", "entry's uri", spec.get());
 
       cache.Remove(spec);
 
       if (entry->HasNoProxies()) {
-        LOG_STATIC_FUNC(gImgLog, "imgLoader::RemoveFromCache removing from tracker");
+        LOG_STATIC_FUNC(GetImgLog(), "imgLoader::RemoveFromCache removing from tracker");
         if (mCacheTracker)
           mCacheTracker->RemoveObject(entry);
         queue.Remove(entry);
       }
 
       entry->SetEvicted(true);
       request->SetIsInCache(false);
 
@@ -1477,33 +1477,33 @@ static PLDHashOperator EnumEvictEntries(
 
   entries->AppendElement(aData);
 
   return PL_DHASH_NEXT;
 }
 
 nsresult imgLoader::EvictEntries(imgCacheTable &aCacheToClear)
 {
-  LOG_STATIC_FUNC(gImgLog, "imgLoader::EvictEntries table");
+  LOG_STATIC_FUNC(GetImgLog(), "imgLoader::EvictEntries table");
 
   // We have to make a temporary, since RemoveFromCache removes the element
   // from the queue, invalidating iterators.
   nsTArray<nsRefPtr<imgCacheEntry> > entries;
   aCacheToClear.Enumerate(EnumEvictEntries, &entries);
 
   for (uint32_t i = 0; i < entries.Length(); ++i)
     if (!RemoveFromCache(entries[i]))
       return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
 nsresult imgLoader::EvictEntries(imgCacheQueue &aQueueToClear)
 {
-  LOG_STATIC_FUNC(gImgLog, "imgLoader::EvictEntries queue");
+  LOG_STATIC_FUNC(GetImgLog(), "imgLoader::EvictEntries queue");
 
   // We have to make a temporary, since RemoveFromCache removes the element
   // from the queue, invalidating iterators.
   nsTArray<nsRefPtr<imgCacheEntry> > entries(aQueueToClear.GetNumElements());
   for (imgCacheQueue::const_iterator i = aQueueToClear.begin(); i != aQueueToClear.end(); ++i)
     entries.AppendElement(*i);
 
   for (uint32_t i = 0; i < entries.Length(); ++i)
@@ -1540,17 +1540,17 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIUR
 
   NS_ASSERTION(aURI, "imgLoader::LoadImage -- NULL URI pointer");
 
   if (!aURI)
     return NS_ERROR_NULL_POINTER;
 
   nsAutoCString spec;
   aURI->GetSpec(spec);
-  LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::LoadImage", "aURI", spec.get());
+  LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgLoader::LoadImage", "aURI", spec.get());
 
   *_retval = nullptr;
 
   nsRefPtr<imgRequest> request;
 
   nsresult rv;
   nsLoadFlags requestFlags = nsIRequest::LOAD_NORMAL;
 
@@ -1615,17 +1615,17 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIUR
   if (cache.Get(spec, getter_AddRefs(entry)) && entry) {
     if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
                       aLoadGroup, aObserver, aCX, requestFlags, true,
                       aRequest, _retval, aPolicy, aLoadingPrincipal, corsmode)) {
       request = getter_AddRefs(entry->GetRequest());
 
       // If this entry has no proxies, its request has no reference to the entry.
       if (entry->HasNoProxies()) {
-        LOG_FUNC_WITH_PARAM(gImgLog, "imgLoader::LoadImage() adding proxyless entry", "uri", spec.get());
+        LOG_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::LoadImage() adding proxyless entry", "uri", spec.get());
         NS_ABORT_IF_FALSE(!request->HasCacheEntry(), "Proxyless entry's request has cache entry!");
         request->SetCacheEntry(entry);
 
         if (mCacheTracker)
           mCacheTracker->MarkUsed(entry);
       } 
 
       entry->Touch();
@@ -1641,17 +1641,17 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIUR
     }
   }
 
   // Keep the channel in this scope, so we can adjust its notificationCallbacks
   // later when we create the proxy.
   nsCOMPtr<nsIChannel> newChannel;
   // If we didn't get a cache hit, we need to load from the network.
   if (!request) {
-    LOG_SCOPE(gImgLog, "imgLoader::LoadImage |cache miss|");
+    LOG_SCOPE(GetImgLog(), "imgLoader::LoadImage |cache miss|");
 
     bool forcePrincipalCheck;
     rv = NewImageChannel(getter_AddRefs(newChannel),
                          &forcePrincipalCheck,
                          aURI,
                          aInitialDocumentURI,
                          aReferrerURI,
                          aLoadGroup,
@@ -1661,17 +1661,17 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIUR
                          aLoadingPrincipal);
     if (NS_FAILED(rv))
       return NS_ERROR_FAILURE;
 
     MOZ_ASSERT(NS_UsePrivateBrowsing(newChannel) == mRespectPrivacy);
 
     NewRequestAndEntry(forcePrincipalCheck, this, getter_AddRefs(request), getter_AddRefs(entry));
 
-    PR_LOG(gImgLog, PR_LOG_DEBUG,
+    PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("[this=%p] imgLoader::LoadImage -- Created new imgRequest [request=%p]\n", this, request.get()));
 
     // Create a loadgroup for this new channel.  This way if the channel
     // is redirected, we'll have a way to cancel the resulting channel.
     nsCOMPtr<nsILoadGroup> loadGroup =
         do_CreateInstance(NS_LOADGROUP_CONTRACTID);
     newChannel->SetLoadGroup(loadGroup);
 
@@ -1686,52 +1686,52 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIUR
 
     // create the proxy listener
     nsCOMPtr<nsIStreamListener> pl = new ProxyListener(request.get());
 
     // See if we need to insert a CORS proxy between the proxy listener and the
     // request.
     nsCOMPtr<nsIStreamListener> listener = pl;
     if (corsmode != imgIRequest::CORS_NONE) {
-      PR_LOG(gImgLog, PR_LOG_DEBUG,
+      PR_LOG(GetImgLog(), PR_LOG_DEBUG,
              ("[this=%p] imgLoader::LoadImage -- Setting up a CORS load",
               this));
       bool withCredentials = corsmode == imgIRequest::CORS_USE_CREDENTIALS;
 
       nsRefPtr<nsCORSListenerProxy> corsproxy =
         new nsCORSListenerProxy(pl, aLoadingPrincipal, withCredentials);
       rv = corsproxy->Init(newChannel);
       if (NS_FAILED(rv)) {
-        PR_LOG(gImgLog, PR_LOG_DEBUG,
+        PR_LOG(GetImgLog(), PR_LOG_DEBUG,
                ("[this=%p] imgLoader::LoadImage -- nsCORSListenerProxy "
                 "creation failed: 0x%x\n", this, rv));
         request->CancelAndAbort(rv);
         return NS_ERROR_FAILURE;
       }
 
       listener = corsproxy;
     }
 
-    PR_LOG(gImgLog, PR_LOG_DEBUG,
+    PR_LOG(GetImgLog(), PR_LOG_DEBUG,
            ("[this=%p] imgLoader::LoadImage -- Calling channel->AsyncOpen()\n", this));
 
     nsresult openRes = newChannel->AsyncOpen(listener, nullptr);
 
     if (NS_FAILED(openRes)) {
-      PR_LOG(gImgLog, PR_LOG_DEBUG,
+      PR_LOG(GetImgLog(), PR_LOG_DEBUG,
              ("[this=%p] imgLoader::LoadImage -- AsyncOpen() failed: 0x%x\n",
               this, openRes));
       request->CancelAndAbort(openRes);
       return openRes;
     }
 
     // Try to add the new request into the cache.
     PutIntoCache(aURI, entry);
   } else {
-    LOG_MSG_WITH_PARAM(gImgLog, 
+    LOG_MSG_WITH_PARAM(GetImgLog(), 
                        "imgLoader::LoadImage |cache hit|", "request", request);
   }
 
 
   // If we didn't get a proxy when validating the cache entry, we need to create one.
   if (!*_retval) {
     // ValidateEntry() has three return values: "Is valid," "might be valid --
     // validating over network", and "not valid." If we don't have a _retval,
@@ -1739,17 +1739,17 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIUR
     // to SetLoadId here because we know this request is valid for this context.
     //
     // Note, however, that this doesn't guarantee the behaviour we want (one
     // URL maps to the same image on a page) if we load the same image in a
     // different tab (see bug 528003), because its load id will get re-set, and
     // that'll cause us to validate over the network.
     request->SetLoadId(aCX);
 
-    LOG_MSG(gImgLog, "imgLoader::LoadImage", "creating proxy request.");
+    LOG_MSG(GetImgLog(), "imgLoader::LoadImage", "creating proxy request.");
     rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver,
                                   requestFlags, aRequest, _retval);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     imgRequestProxy *proxy = static_cast<imgRequestProxy *>(*_retval);
 
@@ -1839,17 +1839,17 @@ NS_IMETHODIMP imgLoader::LoadImageWithCh
         else {
           request = getter_AddRefs(entry->GetRequest());
         }
       }
 
       if (request && entry) {
         // If this entry has no proxies, its request has no reference to the entry.
         if (entry->HasNoProxies()) {
-          LOG_FUNC_WITH_PARAM(gImgLog, "imgLoader::LoadImageWithChannel() adding proxyless entry", "uri", spec.get());
+          LOG_FUNC_WITH_PARAM(GetImgLog(), "imgLoader::LoadImageWithChannel() adding proxyless entry", "uri", spec.get());
           NS_ABORT_IF_FALSE(!request->HasCacheEntry(), "Proxyless entry's request has cache entry!");
           request->SetCacheEntry(entry);
 
           if (mCacheTracker)
             mCacheTracker->MarkUsed(entry);
         } 
       }
     }
@@ -2171,17 +2171,17 @@ NS_IMETHODIMP imgCacheValidator::OnStart
   // We can't load out of cache. We have to create a whole new request for the
   // data that's coming in off the channel.
   nsCOMPtr<nsIURI> uri;
   mRequest->GetURI(getter_AddRefs(uri));
 
 #if defined(PR_LOGGING)
   nsAutoCString spec;
   uri->GetSpec(spec);
-  LOG_MSG_WITH_PARAM(gImgLog, "imgCacheValidator::OnStartRequest creating new request", "uri", spec.get());
+  LOG_MSG_WITH_PARAM(GetImgLog(), "imgCacheValidator::OnStartRequest creating new request", "uri", spec.get());
 #endif
 
   int32_t corsmode = mRequest->GetCORSMode();
   nsCOMPtr<nsIPrincipal> loadingPrincipal = mRequest->GetLoadingPrincipal();
 
   // Doom the old request's cache entry
   mRequest->RemoveFromCache();
 
--- a/image/src/imgRequest.cpp
+++ b/image/src/imgRequest.cpp
@@ -64,17 +64,24 @@ static void
 InitPrefCaches()
 {
   Preferences::AddBoolVarCache(&gDiscardable, "image.mem.discardable");
   Preferences::AddBoolVarCache(&gDecodeOnDraw, "image.mem.decodeondraw");
   gInitializedPrefCaches = true;
 }
 
 #if defined(PR_LOGGING)
-PRLogModuleInfo *gImgLog = PR_NewLogModule("imgRequest");
+PRLogModuleInfo *
+GetImgLog()
+{
+  static PRLogModuleInfo *sImgLog;
+  if (!sImgLog)
+    sImgLog = PR_NewLogModule("imgRequest");
+  return sImgLog;
+}
 #endif
 
 NS_IMPL_ISUPPORTS5(imgRequest,
                    nsIStreamListener, nsIRequestObserver,
                    nsIChannelEventSink,
                    nsIInterfaceRequestor,
                    nsIAsyncVerifyRedirectCallback)
 
@@ -97,31 +104,31 @@ imgRequest::imgRequest(imgLoader* aLoade
   }
 }
 
 imgRequest::~imgRequest()
 {
   if (mURI) {
     nsAutoCString spec;
     mURI->GetSpec(spec);
-    LOG_FUNC_WITH_PARAM(gImgLog, "imgRequest::~imgRequest()", "keyuri", spec.get());
+    LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequest::~imgRequest()", "keyuri", spec.get());
   } else
-    LOG_FUNC(gImgLog, "imgRequest::~imgRequest()");
+    LOG_FUNC(GetImgLog(), "imgRequest::~imgRequest()");
 }
 
 nsresult imgRequest::Init(nsIURI *aURI,
                           nsIURI *aCurrentURI,
                           nsIRequest *aRequest,
                           nsIChannel *aChannel,
                           imgCacheEntry *aCacheEntry,
                           void *aLoadId,
                           nsIPrincipal* aLoadingPrincipal,
                           int32_t aCORSMode)
 {
-  LOG_FUNC(gImgLog, "imgRequest::Init");
+  LOG_FUNC(GetImgLog(), "imgRequest::Init");
 
   NS_ABORT_IF_FALSE(!mImage, "Multiple calls to init");
   NS_ABORT_IF_FALSE(aURI, "No uri");
   NS_ABORT_IF_FALSE(aCurrentURI, "No current uri");
   NS_ABORT_IF_FALSE(aRequest, "No request");
   NS_ABORT_IF_FALSE(aChannel, "No channel");
 
   mProperties = do_CreateInstance("@mozilla.org/properties;1");
@@ -178,31 +185,31 @@ void imgRequest::ResetCacheEntry()
   if (HasCacheEntry()) {
     mCacheEntry->SetDataSize(0);
   }
 }
 
 void imgRequest::AddProxy(imgRequestProxy *proxy)
 {
   NS_PRECONDITION(proxy, "null imgRequestProxy passed in");
-  LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::AddProxy", "proxy", proxy);
+  LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgRequest::AddProxy", "proxy", proxy);
 
   // If we're empty before adding, we have to tell the loader we now have
   // proxies.
   if (GetStatusTracker().ConsumerCount() == 0) {
     NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri.");
     mLoader->SetHasProxies(mURI);
   }
 
   GetStatusTracker().AddConsumer(proxy);
 }
 
 nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus)
 {
-  LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy);
+  LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgRequest::RemoveProxy", "proxy", proxy);
 
   // This will remove our animation consumers, so after removing
   // this proxy, we don't end up without proxies with observers, but still
   // have animation consumers.
   proxy->ClearAnimationConsumers();
 
   // Let the status tracker do its thing before we potentially call Cancel()
   // below, because Cancel() may result in OnStopRequest being called back
@@ -220,27 +227,27 @@ nsresult imgRequest::RemoveProxy(imgRequ
       NS_ABORT_IF_FALSE(mURI, "Removing last observer without key uri.");
 
       mLoader->SetHasNoProxies(mURI, mCacheEntry);
     } 
 #if defined(PR_LOGGING)
     else {
       nsAutoCString spec;
       mURI->GetSpec(spec);
-      LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy no cache entry", "uri", spec.get());
+      LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::RemoveProxy no cache entry", "uri", spec.get());
     }
 #endif
 
     /* If |aStatus| is a failure code, then cancel the load if it is still in progress.
        Otherwise, let the load continue, keeping 'this' in the cache with no observers.
        This way, if a proxy is destroyed without calling cancel on it, it won't leak
        and won't leave a bad pointer in the observer list.
      */
     if (statusTracker.IsLoading() && NS_FAILED(aStatus)) {
-      LOG_MSG(gImgLog, "imgRequest::RemoveProxy", "load in progress.  canceling");
+      LOG_MSG(GetImgLog(), "imgRequest::RemoveProxy", "load in progress.  canceling");
 
       this->Cancel(NS_BINDING_ABORTED);
     }
 
     /* break the cycle from the cache entry. */
     mCacheEntry = nullptr;
   }
 
@@ -249,73 +256,73 @@ nsresult imgRequest::RemoveProxy(imgRequ
   if (aStatus != NS_IMAGELIB_CHANGING_OWNER)
     proxy->RemoveFromLoadGroup(true);
 
   return NS_OK;
 }
 
 void imgRequest::CancelAndAbort(nsresult aStatus)
 {
-  LOG_SCOPE(gImgLog, "imgRequest::CancelAndAbort");
+  LOG_SCOPE(GetImgLog(), "imgRequest::CancelAndAbort");
 
   Cancel(aStatus);
 
   // It's possible for the channel to fail to open after we've set our
   // notification callbacks. In that case, make sure to break the cycle between
   // the channel and us, because it won't.
   if (mChannel) {
     mChannel->SetNotificationCallbacks(mPrevChannelSink);
     mPrevChannelSink = nullptr;
   }
 }
 
 void imgRequest::Cancel(nsresult aStatus)
 {
   /* The Cancel() method here should only be called by this class. */
 
-  LOG_SCOPE(gImgLog, "imgRequest::Cancel");
+  LOG_SCOPE(GetImgLog(), "imgRequest::Cancel");
 
   imgStatusTracker& statusTracker = GetStatusTracker();
 
   statusTracker.MaybeUnblockOnload();
 
   statusTracker.RecordCancel();
 
   RemoveFromCache();
 
   if (mRequest && statusTracker.IsLoading())
     mRequest->Cancel(aStatus);
 }
 
 nsresult imgRequest::GetURI(nsIURI **aURI)
 {
-  LOG_FUNC(gImgLog, "imgRequest::GetURI");
+  LOG_FUNC(GetImgLog(), "imgRequest::GetURI");
 
   if (mURI) {
     *aURI = mURI;
     NS_ADDREF(*aURI);
     return NS_OK;
   }
 
   return NS_ERROR_FAILURE;
 }
 
 nsresult imgRequest::GetSecurityInfo(nsISupports **aSecurityInfo)
 {
-  LOG_FUNC(gImgLog, "imgRequest::GetSecurityInfo");
+  LOG_FUNC(GetImgLog(), "imgRequest::GetSecurityInfo");
 
   // Missing security info means this is not a security load
   // i.e. it is not an error when security info is missing
   NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
   return NS_OK;
 }
 
 void imgRequest::RemoveFromCache()
 {
-  LOG_SCOPE(gImgLog, "imgRequest::RemoveFromCache");
+  LOG_SCOPE(GetImgLog(), "imgRequest::RemoveFromCache");
 
   if (mIsInCache) {
     // mCacheEntry is nulled out when we have no more observers.
     if (mCacheEntry)
       mLoader->RemoveFromCache(mCacheEntry);
     else
       mLoader->RemoveFromCache(mURI);
   }
@@ -346,17 +353,17 @@ void imgRequest::AdjustPriority(imgReque
 
   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mChannel);
   if (p)
     p->AdjustPriority(delta);
 }
 
 void imgRequest::SetIsInCache(bool incache)
 {
-  LOG_FUNC_WITH_PARAM(gImgLog, "imgRequest::SetIsCacheable", "incache", incache);
+  LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequest::SetIsCacheable", "incache", incache);
   mIsInCache = incache;
 }
 
 void imgRequest::UpdateCacheEntrySize()
 {
   if (mCacheEntry) {
     mCacheEntry->SetDataSize(mImage->SizeOfData());
 
@@ -473,17 +480,17 @@ imgRequest::StartDecoding()
   return NS_OK;
 }
 
 /** nsIRequestObserver methods **/
 
 /* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
 NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
 {
-  LOG_SCOPE(gImgLog, "imgRequest::OnStartRequest");
+  LOG_SCOPE(GetImgLog(), "imgRequest::OnStartRequest");
 
   // Figure out if we're multipart
   nsCOMPtr<nsIMultiPartChannel> mpchan(do_QueryInterface(aRequest));
   if (mpchan)
       mIsMultiPartChannel = true;
 
   // If we're not multipart, we shouldn't have an image yet
   NS_ABORT_IF_FALSE(mIsMultiPartChannel || !mImage,
@@ -546,17 +553,17 @@ NS_IMETHODIMP imgRequest::OnStartRequest
   }
 
   return NS_OK;
 }
 
 /* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */
 NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status)
 {
-  LOG_FUNC(gImgLog, "imgRequest::OnStopRequest");
+  LOG_FUNC(GetImgLog(), "imgRequest::OnStopRequest");
 
   bool lastPart = true;
   nsCOMPtr<nsIMultiPartChannel> mpchan(do_QueryInterface(aRequest));
   if (mpchan)
     mpchan->GetIsLastPart(&lastPart);
 
   // XXXldb What if this is a non-last part of a multipart request?
   // xxx before we release our reference to mRequest, lets
@@ -630,24 +637,24 @@ static NS_METHOD sniff_mimetype_callback
 /** nsIStreamListener methods **/
 
 /* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long long sourceOffset, in unsigned long count); */
 NS_IMETHODIMP
 imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
                             nsIInputStream *inStr, uint64_t sourceOffset,
                             uint32_t count)
 {
-  LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "count", count);
+  LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgRequest::OnDataAvailable", "count", count);
 
   NS_ASSERTION(aRequest, "imgRequest::OnDataAvailable -- no request!");
 
   nsresult rv;
 
   if (!mGotData || mResniffMimeType) {
-    LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |First time through... finding mimetype|");
+    LOG_SCOPE(GetImgLog(), "imgRequest::OnDataAvailable |First time through... finding mimetype|");
 
     mGotData = true;
 
     mimetype_closure closure;
     nsAutoCString newType;
     closure.request = this;
     closure.newType = &newType;
 
@@ -658,34 +665,34 @@ imgRequest::OnDataAvailable(nsIRequest *
     inStr->ReadSegments(sniff_mimetype_callback, &closure, count, &out);
 
 #ifdef DEBUG
     /* NS_WARNING if the content type from the channel isn't the same if the sniffing */
 #endif
 
     nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
     if (newType.IsEmpty()) {
-      LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |sniffing of mimetype failed|");
+      LOG_SCOPE(GetImgLog(), "imgRequest::OnDataAvailable |sniffing of mimetype failed|");
 
       rv = NS_ERROR_FAILURE;
       if (chan) {
         rv = chan->GetContentType(newType);
       }
 
       if (NS_FAILED(rv)) {
-        PR_LOG(gImgLog, PR_LOG_ERROR,
+        PR_LOG(GetImgLog(), PR_LOG_ERROR,
                ("[this=%p] imgRequest::OnDataAvailable -- Content type unavailable from the channel\n",
                 this));
 
         this->Cancel(NS_IMAGELIB_ERROR_FAILURE);
 
         return NS_BINDING_ABORTED;
       }
 
-      LOG_MSG(gImgLog, "imgRequest::OnDataAvailable", "Got content type from the channel");
+      LOG_MSG(GetImgLog(), "imgRequest::OnDataAvailable", "Got content type from the channel");
     }
 
     // If we're a regular image and this is the first call to OnDataAvailable,
     // this will always be true. If we've resniffed our MIME type (i.e. we're a
     // multipart/x-mixed-replace image), we have to be able to switch our image
     // type and decoder.
     // We always reinitialize for SVGs, because they have no way of
     // reinitializing themselves.
@@ -729,17 +736,17 @@ imgRequest::OnDataAvailable(nsIRequest *
       if (!disposition.IsEmpty()) {
         nsCOMPtr<nsISupportsCString> contentDisposition(do_CreateInstance("@mozilla.org/supports-cstring;1"));
         if (contentDisposition) {
           contentDisposition->SetData(disposition);
           mProperties->Set("content-disposition", contentDisposition);
         }
       }
 
-      LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "content type", mContentType.get());
+      LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::OnDataAvailable", "content type", mContentType.get());
 
       //
       // Figure out our Image initialization flags
       //
 
       // We default to the static globals
       bool isDiscardable = gDiscardable;
       bool doDecodeOnDraw = gDecodeOnDraw;
@@ -847,17 +854,17 @@ imgRequest::OnDataAvailable(nsIRequest *
     NS_ABORT_IF_FALSE(bytesRead == count || mImage->HasError(),
   "WriteToRasterImage should consume everything or the image must be in error!");
   } else { // mImage->GetType() == imgIContainer::TYPE_VECTOR
     nsCOMPtr<nsIStreamListener> imageAsStream = do_QueryInterface(mImage);
     rv = imageAsStream->OnDataAvailable(aRequest, ctxt, inStr,
                                         sourceOffset, count);
   }
   if (NS_FAILED(rv)) {
-    PR_LOG(gImgLog, PR_LOG_WARNING,
+    PR_LOG(GetImgLog(), PR_LOG_WARNING,
            ("[this=%p] imgRequest::OnDataAvailable -- "
             "copy to RasterImage failed\n", this));
     this->Cancel(NS_IMAGELIB_ERROR_FAILURE);
     return NS_BINDING_ABORTED;
   }
 
   return NS_OK;
 }
@@ -965,17 +972,17 @@ imgRequest::OnRedirectVerifyCallback(nsr
   mChannel = mNewRedirectChannel;
   mTimedChannel = do_QueryInterface(mChannel);
   mNewRedirectChannel = nullptr;
 
 #if defined(PR_LOGGING)
   nsAutoCString oldspec;
   if (mCurrentURI)
     mCurrentURI->GetSpec(oldspec);
-  LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "old", oldspec.get());
+  LOG_MSG_WITH_PARAM(GetImgLog(), "imgRequest::OnChannelRedirect", "old", oldspec.get());
 #endif
 
   // make sure we have a protocol that returns data rather than opens
   // an external application, e.g. mailto:
   mChannel->GetURI(getter_AddRefs(mCurrentURI));
   bool doesNotReturnData = false;
   nsresult rv =
     NS_URIChainHasFlags(mCurrentURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA,
--- a/image/src/imgRequestProxy.cpp
+++ b/image/src/imgRequestProxy.cpp
@@ -86,17 +86,17 @@ imgRequestProxy::~imgRequestProxy()
 }
 
 nsresult imgRequestProxy::Init(imgStatusTracker* aStatusTracker,
                                nsILoadGroup* aLoadGroup,
                                nsIURI* aURI, imgINotificationObserver* aObserver)
 {
   NS_PRECONDITION(!mOwner && !mListener, "imgRequestProxy is already initialized");
 
-  LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequestProxy::Init", "request", aStatusTracker->GetRequest());
+  LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgRequestProxy::Init", "request", aStatusTracker->GetRequest());
 
   NS_ABORT_IF_FALSE(mAnimationConsumers == 0, "Cannot have animation before Init");
 
   mOwner = aStatusTracker->GetRequest();
   mOwnerHasImage = !!aStatusTracker->GetImage();
   mListener = aObserver;
   // Make sure to addref mListener before the AddProxy call below, since
   // that call might well want to release it if the imgRequest has
@@ -225,17 +225,17 @@ NS_IMETHODIMP imgRequestProxy::GetStatus
 }
 
 /* void cancel (in nsresult status); */
 NS_IMETHODIMP imgRequestProxy::Cancel(nsresult status)
 {
   if (mCanceled)
     return NS_ERROR_FAILURE;
 
-  LOG_SCOPE(gImgLog, "imgRequestProxy::Cancel");
+  LOG_SCOPE(GetImgLog(), "imgRequestProxy::Cancel");
 
   mCanceled = true;
 
   nsCOMPtr<nsIRunnable> ev = new imgCancelRunnable(this, status);
   return NS_DispatchToCurrentThread(ev);
 }
 
 void
@@ -255,17 +255,17 @@ NS_IMETHODIMP imgRequestProxy::CancelAnd
   // someone called Cancel() on us but the imgCancelRunnable is still
   // pending.  We still need to null out mListener before returning
   // from this function in this case.  That means we want to do the
   // RemoveProxy call right now, because we need to deliver the
   // onStopRequest.
   if (mCanceled && !mListener)
     return NS_ERROR_FAILURE;
 
-  LOG_SCOPE(gImgLog, "imgRequestProxy::CancelAndForgetObserver");
+  LOG_SCOPE(GetImgLog(), "imgRequestProxy::CancelAndForgetObserver");
 
   mCanceled = true;
 
   // Now cheat and make sure our removal from loadgroup happens async
   bool oldIsInLoadGroup = mIsInLoadGroup;
   mIsInLoadGroup = false;
 
   if (mOwner) {
@@ -495,17 +495,17 @@ NS_IMETHODIMP imgRequestProxy::Clone(img
 }
 
 nsresult imgRequestProxy::PerformClone(imgINotificationObserver* aObserver,
                                        imgRequestProxy* (aAllocFn)(imgRequestProxy*),
                                        imgIRequest** aClone)
 {
   NS_PRECONDITION(aClone, "Null out param");
 
-  LOG_SCOPE(gImgLog, "imgRequestProxy::Clone");
+  LOG_SCOPE(GetImgLog(), "imgRequestProxy::Clone");
 
   *aClone = nullptr;
   nsRefPtr<imgRequestProxy> clone = aAllocFn(this);
 
   // It is important to call |SetLoadFlags()| before calling |Init()| because
   // |Init()| adds the request to the loadgroup.
   // When a request is added to a loadgroup, its load flags are merged
   // with the load flags of the loadgroup.
@@ -604,99 +604,99 @@ NS_IMETHODIMP imgRequestProxy::GetHasTra
   }
   return NS_OK;
 }
 
 /** imgIDecoderObserver methods **/
 
 void imgRequestProxy::OnStartContainer()
 {
-  LOG_FUNC(gImgLog, "imgRequestProxy::OnStartContainer");
+  LOG_FUNC(GetImgLog(), "imgRequestProxy::OnStartContainer");
 
   if (mListener && !mCanceled && !mSentStartContainer) {
     // Hold a ref to the listener while we call it, just in case.
     nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
     mListener->Notify(this, imgINotificationObserver::SIZE_AVAILABLE, nullptr);
     mSentStartContainer = true;
   }
 }
 
 void imgRequestProxy::OnFrameUpdate(const nsIntRect * rect)
 {
-  LOG_FUNC(gImgLog, "imgRequestProxy::OnDataAvailable");
+  LOG_FUNC(GetImgLog(), "imgRequestProxy::OnDataAvailable");
 
   if (mListener && !mCanceled) {
     // Hold a ref to the listener while we call it, just in case.
     nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
     mListener->Notify(this, imgINotificationObserver::FRAME_UPDATE, rect);
   }
 }
 
 void imgRequestProxy::OnStopFrame()
 {
-  LOG_FUNC(gImgLog, "imgRequestProxy::OnStopFrame");
+  LOG_FUNC(GetImgLog(), "imgRequestProxy::OnStopFrame");
 
   if (mListener && !mCanceled) {
     // Hold a ref to the listener while we call it, just in case.
     nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
     mListener->Notify(this, imgINotificationObserver::FRAME_COMPLETE, nullptr);
   }
 }
 
 void imgRequestProxy::OnStopDecode()
 {
-  LOG_FUNC(gImgLog, "imgRequestProxy::OnStopDecode");
+  LOG_FUNC(GetImgLog(), "imgRequestProxy::OnStopDecode");
 
   if (mListener && !mCanceled) {
     // Hold a ref to the listener while we call it, just in case.
     nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
     mListener->Notify(this, imgINotificationObserver::DECODE_COMPLETE, nullptr);
   }
 
   // Multipart needs reset for next OnStartContainer
   if (mOwner && mOwner->GetMultipart())
     mSentStartContainer = false;
 }
 
 void imgRequestProxy::OnDiscard()
 {
-  LOG_FUNC(gImgLog, "imgRequestProxy::OnDiscard");
+  LOG_FUNC(GetImgLog(), "imgRequestProxy::OnDiscard");
 
   if (mListener && !mCanceled) {
     // Hold a ref to the listener while we call it, just in case.
     nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
     mListener->Notify(this, imgINotificationObserver::DISCARD, nullptr);
   }
 }
 
 void imgRequestProxy::OnImageIsAnimated()
 {
-  LOG_FUNC(gImgLog, "imgRequestProxy::OnImageIsAnimated");
+  LOG_FUNC(GetImgLog(), "imgRequestProxy::OnImageIsAnimated");
   if (mListener && !mCanceled) {
     // Hold a ref to the listener while we call it, just in case.
     nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
     mListener->Notify(this, imgINotificationObserver::IS_ANIMATED, nullptr);
   }
 }
 
 void imgRequestProxy::OnStartRequest()
 {
 #ifdef PR_LOGGING
   nsAutoCString name;
   GetName(name);
-  LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::OnStartRequest", "name", name.get());
+  LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequestProxy::OnStartRequest", "name", name.get());
 #endif
 }
 
 void imgRequestProxy::OnStopRequest(bool lastPart)
 {
 #ifdef PR_LOGGING
   nsAutoCString name;
   GetName(name);
-  LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::OnStopRequest", "name", name.get());
+  LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequestProxy::OnStopRequest", "name", name.get());
 #endif
   // There's all sorts of stuff here that could kill us (the OnStopRequest call
   // on the listener, the removal from the loadgroup, the release of the
   // listener, etc).  Don't let them do it.
   nsCOMPtr<imgIRequest> kungFuDeathGrip(this);
 
   if (mListener) {
     // Hold a ref to the listener while we call it, just in case.
@@ -729,31 +729,31 @@ void imgRequestProxy::OnStopRequest(bool
   }
 }
 
 void imgRequestProxy::BlockOnload()
 {
 #ifdef PR_LOGGING
   nsAutoCString name;
   GetName(name);
-  LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::BlockOnload", "name", name.get());
+  LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequestProxy::BlockOnload", "name", name.get());
 #endif
 
   nsCOMPtr<imgIOnloadBlocker> blocker = do_QueryInterface(mListener);
   if (blocker) {
     blocker->BlockOnload(this);
   }
 }
 
 void imgRequestProxy::UnblockOnload()
 {
 #ifdef PR_LOGGING
   nsAutoCString name;
   GetName(name);
-  LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::UnblockOnload", "name", name.get());
+  LOG_FUNC_WITH_PARAM(GetImgLog(), "imgRequestProxy::UnblockOnload", "name", name.get());
 #endif
 
   nsCOMPtr<imgIOnloadBlocker> blocker = do_QueryInterface(mListener);
   if (blocker) {
     blocker->UnblockOnload(this);
   }
 }
 
--- a/image/src/imgStatusTracker.cpp
+++ b/image/src/imgStatusTracker.cpp
@@ -25,17 +25,17 @@ NS_IMPL_ISUPPORTS3(imgStatusTrackerObser
                    imgIContainerObserver,
                    nsISupportsWeakReference)
 
 /** imgIContainerObserver methods **/
 
 /* [noscript] void frameChanged (in nsIntRect dirtyRect); */
 NS_IMETHODIMP imgStatusTrackerObserver::FrameChanged(const nsIntRect *dirtyRect)
 {
-  LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::FrameChanged");
+  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::FrameChanged");
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "FrameChanged callback before we've created our image");
 
   mTracker->RecordFrameChanged(dirtyRect);
 
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
   while (iter.HasMore()) {
     mTracker->SendFrameChanged(iter.GetNext(), dirtyRect);
@@ -43,17 +43,17 @@ NS_IMETHODIMP imgStatusTrackerObserver::
 
   return NS_OK;
 }
 
 /** imgIDecoderObserver methods **/
 
 NS_IMETHODIMP imgStatusTrackerObserver::OnStartDecode()
 {
-  LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnStartDecode");
+  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStartDecode");
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "OnStartDecode callback before we've created our image");
 
   if (mTracker->GetRequest() && !mTracker->GetRequest()->GetMultipart()) {
     MOZ_ASSERT(!mTracker->mBlockingOnload);
     mTracker->mBlockingOnload = true;
 
     mTracker->RecordBlockOnload();
@@ -80,51 +80,51 @@ NS_IMETHODIMP imgStatusTrackerObserver::
 {
   NS_NOTREACHED("imgRequest(imgIDecoderObserver)::OnStartRequest");
   return NS_OK;
 }
 
 /* void onStartContainer (); */
 NS_IMETHODIMP imgStatusTrackerObserver::OnStartContainer()
 {
-  LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnStartContainer");
+  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStartContainer");
 
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "OnStartContainer callback before we've created our image");
   mTracker->RecordStartContainer(mTracker->GetImage());
 
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
   while (iter.HasMore()) {
     mTracker->SendStartContainer(iter.GetNext());
   }
 
   return NS_OK;
 }
 
 /* [noscript] void onDataAvailable ([const] in nsIntRect rect); */
 NS_IMETHODIMP imgStatusTrackerObserver::OnDataAvailable(const nsIntRect * rect)
 {
-  LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnDataAvailable");
+  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnDataAvailable");
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "OnDataAvailable callback before we've created our image");
 
   mTracker->RecordDataAvailable();
 
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
   while (iter.HasMore()) {
     mTracker->SendDataAvailable(iter.GetNext(), rect);
   }
 
   return NS_OK;
 }
 
 /* void onStopFrame (); */
 NS_IMETHODIMP imgStatusTrackerObserver::OnStopFrame()
 {
-  LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnStopFrame");
+  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStopFrame");
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "OnStopFrame callback before we've created our image");
 
   mTracker->RecordStopFrame();
 
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
   while (iter.HasMore()) {
     mTracker->SendStopFrame(iter.GetNext());
@@ -147,17 +147,17 @@ FireFailureNotification(imgRequest* aReq
     aRequest->GetURI(getter_AddRefs(uri));
     os->NotifyObservers(uri, "net:failed-to-process-uri-content", nullptr);
   }
 }
 
 /* void onStopDecode (in nsresult status); */
 NS_IMETHODIMP imgStatusTrackerObserver::OnStopDecode(nsresult aStatus)
 {
-  LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnStopDecode");
+  LOG_SCOPE(GetImgLog(), "imgStatusTrackerObserver::OnStopDecode");
   NS_ABORT_IF_FALSE(mTracker->GetImage(),
                     "OnStopDecode callback before we've created our image");
 
   // We finished the decode, and thus have the decoded frames. Update the cache
   // entry size to take this into account.
   if (mTracker->GetRequest()) {
     mTracker->GetRequest()->UpdateCacheEntrySize();
   }
@@ -308,17 +308,17 @@ class imgRequestNotifyRunnable : public 
 void
 imgStatusTracker::Notify(imgRequest* request, imgRequestProxy* proxy)
 {
 #ifdef PR_LOGGING
   nsCOMPtr<nsIURI> uri;
   request->GetURI(getter_AddRefs(uri));
   nsAutoCString spec;
   uri->GetSpec(spec);
-  LOG_FUNC_WITH_PARAM(gImgLog, "imgStatusTracker::Notify async", "uri", spec.get());
+  LOG_FUNC_WITH_PARAM(GetImgLog(), "imgStatusTracker::Notify async", "uri", spec.get());
 #endif
 
   proxy->SetNotificationsDeferred(true);
 
   // If we have an existing runnable that we can use, we just append this proxy
   // to its list of proxies to be notified. This ensures we don't unnecessarily
   // delay onload.
   imgRequestNotifyRunnable* runnable = static_cast<imgRequestNotifyRunnable*>(mRequestRunnable.get());
@@ -362,17 +362,17 @@ class imgStatusNotifyRunnable : public n
 void
 imgStatusTracker::NotifyCurrentState(imgRequestProxy* proxy)
 {
 #ifdef PR_LOGGING
   nsCOMPtr<nsIURI> uri;
   proxy->GetURI(getter_AddRefs(uri));
   nsAutoCString spec;
   uri->GetSpec(spec);
-  LOG_FUNC_WITH_PARAM(gImgLog, "imgStatusTracker::NotifyCurrentState", "uri", spec.get());
+  LOG_FUNC_WITH_PARAM(GetImgLog(), "imgStatusTracker::NotifyCurrentState", "uri", spec.get());
 #endif
 
   proxy->SetNotificationsDeferred(true);
 
   // We don't keep track of 
   nsCOMPtr<nsIRunnable> ev = new imgStatusNotifyRunnable(*this, proxy);
   NS_DispatchToCurrentThread(ev);
 }
@@ -380,17 +380,17 @@ imgStatusTracker::NotifyCurrentState(img
 void
 imgStatusTracker::SyncNotify(imgRequestProxy* proxy)
 {
 #ifdef PR_LOGGING
   nsCOMPtr<nsIURI> uri;
   proxy->GetURI(getter_AddRefs(uri));
   nsAutoCString spec;
   uri->GetSpec(spec);
-  LOG_SCOPE_WITH_PARAM(gImgLog, "imgStatusTracker::SyncNotify", "uri", spec.get());
+  LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgStatusTracker::SyncNotify", "uri", spec.get());
 #endif
 
   nsCOMPtr<imgIRequest> kungFuDeathGrip(proxy);
 
   // OnStartRequest
   if (mState & stateRequestStarted)
     proxy->OnStartRequest();
 
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -171,18 +171,25 @@ using namespace mozilla;
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG /* Allow logging in the release build */
 #endif
 
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 
-static PRLogModuleInfo * kPrintingLogMod = PR_NewLogModule("printing");
-#define PR_PL(_p1)  PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1);
+static PRLogModuleInfo *
+GetPrintingLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("printing");
+  return sLog;
+}
+#define PR_PL(_p1)  PR_LOG(GetPrintingLog(), PR_LOG_DEBUG, _p1);
 
 #define PRT_YESNO(_p) ((_p)?"YES":"NO")
 #else
 #define PRT_YESNO(_p)
 #define PR_PL(_p1)
 #endif
 //-----------------------------------------------------
 
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -11,17 +11,24 @@
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "prlog.h"
 
 using namespace mozilla::css;
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo* nsFlexContainerFrameLM = PR_NewLogModule("nsFlexContainerFrame");
+static PRLogModuleInfo*
+GetFlexContainerLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsFlexContainerFrame");
+  return sLog;
+}
 #endif /* PR_LOGGING */
 
 // XXXdholbert Some of this helper-stuff should be separated out into a general
 // "LogicalAxisUtils.h" helper.  Should that be a class, or a namespace (under
 // what super-namespace?), or what?
 
 // Helper enums
 // ============
@@ -1083,17 +1090,17 @@ ShouldUseFlexGrow(nscoord aTotalFreeSpac
 // margin-box sizes, but we can have fewer values in play & a simpler algorithm
 // if we subtract margin/border/padding up front.)
 void
 nsFlexContainerFrame::ResolveFlexibleLengths(
   const FlexboxAxisTracker& aAxisTracker,
   nscoord aFlexContainerMainSize,
   nsTArray<FlexItem>& aItems)
 {
-  PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG, ("ResolveFlexibleLengths\n"));
+  PR_LOG(GetFlexContainerLog(), PR_LOG_DEBUG, ("ResolveFlexibleLengths\n"));
   if (aItems.IsEmpty()) {
     return;
   }
 
   // Subtract space occupied by our items' margins/borders/padding, so we can
   // just be dealing with the space available for our flex items' content
   // boxes.
   nscoord spaceAvailableForFlexItemsContentBoxes = aFlexContainerMainSize;
@@ -1122,17 +1129,17 @@ nsFlexContainerFrame::ResolveFlexibleLen
     for (uint32_t i = 0; i < aItems.Length(); i++) {
       FlexItem& item = aItems[i];
       if (!item.IsFrozen()) {
         item.SetMainSize(item.GetFlexBaseSize());
       }
       availableFreeSpace -= item.GetMainSize();
     }
 
-    PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG,
+    PR_LOG(GetFlexContainerLog(), PR_LOG_DEBUG,
            (" available free space = %d\n", availableFreeSpace));
 
     // If sign of free space matches flexType, give each flexible
     // item a portion of availableFreeSpace.
     if ((availableFreeSpace > 0 && havePositiveFreeSpace) ||
         (availableFreeSpace < 0 && !havePositiveFreeSpace)) {
 
       // STRATEGY: On each item, we compute & store its "share" of the total
@@ -1175,17 +1182,17 @@ nsFlexContainerFrame::ResolveFlexibleLen
           largestFlexWeight = curFlexWeight;
           numItemsWithLargestFlexWeight = 1;
         } else if (curFlexWeight == largestFlexWeight) {
           numItemsWithLargestFlexWeight++;
         }
       }
 
       if (runningFlexWeightSum != 0.0f) { // no distribution if no flexibility
-        PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG,
+        PR_LOG(GetFlexContainerLog(), PR_LOG_DEBUG,
                (" Distributing available space:"));
         for (uint32_t i = aItems.Length() - 1; i < aItems.Length(); --i) {
           FlexItem& item = aItems[i];
 
           if (!item.IsFrozen()) {
             // To avoid rounding issues, we compute the change in size for this
             // item, and then subtract it from the remaining available space.
             nscoord sizeDelta = 0;
@@ -1214,27 +1221,27 @@ nsFlexContainerFrame::ResolveFlexibleLen
                 NSToCoordRound(availableFreeSpace /
                                float(numItemsWithLargestFlexWeight));
               numItemsWithLargestFlexWeight--;
             }
 
             availableFreeSpace -= sizeDelta;
 
             item.SetMainSize(item.GetMainSize() + sizeDelta);
-            PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG,
+            PR_LOG(GetFlexContainerLog(), PR_LOG_DEBUG,
                    ("  child %d receives %d, for a total of %d\n",
                     i, sizeDelta, item.GetMainSize()));
           }
         }
       }
     }
 
     // Fix min/max violations:
     nscoord totalViolation = 0; // keeps track of adjustments for min/max
-    PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG,
+    PR_LOG(GetFlexContainerLog(), PR_LOG_DEBUG,
            (" Checking for violations:"));
 
     for (uint32_t i = 0; i < aItems.Length(); i++) {
       FlexItem& item = aItems[i];
       if (!item.IsFrozen()) {
         if (item.GetMainSize() < item.GetMainMinSize()) {
           // min violation
           totalViolation += item.GetMainMinSize() - item.GetMainSize();
@@ -1246,17 +1253,17 @@ nsFlexContainerFrame::ResolveFlexibleLen
           item.SetMainSize(item.GetMainMaxSize());
           item.SetHadMaxViolation();
         }
       }
     }
 
     FreezeOrRestoreEachFlexibleSize(totalViolation, aItems);
 
-    PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG,
+    PR_LOG(GetFlexContainerLog(), PR_LOG_DEBUG,
            (" Total violation: %d\n", totalViolation));
 
     if (totalViolation == 0) {
       break;
     }
   }
 
   // Post-condition: all lengths should've been frozen.
@@ -1941,17 +1948,17 @@ nsFlexContainerFrame::PositionItemInCros
 NS_IMETHODIMP
 nsFlexContainerFrame::Reflow(nsPresContext*           aPresContext,
                              nsHTMLReflowMetrics&     aDesiredSize,
                              const nsHTMLReflowState& aReflowState,
                              nsReflowStatus&          aStatus)
 {
   DO_GLOBAL_REFLOW_COUNT("nsFlexContainerFrame");
   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
-  PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG,
+  PR_LOG(GetFlexContainerLog(), PR_LOG_DEBUG,
          ("Reflow() for nsFlexContainerFrame %p\n", this));
 
   // We (and our children) can only depend on our ancestor's height if we have
   // a percent-height.  (There are actually other cases, too -- e.g. if our
   // parent is itself a vertical flex container and we're flexible -- but we'll
   // let our ancestors handle those sorts of cases.)
   if (GetStylePosition()->mHeight.HasPercent()) {
     AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -149,17 +149,24 @@ using mozilla::DefaultXDisplay;
 #include "GLContext.h"
 #endif
 
 #ifdef CreateEvent // Thank you MS.
 #undef CreateEvent
 #endif
 
 #ifdef PR_LOGGING 
-static PRLogModuleInfo *nsObjectFrameLM = PR_NewLogModule("nsObjectFrame");
+static PRLogModuleInfo *
+GetObjectFrameLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsObjectFrame");
+  return sLog;
+}
 #endif /* PR_LOGGING */
 
 #if defined(XP_MACOSX) && !defined(__LP64__)
 
 // The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
 // and up (though the QuickDraw APIs defined in them are still present) -- so
 // we need to supply the relevant parts of their contents here.  It's likely
 // that Apple will eventually remove the APIs themselves (probably in OS X
@@ -244,23 +251,23 @@ protected:
   uint64_t mLastSequenceNumber;
   nsObjectFrame* mFrame;
 };
 
 nsObjectFrame::nsObjectFrame(nsStyleContext* aContext)
   : nsObjectFrameSuper(aContext)
   , mReflowCallbackPosted(false)
 {
-  PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
+  PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
          ("Created new nsObjectFrame %p\n", this));
 }
 
 nsObjectFrame::~nsObjectFrame()
 {
-  PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
+  PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
          ("nsObjectFrame %p deleted\n", this));
 }
 
 NS_QUERYFRAME_HEAD(nsObjectFrame)
   NS_QUERYFRAME_ENTRY(nsObjectFrame)
   NS_QUERYFRAME_ENTRY(nsIObjectFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsObjectFrameSuper)
 
@@ -280,17 +287,17 @@ NS_IMETHODIMP nsObjectFrame::GetPluginPo
 #endif
 #endif
 
 NS_IMETHODIMP 
 nsObjectFrame::Init(nsIContent*      aContent,
                     nsIFrame*        aParent,
                     nsIFrame*        aPrevInFlow)
 {
-  PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
+  PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
          ("Initializing nsObjectFrame %p for content %p\n", this, aContent));
 
   nsresult rv = nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
 
   return rv;
 }
 
 void
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -20,18 +20,18 @@
 #ifdef IBMBIDI
 #include "nsBidiUtils.h"
 #endif
 #include "nsIPrintSettings.h"
 #include "nsRegion.h"
 
 #include "prlog.h"
 #ifdef PR_LOGGING 
-extern PRLogModuleInfo * kLayoutPrintingLogMod;
-#define PR_PL(_p1)  PR_LOG(kLayoutPrintingLogMod, PR_LOG_DEBUG, _p1)
+extern PRLogModuleInfo *GetLayoutPrintingLog();
+#define PR_PL(_p1)  PR_LOG(GetLayoutPrintingLog(), PR_LOG_DEBUG, _p1)
 #else
 #define PR_PL(_p1)
 #endif
 
 nsIFrame*
 NS_NewPageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsPageFrame(aContext);
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -36,18 +36,25 @@
 using namespace mozilla;
 
 static const char sPrintOptionsContractID[] = "@mozilla.org/gfx/printsettings-service;1";
 
 //
 
 #include "prlog.h"
 #ifdef PR_LOGGING 
-PRLogModuleInfo * kLayoutPrintingLogMod = PR_NewLogModule("printing-layout");
-#define PR_PL(_p1)  PR_LOG(kLayoutPrintingLogMod, PR_LOG_DEBUG, _p1)
+PRLogModuleInfo *
+GetLayoutPrintingLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("printing-layout");
+  return sLog;
+}
+#define PR_PL(_p1)  PR_LOG(GetLayoutPrintingLog(), PR_LOG_DEBUG, _p1)
 #else
 #define PR_PL(_p1)
 #endif
 
 // This object a shared by all the nsPageFrames 
 // parented to a SimplePageSequenceFrame
 nsSharedPageData::nsSharedPageData() :
   mDateTimeStr(nullptr),
--- a/layout/printing/nsPrintData.cpp
+++ b/layout/printing/nsPrintData.cpp
@@ -17,18 +17,25 @@
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG /* Allow logging in the release build */
 #endif
 
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 #define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info
-static PRLogModuleInfo * kPrintingLogMod = PR_NewLogModule("printing");
-#define PR_PL(_p1)  PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1);
+static PRLogModuleInfo *
+GetPrintingLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("printing");
+  return sLog;
+}
+#define PR_PL(_p1)  PR_LOG(GetPrintingLog(), PR_LOG_DEBUG, _p1);
 #else
 #define PRT_YESNO(_p)
 #define PR_PL(_p1)
 #endif
 
 //---------------------------------------------------
 //-- nsPrintData Class Impl
 //---------------------------------------------------
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -141,18 +141,25 @@ using namespace mozilla::dom;
 #ifdef DEBUG
 // PR_LOGGING is force to always be on (even in release builds)
 // but we only want some of it on,
 //#define EXTENDED_DEBUG_PRINTING 
 #endif
 
 #define DUMP_LAYOUT_LEVEL 9 // this turns on the dumping of each doucment's layout info
 
-static PRLogModuleInfo * kPrintingLogMod = PR_NewLogModule("printing");
-#define PR_PL(_p1)  PR_LOG(kPrintingLogMod, PR_LOG_DEBUG, _p1);
+static PRLogModuleInfo *
+GetPrintingLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("printing");
+  return sLog;
+}
+#define PR_PL(_p1)  PR_LOG(GetPrintingLog(), PR_LOG_DEBUG, _p1);
 
 #ifdef EXTENDED_DEBUG_PRINTING
 static uint32_t gDumpFileNameCnt   = 0;
 static uint32_t gDumpLOFileNameCnt = 0;
 #endif
 
 #define PRT_YESNO(_p) ((_p)?"YES":"NO")
 static const char * gFrameTypesStr[]       = {"eDoc", "eFrame", "eIFrame", "eFrameSet"};
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -246,29 +246,36 @@ private:
 };
 
 #ifdef MOZ_LOGGING
 // #define FORCE_PR_LOG /* Allow logging in the release build */
 #endif /* MOZ_LOGGING */
 #include "prlog.h"
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *gLoaderLog = PR_NewLogModule("nsCSSLoader");
+static PRLogModuleInfo *
+GetLoaderLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsCSSLoader");
+  return sLog;
+}
 #endif /* PR_LOGGING */
 
-#define LOG_FORCE(args) PR_LOG(gLoaderLog, PR_LOG_ALWAYS, args)
-#define LOG_ERROR(args) PR_LOG(gLoaderLog, PR_LOG_ERROR, args)
-#define LOG_WARN(args) PR_LOG(gLoaderLog, PR_LOG_WARNING, args)
-#define LOG_DEBUG(args) PR_LOG(gLoaderLog, PR_LOG_DEBUG, args)
+#define LOG_FORCE(args) PR_LOG(GetLoaderLog(), PR_LOG_ALWAYS, args)
+#define LOG_ERROR(args) PR_LOG(GetLoaderLog(), PR_LOG_ERROR, args)
+#define LOG_WARN(args) PR_LOG(GetLoaderLog(), PR_LOG_WARNING, args)
+#define LOG_DEBUG(args) PR_LOG(GetLoaderLog(), PR_LOG_DEBUG, args)
 #define LOG(args) LOG_DEBUG(args)
 
-#define LOG_FORCE_ENABLED() PR_LOG_TEST(gLoaderLog, PR_LOG_ALWAYS)
-#define LOG_ERROR_ENABLED() PR_LOG_TEST(gLoaderLog, PR_LOG_ERROR)
-#define LOG_WARN_ENABLED() PR_LOG_TEST(gLoaderLog, PR_LOG_WARNING)
-#define LOG_DEBUG_ENABLED() PR_LOG_TEST(gLoaderLog, PR_LOG_DEBUG)
+#define LOG_FORCE_ENABLED() PR_LOG_TEST(GetLoaderLog(), PR_LOG_ALWAYS)
+#define LOG_ERROR_ENABLED() PR_LOG_TEST(GetLoaderLog(), PR_LOG_ERROR)
+#define LOG_WARN_ENABLED() PR_LOG_TEST(GetLoaderLog(), PR_LOG_WARNING)
+#define LOG_DEBUG_ENABLED() PR_LOG_TEST(GetLoaderLog(), PR_LOG_DEBUG)
 #define LOG_ENABLED() LOG_DEBUG_ENABLED()
 
 #ifdef PR_LOGGING
 #define LOG_URI(format, uri)                        \
   PR_BEGIN_MACRO                                    \
     NS_ASSERTION(uri, "Logging null uri");          \
     if (LOG_ENABLED()) {                            \
       nsAutoCString _logURISpec;                    \
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -39,21 +39,28 @@
 #include "nsIConsoleService.h"
 
 #include "nsStyleSet.h"
 #include "nsPrintfCString.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *gFontDownloaderLog = PR_NewLogModule("fontdownloader");
+static PRLogModuleInfo *
+GetFontDownloaderLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("fontdownloader");
+  return sLog;
+}
 #endif /* PR_LOGGING */
 
-#define LOG(args) PR_LOG(gFontDownloaderLog, PR_LOG_DEBUG, args)
-#define LOG_ENABLED() PR_LOG_TEST(gFontDownloaderLog, PR_LOG_DEBUG)
+#define LOG(args) PR_LOG(GetFontDownloaderLog(), PR_LOG_DEBUG, args)
+#define LOG_ENABLED() PR_LOG_TEST(GetFontDownloaderLog(), PR_LOG_DEBUG)
 
 
 nsFontFaceLoader::nsFontFaceLoader(gfxProxyFontEntry *aProxy, nsIURI *aFontURI,
                                    nsUserFontSet *aFontSet, nsIChannel *aChannel)
   : mFontEntry(aProxy), mFontURI(aFontURI), mFontSet(aFontSet),
     mChannel(aChannel)
 {
   mFontFamily = aProxy->Family();
@@ -749,18 +756,18 @@ nsUserFontSet::LogMessage(gfxProxyFontEn
       msg.AppendInt(static_cast<uint32_t>(aStatus));
       break;
     }
   }
   msg.Append("\nsource: ");
   msg.Append(fontURI);
 
 #ifdef PR_LOGGING
-  if (PR_LOG_TEST(sUserFontsLog, PR_LOG_DEBUG)) {
-    PR_LOG(sUserFontsLog, PR_LOG_DEBUG,
+  if (PR_LOG_TEST(GetUserFontsLog(), PR_LOG_DEBUG)) {
+    PR_LOG(GetUserFontsLog(), PR_LOG_DEBUG,
            ("userfonts (%p) %s", this, msg.get()));
   }
 #endif
 
   // try to give the user an indication of where the rule came from
   nsCSSFontFaceRule* rule = FindRuleForEntry(aProxy);
   nsString href;
   nsString text;
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -229,25 +229,25 @@ public class GeckoAppShell
 
     public static native void processNextNativeEvent();
 
     public static native void notifyBatteryChange(double aLevel, boolean aCharging, double aRemainingTime);
 
     public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
     public static native int  saveMessageInSentbox(String aReceiver, String aBody, long aTimestamp);
     public static native void notifySmsSent(int aId, String aReceiver, String aBody, long aTimestamp, int aRequestId, long aProcessId);
-    public static native void notifySmsDelivered(int aId, String aReceiver, String aBody, long aTimestamp);
+    public static native void notifySmsDelivery(int aId, int aDeliveryStatus, String aReceiver, String aBody, long aTimestamp);
     public static native void notifySmsSendFailed(int aError, int aRequestId, long aProcessId);
-    public static native void notifyGetSms(int aId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
+    public static native void notifyGetSms(int aId, int aDeliveryStatus, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifyGetSmsFailed(int aError, int aRequestId, long aProcessId);
     public static native void notifySmsDeleted(boolean aDeleted, int aRequestId, long aProcessId);
     public static native void notifySmsDeleteFailed(int aError, int aRequestId, long aProcessId);
     public static native void notifyNoMessageInList(int aRequestId, long aProcessId);
-    public static native void notifyListCreated(int aListId, int aMessageId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
-    public static native void notifyGotNextMessage(int aMessageId, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
+    public static native void notifyListCreated(int aListId, int aMessageId, int aDeliveryStatus, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
+    public static native void notifyGotNextMessage(int aMessageId, int aDeliveryStatus, String aReceiver, String aSender, String aBody, long aTimestamp, int aRequestId, long aProcessId);
     public static native void notifyReadingMessageListFailed(int aError, int aRequestId, long aProcessId);
 
     public static native void scheduleComposite();
     public static native void schedulePauseComposition();
     public static native void scheduleResumeComposition(int width, int height);
     public static native float computeRenderIntegrity();
 
     public static native SurfaceBits getSurfaceBits(Surface surface);
--- a/mobile/android/base/GeckoSmsManager.java
+++ b/mobile/android/base/GeckoSmsManager.java
@@ -302,25 +302,43 @@ public class GeckoSmsManager
 
   private final static Uri kSmsContentUri     = Uri.parse("content://sms");
   private final static Uri kSmsSentContentUri = Uri.parse("content://sms/sent");
 
   private final static int kSmsTypeInbox      = 1;
   private final static int kSmsTypeSentbox    = 2;
 
   /*
-   * Keep the following error codes in syng with |DeliveryState| in:
+   * Keep the following state codes in syng with |DeliveryState| in:
    * dom/sms/src/Types.h
    */
   private final static int kDeliveryStateSent     = 0;
   private final static int kDeliveryStateReceived = 1;
   private final static int kDeliveryStateUnknown  = 2;
   private final static int kDeliveryStateEndGuard = 3;
 
-  private final static String[] kRequiredMessageRows = new String[] { "_id", "address", "body", "date", "type" };
+  /*
+   * Keep the following status codes in sync with |DeliveryStatus| in:
+   * dom/sms/src/Types.h
+   */
+  private final static int kDeliveryStatusNotApplicable = 0;
+  private final static int kDeliveryStatusSuccess       = 1;
+  private final static int kDeliveryStatusPending       = 2;
+  private final static int kDeliveryStatusError         = 3;
+
+  /*
+   * android.provider.Telephony.Sms.STATUS_*. Duplicated because they're not
+   * part of Android public API.
+   */
+  private final static int kInternalDeliveryStatusNone     = -1;
+  private final static int kInternalDeliveryStatusComplete = 0;
+  private final static int kInternalDeliveryStatusPending  = 32;
+  private final static int kInternalDeliveryStatusFailed   = 64;
+
+  private final static String[] kRequiredMessageRows = new String[] { "_id", "address", "body", "date", "type", "status" };
 
   public GeckoSmsManager() {
     SmsIOThread.getInstance().start();
   }
 
   public void start() {
     IntentFilter smsFilter = new IntentFilter();
     smsFilter.addAction(GeckoSmsManager.ACTION_SMS_RECEIVED);
@@ -408,19 +426,22 @@ public class GeckoSmsManager
 
       if (envelope.isFailing(part)) {
         if (part == Envelope.SubParts.SENT_PART) {
           GeckoAppShell.notifySmsSendFailed(envelope.getError(),
                                             bundle.getInt("requestId"),
                                             bundle.getLong("processId"));
           Log.i("GeckoSmsManager", "SMS sending failed!");
         } else {
-          // It seems unlikely to get a result code for a failure to deliver.
-          // Even if, we don't want to do anything with this.
-          Log.e("GeckoSmsManager", "SMS failed to be delivered... is that even possible?");
+          GeckoAppShell.notifySmsDelivery(envelope.getMessageId(),
+                                          kDeliveryStatusError,
+                                          bundle.getString("number"),
+                                          bundle.getString("message"),
+                                          envelope.getMessageTimestamp());
+          Log.i("GeckoSmsManager", "SMS delivery failed!");
         }
       } else {
         if (part == Envelope.SubParts.SENT_PART) {
           String number = bundle.getString("number");
           String message = bundle.getString("message");
           long timestamp = System.currentTimeMillis();
 
           int id = GeckoAppShell.saveMessageInSentbox(number, message, timestamp);
@@ -429,20 +450,21 @@ public class GeckoSmsManager
                                       bundle.getInt("requestId"),
                                       bundle.getLong("processId"));
 
           envelope.setMessageId(id);
           envelope.setMessageTimestamp(timestamp);
 
           Log.i("GeckoSmsManager", "SMS sending was successfull!");
         } else {
-          GeckoAppShell.notifySmsDelivered(envelope.getMessageId(),
-                                           bundle.getString("number"),
-                                           bundle.getString("message"),
-                                           envelope.getMessageTimestamp());
+          GeckoAppShell.notifySmsDelivery(envelope.getMessageId(),
+                                          kDeliveryStatusSuccess,
+                                          bundle.getString("number"),
+                                          bundle.getString("message"),
+                                          envelope.getMessageTimestamp());
           Log.i("GeckoSmsManager", "SMS successfully delivered!");
         }
       }
 
       // Destroy the envelope object only if the SMS has been sent and delivered.
       if (!envelope.arePartsRemaining(Envelope.SubParts.SENT_PART) &&
           !envelope.arePartsRemaining(Envelope.SubParts.DELIVERED_PART)) {
         postman.destroyEnvelope(envelopeId);
@@ -543,16 +565,18 @@ public class GeckoSmsManager
   }
 
   public int saveSentMessage(String aRecipient, String aBody, long aDate) {
     try {
       ContentValues values = new ContentValues();
       values.put("address", aRecipient);
       values.put("body", aBody);
       values.put("date", aDate);
+      // Always 'PENDING' because we always request status report.
+      values.put("status", kInternalDeliveryStatusPending);
 
       ContentResolver cr = GeckoApp.mAppContext.getContentResolver();
       Uri uri = cr.insert(kSmsSentContentUri, values);
 
       long id = ContentUris.parseId(uri);
 
       // The DOM API takes a 32bits unsigned int for the id. It's unlikely that
       // we happen to need more than that but it doesn't cost to check.
@@ -601,28 +625,32 @@ public class GeckoSmsManager
 
           cursor.moveToFirst();
 
           if (cursor.getInt(cursor.getColumnIndex("_id")) != mMessageId) {
             throw new UnmatchingIdException();
           }
 
           int type = cursor.getInt(cursor.getColumnIndex("type"));
+          int deliveryStatus;
           String sender = "";
           String receiver = "";
 
           if (type == kSmsTypeInbox) {
+            deliveryStatus = kDeliveryStatusSuccess;
             sender = cursor.getString(cursor.getColumnIndex("address"));
           } else if (type == kSmsTypeSentbox) {
+            deliveryStatus = getGeckoDeliveryStatus(cursor.getInt(cursor.getColumnIndex("status")));
             receiver = cursor.getString(cursor.getColumnIndex("address"));
           } else {
             throw new InvalidTypeException();
           }
 
           GeckoAppShell.notifyGetSms(cursor.getInt(cursor.getColumnIndex("_id")),
+                                     deliveryStatus,
                                      receiver, sender,
                                      cursor.getString(cursor.getColumnIndex("body")),
                                      cursor.getLong(cursor.getColumnIndex("date")),
                                      mRequestId, mProcessId);
         } catch (NotFoundException e) {
           Log.i("GeckoSmsManager", "Message id " + mMessageId + " not found");
           GeckoAppShell.notifyGetSmsFailed(kNotFoundError, mRequestId, mProcessId);
         } catch (UnmatchingIdException e) {
@@ -766,31 +794,35 @@ public class GeckoSmsManager
           if (cursor.getCount() == 0) {
             GeckoAppShell.notifyNoMessageInList(mRequestId, mProcessId);
             return;
           }
 
           cursor.moveToFirst();
 
           int type = cursor.getInt(cursor.getColumnIndex("type"));
+          int deliveryStatus;
           String sender = "";
           String receiver = "";
 
           if (type == kSmsTypeInbox) {
+            deliveryStatus = kDeliveryStatusSuccess;
             sender = cursor.getString(cursor.getColumnIndex("address"));
           } else if (type == kSmsTypeSentbox) {
+            deliveryStatus = getGeckoDeliveryStatus(cursor.getInt(cursor.getColumnIndex("status")));
             receiver = cursor.getString(cursor.getColumnIndex("address"));
           } else {
             throw new UnexpectedDeliveryStateException();
           }
 
           int listId = MessagesListManager.getInstance().add(cursor);
           closeCursor = false;
           GeckoAppShell.notifyListCreated(listId,
                                           cursor.getInt(cursor.getColumnIndex("_id")),
+                                          deliveryStatus,
                                           receiver, sender,
                                           cursor.getString(cursor.getColumnIndex("body")),
                                           cursor.getLong(cursor.getColumnIndex("date")),
                                           mRequestId, mProcessId);
         } catch (UnexpectedDeliveryStateException e) {
           Log.e("GeckoSmsManager", "Unexcepted delivery state type", e);
           GeckoAppShell.notifyReadingMessageListFailed(kUnknownError, mRequestId, mProcessId);
         } catch (Exception e) {
@@ -832,29 +864,33 @@ public class GeckoSmsManager
 
           if (!cursor.moveToNext()) {
             MessagesListManager.getInstance().remove(mListId);
             GeckoAppShell.notifyNoMessageInList(mRequestId, mProcessId);
             return;
           }
 
           int type = cursor.getInt(cursor.getColumnIndex("type"));
+          int deliveryStatus;
           String sender = "";
           String receiver = "";
 
           if (type == kSmsTypeInbox) {
+            deliveryStatus = kDeliveryStatusSuccess;
             sender = cursor.getString(cursor.getColumnIndex("address"));
           } else if (type == kSmsTypeSentbox) {
+            deliveryStatus = getGeckoDeliveryStatus(cursor.getInt(cursor.getColumnIndex("status")));
             receiver = cursor.getString(cursor.getColumnIndex("address"));
           } else {
             throw new UnexpectedDeliveryStateException();
           }
 
           int listId = MessagesListManager.getInstance().add(cursor);
           GeckoAppShell.notifyGotNextMessage(cursor.getInt(cursor.getColumnIndex("_id")),
+                                             deliveryStatus,
                                              receiver, sender,
                                              cursor.getString(cursor.getColumnIndex("body")),
                                              cursor.getLong(cursor.getColumnIndex("date")),
                                              mRequestId, mProcessId);
         } catch (UnexpectedDeliveryStateException e) {
           Log.e("GeckoSmsManager", "Unexcepted delivery state type", e);
           GeckoAppShell.notifyReadingMessageListFailed(kUnknownError, mRequestId, mProcessId);
         } catch (Exception e) {
@@ -878,16 +914,29 @@ public class GeckoSmsManager
     GeckoApp.mAppContext.unregisterReceiver(this);
   }
 
   public void shutdown() {
     SmsIOThread.getInstance().interrupt();
     MessagesListManager.getInstance().clear();
   }
 
+  private int getGeckoDeliveryStatus(int aDeliveryStatus) {
+    if (aDeliveryStatus == kInternalDeliveryStatusNone) {
+      return kDeliveryStatusNotApplicable;
+    }
+    if (aDeliveryStatus >= kInternalDeliveryStatusFailed) {
+      return kDeliveryStatusError;
+    }
+    if (aDeliveryStatus >= kInternalDeliveryStatusPending) {
+      return kDeliveryStatusPending;
+    }
+    return kDeliveryStatusSuccess;
+  }
+
   class IdTooHighException extends Exception {
     private static final long serialVersionUID = 29935575131092050L;
   }
 
   class InvalidTypeException extends Exception {
     private static final long serialVersionUID = 47436856832535912L;
   }
 
--- a/mobile/android/base/tests/testBookmarksTab.java.in
+++ b/mobile/android/base/tests/testBookmarksTab.java.in
@@ -1,14 +1,15 @@
 #filter substitution
 package @ANDROID_PACKAGE_NAME@.tests;
 
 import @ANDROID_PACKAGE_NAME@.*;
 import android.app.Activity;
 import android.content.ContentUris;
+import android.view.ViewGroup;
 import android.view.View;
 import android.widget.ListView;
 import android.widget.ExpandableListView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import android.widget.ImageView;
 import android.widget.TabHost;
 import android.text.TextUtils;
@@ -17,28 +18,29 @@ import android.content.ContentValues;
 import android.content.ContentResolver;
 import android.database.Cursor;
 import android.net.Uri;
 
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.io.File;
 
-/* Tests opening the all pages tab, that items look correct, clicking on an item
+/* Tests opening the bookmarks tab, that items look correct, clicking on an item
    and long tapping on an item
 */
 
 public class testBookmarksTab extends BaseTest {
-    private static final String ABOUT_HOME_URL = "about:home";
+    private static final int WAIT_FOR_CHILD_TIMEOUT = 2000;
     private String[] defaultBookmarksUrls = new String[] {
         "about:firefox",
         "about:home",
         "http://support.mozilla.org/en-US/mobile",
         "https://addons.mozilla.org/en-US/android/"
     };
+    private View mFirstChild;
 
     @Override
     protected int getTestType() {
         return TEST_MOCHITEST;
     }
 
     public void testBookmarksTab() {
         blockForGeckoReady();
@@ -46,19 +48,21 @@ public class testBookmarksTab extends Ba
 
         // add one page to desktop folders so that we can see them
         addBookmark("BOOKMARK_TITLE", url);
 
         testList(url);
         testContextMenu(url);
     }
 
+    private ListView list;
+
     private void testList(String url) {
         View child;
-        ListView list = getBookmarksList();
+        list = getBookmarksList();
 
         // Clear VKB so that list is not obscured
         mActions.sendSpecialKey(Actions.SpecialKey.BACK);
 
         mSolo.waitForText(url);
         mAsserter.ok(list != null, "checking that bookmarks list exists", list.toString());
 
         mAsserter.is(list.getChildCount(), 5, "bookmarks list has 5 children (defaults + a folder)");
@@ -97,45 +101,77 @@ public class testBookmarksTab extends Ba
 
         mActions.sendSpecialKey(Actions.SpecialKey.BACK);
         mAsserter.ok(mSolo.waitForText("about:home"), "Back moved up one level", "");
 
         mActions.sendSpecialKey(Actions.SpecialKey.BACK);
     }
 
     private void testContextMenu(String url) {
-        ListView list = getBookmarksList();
-
+        list = getBookmarksList();
         // Clear VKB so that list is not obscured
         mActions.sendSpecialKey(Actions.SpecialKey.BACK);
-
         mSolo.waitForText(url);
 
-        // test long tap on a folder, this should fail but will still open the folder
-        View child = list.getChildAt(0);
-        mSolo.clickLongOnView(child);
-        mAsserter.is(mSolo.waitForText("Open in New Tab"), false, "Folders have no context menu");
-        // pressing back should exit the folder
-        mActions.sendSpecialKey(Actions.SpecialKey.BACK);
-
-        // long tap on a bookmark should show a context menu with an edit option
-        child = list.getChildAt(1);
-        mSolo.clickLongOnView(child);
+        // wait for the bookmarks list to be populated
+        mFirstChild = null;
+        boolean success = waitForTest(new BooleanTest() {
+            public boolean test() {
+                mFirstChild = list.getChildAt(1);
+                if (mFirstChild == null) {
+                    return false;
+                }
+                if (mFirstChild instanceof android.view.ViewGroup) {
+                    ViewGroup group = (ViewGroup)mFirstChild;
+                    if (group.getChildCount() < 1) {
+                        return false;
+                    }
+                    for (int i = 0; i < group.getChildCount(); i++) {
+                        View grandChild = group.getChildAt(i);
+                        if (grandChild instanceof android.widget.TextView) {
+                            mAsserter.ok(true, "found TextView:", ((android.widget.TextView)grandChild).getText().toString());
+                        }
+                    }
+                } else {
+                    mAsserter.dumpLog("first child not a ViewGroup: "+mFirstChild);
+                    return false;
+                }
+                return true;
+            }
+        }, WAIT_FOR_CHILD_TIMEOUT);
+        if (success == true && mFirstChild != null) {
+            mAsserter.dumpLog("clickLongOnView: "+mFirstChild);
 
-        // TODO: Test clicking these does the right thing
-        mAsserter.ok(mSolo.waitForText("Open in New Tab"), "Context menu has New Tab option", "Open in New Tab");
-        mAsserter.ok(mSolo.searchText("Share", true), "Context menu has Share option", "Share");
-        mAsserter.ok(mSolo.searchText("Edit", true), "Context menu has Edit option", "Edit");
-        mAsserter.ok(mSolo.searchText("Remove", true), "Context menu has Remove option", "Remove");
-        mAsserter.ok(mSolo.searchText("Add to Home Screen", true), "Context menu has Add to Home Screen option", "Add to Home Screen");
+            // long tap on a bookmark should show a context menu with an edit option
+            mSolo.clickLongOnView(mFirstChild);
+
+            // TODO: Test clicking these does the right thing
+            mAsserter.ok(mSolo.waitForText("Open in New Tab"), "Context menu has New Tab option", "Open in New Tab");
+            mAsserter.ok(mSolo.searchText("Share", true), "Context menu has Share option", "Share");
+            mAsserter.ok(mSolo.searchText("Edit", true), "Context menu has Edit option", "Edit");
+            mAsserter.ok(mSolo.searchText("Remove", true), "Context menu has Remove option", "Remove");
+            mAsserter.ok(mSolo.searchText("Add to Home Screen", true), "Context menu has Add to Home Screen option", "Add to Home Screen");
+
+            // press back to exit the context menu
+            mActions.sendSpecialKey(Actions.SpecialKey.BACK);
 
-        // press back to exit the context menu
+            // test long tap on a folder, this should fail but will still open the folder
+            View child = list.getChildAt(0);
+            mSolo.clickLongOnView(child);
+            mAsserter.is(mSolo.waitForText("Open in New Tab"), false, "Folders have no context menu");
+
+            // pressing back should exit the folder
+            mActions.sendSpecialKey(Actions.SpecialKey.BACK);
+
+        } else {
+            mAsserter.ok(false, "waiting for bookmark item", "bookmark item available");
+        }
+
         // back again to exit the awesomebar
         mActions.sendSpecialKey(Actions.SpecialKey.BACK);
-        mActions.sendSpecialKey(Actions.SpecialKey.BACK);
     }
 
     private void compareRow(View child, int numTextViews, int numImageViews) {
         ArrayList<View> views = mSolo.getViews(child);
         ArrayList<ImageView> imageViews = new ArrayList<ImageView>();
         ArrayList<TextView> textViews = new ArrayList<TextView>();
 
         for (int j = 0; j < views.size(); j++) {
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -283,16 +283,34 @@ Java_org_mozilla_gecko_GeckoAppShell_ ##
 typedef return_type (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven, type8 eight); \
 static name ## _t f_ ## name; \
 extern "C" NS_EXPORT return_type JNICALL \
 Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven, type8 eight) \
 { \
   return f_ ## name(jenv, jc, one, two, three, four, five, six, seven, eight); \
 }
 
+#define SHELL_WRAPPER9_WITH_RETURN(name, return_type, type1, type2, type3, type4, type5, type6, type7, type8, type9) \
+typedef return_type (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven, type8 eight, type9 nine); \
+static name ## _t f_ ## name; \
+extern "C" NS_EXPORT return_type JNICALL \
+Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven, type8 eight, type9 nine) \
+{ \
+  return f_ ## name(jenv, jc, one, two, three, four, five, six, seven, eight, nine); \
+}
+
+#define SHELL_WRAPPER9(name,type1,type2,type3,type4,type5,type6,type7,type8, type9) \
+typedef void (*name ## _t)(JNIEnv *, jclass, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven, type8 eight, type9 nine); \
+static name ## _t f_ ## name; \
+extern "C" NS_EXPORT void JNICALL \
+Java_org_mozilla_gecko_GeckoAppShell_ ## name(JNIEnv *jenv, jclass jc, type1 one, type2 two, type3 three, type4 four, type5 five, type6 six, type7 seven, type8 eight, type9 nine) \
+{ \
+  f_ ## name(jenv, jc, one, two, three, four, five, six, seven, eight, nine); \
+}
+
 SHELL_WRAPPER0(nativeInit)
 SHELL_WRAPPER1(notifyGeckoOfEvent, jobject)
 SHELL_WRAPPER0(processNextNativeEvent)
 SHELL_WRAPPER1(setSurfaceView, jobject)
 SHELL_WRAPPER2(setLayerClient, jobject, jint)
 SHELL_WRAPPER0(onResume)
 SHELL_WRAPPER0(onLowMemory)
 SHELL_WRAPPER3(callObserver, jstring, jstring, jstring)
@@ -304,25 +322,25 @@ SHELL_WRAPPER3(notifyBatteryChange, jdou
 SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong)
 SHELL_WRAPPER0(bindWidgetTexture)
 SHELL_WRAPPER0(scheduleComposite)
 SHELL_WRAPPER0(schedulePauseComposition)
 SHELL_WRAPPER2(scheduleResumeComposition, jint, jint)
 SHELL_WRAPPER0_WITH_RETURN(computeRenderIntegrity, jfloat)
 SHELL_WRAPPER3_WITH_RETURN(saveMessageInSentbox, jint, jstring, jstring, jlong)
 SHELL_WRAPPER6(notifySmsSent, jint, jstring, jstring, jlong, jint, jlong)
-SHELL_WRAPPER4(notifySmsDelivered, jint, jstring, jstring, jlong)
+SHELL_WRAPPER5(notifySmsDelivery, jint, jint, jstring, jstring, jlong)
 SHELL_WRAPPER3(notifySmsSendFailed, jint, jint, jlong)
-SHELL_WRAPPER7(notifyGetSms, jint, jstring, jstring, jstring, jlong, jint, jlong)
+SHELL_WRAPPER8(notifyGetSms, jint, jint, jstring, jstring, jstring, jlong, jint, jlong)
 SHELL_WRAPPER3(notifyGetSmsFailed, jint, jint, jlong)
 SHELL_WRAPPER3(notifySmsDeleted, jboolean, jint, jlong)
 SHELL_WRAPPER3(notifySmsDeleteFailed, jint, jint, jlong)
 SHELL_WRAPPER2(notifyNoMessageInList, jint, jlong)
-SHELL_WRAPPER8(notifyListCreated, jint, jint, jstring, jstring, jstring, jlong, jint, jlong)
-SHELL_WRAPPER7(notifyGotNextMessage, jint, jstring, jstring, jstring, jlong, jint, jlong)
+SHELL_WRAPPER9(notifyListCreated, jint, jint, jint, jstring, jstring, jstring, jlong, jint, jlong)
+SHELL_WRAPPER8(notifyGotNextMessage, jint, jint, jstring, jstring, jstring, jlong, jint, jlong)
 SHELL_WRAPPER3(notifyReadingMessageListFailed, jint, jint, jlong)
 SHELL_WRAPPER2(notifyFilePickerResult, jstring, jlong)
 SHELL_WRAPPER1_WITH_RETURN(getSurfaceBits, jobject, jobject)
 SHELL_WRAPPER1(onFullScreenPluginHidden, jobject)
 SHELL_WRAPPER1_WITH_RETURN(getNextMessageFromQueue, jobject, jobject)
 SHELL_WRAPPER2(onSurfaceTextureFrameAvailable, jobject, jint)
 
 static void * xul_handle = NULL;
@@ -728,17 +746,17 @@ loadGeckoLibs(const char *apkName)
   GETFUNC(notifySmsReceived);
   GETFUNC(bindWidgetTexture);
   GETFUNC(scheduleComposite);
   GETFUNC(schedulePauseComposition);
   GETFUNC(scheduleResumeComposition);
   GETFUNC(computeRenderIntegrity);
   GETFUNC(saveMessageInSentbox);
   GETFUNC(notifySmsSent);
-  GETFUNC(notifySmsDelivered);
+  GETFUNC(notifySmsDelivery);
   GETFUNC(notifySmsSendFailed);
   GETFUNC(notifyGetSms);
   GETFUNC(notifyGetSmsFailed);
   GETFUNC(notifySmsDeleted);
   GETFUNC(notifySmsDeleteFailed);
   GETFUNC(notifyNoMessageInList);
   GETFUNC(notifyListCreated);
   GETFUNC(notifyGotNextMessage);
--- a/netwerk/base/src/nsAsyncRedirectVerifyHelper.cpp
+++ b/netwerk/base/src/nsAsyncRedirectVerifyHelper.cpp
@@ -13,18 +13,25 @@
 #include "nsNetUtil.h"
 
 #include "nsIOService.h"
 #include "nsIChannel.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *gLog = PR_NewLogModule("nsRedirect");
-#define LOG(args) PR_LOG(gLog, PR_LOG_DEBUG, args)
+static PRLogModuleInfo *
+GetRedirectLog()
+{
+    static PRLogModuleInfo *sLog;
+    if (!sLog)
+        sLog = PR_NewLogModule("nsRedirect");
+    return sLog;
+}
+#define LOG(args) PR_LOG(GetRedirectLog(), PR_LOG_DEBUG, args)
 #else
 #define LOG(args)
 #endif
 
 NS_IMPL_THREADSAFE_ISUPPORTS2(nsAsyncRedirectVerifyHelper,
                               nsIAsyncVerifyRedirectCallback,
                               nsIRunnable)
 
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -34,19 +34,26 @@
 #include "mozilla/CondVar.h"
 
 //----------------------------------------------------------------------------
 
 using namespace mozilla;
 
 #include "prlog.h"
 #if defined(PR_LOGGING)
-static PRLogModuleInfo *sLog = PR_NewLogModule("proxy");
+static PRLogModuleInfo *
+GetProxyLog()
+{
+    static PRLogModuleInfo *sLog;
+    if (!sLog)
+        sLog = PR_NewLogModule("proxy");
+    return sLog;
+}
 #endif
-#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetProxyLog(), PR_LOG_DEBUG, args)
 
 //----------------------------------------------------------------------------
 
 #define PROXY_PREF_BRANCH  "network.proxy"
 #define PROXY_PREF(x)      PROXY_PREF_BRANCH "." x
 
 #define WPAD_URL "http://wpad/wpad.dat"
 
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -172,125 +172,132 @@ struct nsListIter
 #include "prlog.h"
 #endif
 
 // define logging macros for convenience
 #define SET_COOKIE true
 #define GET_COOKIE false
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *sCookieLog = PR_NewLogModule("cookie");
+static PRLogModuleInfo *
+GetCookieLog()
+{
+  static PRLogModuleInfo *sCookieLog;
+  if (!sCookieLog)
+    sCookieLog = PR_NewLogModule("cookie");
+  return sCookieLog;
+}
 
 #define COOKIE_LOGFAILURE(a, b, c, d)    LogFailure(a, b, c, d)
 #define COOKIE_LOGSUCCESS(a, b, c, d, e) LogSuccess(a, b, c, d, e)
 
 #define COOKIE_LOGEVICTED(a, details)          \
   PR_BEGIN_MACRO                               \
-    if (PR_LOG_TEST(sCookieLog, PR_LOG_DEBUG)) \
+  if (PR_LOG_TEST(GetCookieLog(), PR_LOG_DEBUG))  \
       LogEvicted(a, details);                  \
   PR_END_MACRO
 
 #define COOKIE_LOGSTRING(lvl, fmt)   \
   PR_BEGIN_MACRO                     \
-    PR_LOG(sCookieLog, lvl, fmt);    \
-    PR_LOG(sCookieLog, lvl, ("\n")); \
+    PR_LOG(GetCookieLog(), lvl, fmt);  \
+    PR_LOG(GetCookieLog(), lvl, ("\n")); \
   PR_END_MACRO
 
 static void
 LogFailure(bool aSetCookie, nsIURI *aHostURI, const char *aCookieString, const char *aReason)
 {
   // if logging isn't enabled, return now to save cycles
-  if (!PR_LOG_TEST(sCookieLog, PR_LOG_WARNING))
+  if (!PR_LOG_TEST(GetCookieLog(), PR_LOG_WARNING))
     return;
 
   nsAutoCString spec;
   if (aHostURI)
     aHostURI->GetAsciiSpec(spec);
 
-  PR_LOG(sCookieLog, PR_LOG_WARNING,
+  PR_LOG(GetCookieLog(), PR_LOG_WARNING,
     ("===== %s =====\n", aSetCookie ? "COOKIE NOT ACCEPTED" : "COOKIE NOT SENT"));
-  PR_LOG(sCookieLog, PR_LOG_WARNING,("request URL: %s\n", spec.get()));
+  PR_LOG(GetCookieLog(), PR_LOG_WARNING,("request URL: %s\n", spec.get()));
   if (aSetCookie)
-    PR_LOG(sCookieLog, PR_LOG_WARNING,("cookie string: %s\n", aCookieString));
+    PR_LOG(GetCookieLog(), PR_LOG_WARNING,("cookie string: %s\n", aCookieString));
 
   PRExplodedTime explodedTime;
   PR_ExplodeTime(PR_Now(), PR_GMTParameters, &explodedTime);
   char timeString[40];
   PR_FormatTimeUSEnglish(timeString, 40, "%c GMT", &explodedTime);
 
-  PR_LOG(sCookieLog, PR_LOG_WARNING,("current time: %s", timeString));
-  PR_LOG(sCookieLog, PR_LOG_WARNING,("rejected because %s\n", aReason));
-  PR_LOG(sCookieLog, PR_LOG_WARNING,("\n"));
+  PR_LOG(GetCookieLog(), PR_LOG_WARNING,("current time: %s", timeString));
+  PR_LOG(GetCookieLog(), PR_LOG_WARNING,("rejected because %s\n", aReason));
+  PR_LOG(GetCookieLog(), PR_LOG_WARNING,("\n"));
 }
 
 static void
 LogCookie(nsCookie *aCookie)
 {
   PRExplodedTime explodedTime;
   PR_ExplodeTime(PR_Now(), PR_GMTParameters, &explodedTime);
   char timeString[40];
   PR_FormatTimeUSEnglish(timeString, 40, "%c GMT", &explodedTime);
 
-  PR_LOG(sCookieLog, PR_LOG_DEBUG,("current time: %s", timeString));
+  PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("current time: %s", timeString));
 
   if (aCookie) {
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("----------------\n"));
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("name: %s\n", aCookie->Name().get()));
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("value: %s\n", aCookie->Value().get()));
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("%s: %s\n", aCookie->IsDomain() ? "domain" : "host", aCookie->Host().get()));
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("path: %s\n", aCookie->Path().get()));
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("----------------\n"));
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("name: %s\n", aCookie->Name().get()));
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("value: %s\n", aCookie->Value().get()));
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("%s: %s\n", aCookie->IsDomain() ? "domain" : "host", aCookie->Host().get()));
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("path: %s\n", aCookie->Path().get()));
 
     PR_ExplodeTime(aCookie->Expiry() * int64_t(PR_USEC_PER_SEC),
                    PR_GMTParameters, &explodedTime);
     PR_FormatTimeUSEnglish(timeString, 40, "%c GMT", &explodedTime);
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,
       ("expires: %s%s", timeString, aCookie->IsSession() ? " (at end of session)" : ""));
 
     PR_ExplodeTime(aCookie->CreationTime(), PR_GMTParameters, &explodedTime);
     PR_FormatTimeUSEnglish(timeString, 40, "%c GMT", &explodedTime);
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("created: %s", timeString));
-
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("is secure: %s\n", aCookie->IsSecure() ? "true" : "false"));
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("is httpOnly: %s\n", aCookie->IsHttpOnly() ? "true" : "false"));
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("created: %s", timeString));
+
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("is secure: %s\n", aCookie->IsSecure() ? "true" : "false"));
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("is httpOnly: %s\n", aCookie->IsHttpOnly() ? "true" : "false"));
   }
 }
 
 static void
 LogSuccess(bool aSetCookie, nsIURI *aHostURI, const char *aCookieString, nsCookie *aCookie, bool aReplacing)
 {
   // if logging isn't enabled, return now to save cycles
-  if (!PR_LOG_TEST(sCookieLog, PR_LOG_DEBUG)) {
+  if (!PR_LOG_TEST(GetCookieLog(), PR_LOG_DEBUG)) {
     return;
   }
 
   nsAutoCString spec;
   if (aHostURI)
     aHostURI->GetAsciiSpec(spec);
 
-  PR_LOG(sCookieLog, PR_LOG_DEBUG,
+  PR_LOG(GetCookieLog(), PR_LOG_DEBUG,
     ("===== %s =====\n", aSetCookie ? "COOKIE ACCEPTED" : "COOKIE SENT"));
-  PR_LOG(sCookieLog, PR_LOG_DEBUG,("request URL: %s\n", spec.get()));
-  PR_LOG(sCookieLog, PR_LOG_DEBUG,("cookie string: %s\n", aCookieString));
+  PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("request URL: %s\n", spec.get()));
+  PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("cookie string: %s\n", aCookieString));
   if (aSetCookie)
-    PR_LOG(sCookieLog, PR_LOG_DEBUG,("replaces existing cookie: %s\n", aReplacing ? "true" : "false"));
+    PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("replaces existing cookie: %s\n", aReplacing ? "true" : "false"));
 
   LogCookie(aCookie);
 
-  PR_LOG(sCookieLog, PR_LOG_DEBUG,("\n"));
+  PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("\n"));
 }
 
 static void
 LogEvicted(nsCookie *aCookie, const char* details)
 {
-  PR_LOG(sCookieLog, PR_LOG_DEBUG,("===== COOKIE EVICTED =====\n"));
-  PR_LOG(sCookieLog, PR_LOG_DEBUG,("%s\n", details));
+  PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("===== COOKIE EVICTED =====\n"));
+  PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("%s\n", details));
 
   LogCookie(aCookie);
 
-  PR_LOG(sCookieLog, PR_LOG_DEBUG,("\n"));
+  PR_LOG(GetCookieLog(), PR_LOG_DEBUG,("\n"));
 }
 
 // inline wrappers to make passing in nsAFlatCStrings easier
 static inline void
 LogFailure(bool aSetCookie, nsIURI *aHostURI, const nsAFlatCString &aCookieString, const char *aReason)
 {
   LogFailure(aSetCookie, aHostURI, aCookieString.get(), aReason);
 }
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -26,17 +26,24 @@
 #include "nsNetUtil.h"
 #ifdef MOZ_PEERCONNECTION
 #include "mtransport/runnable_utils.h"
 #endif
 #include "DataChannel.h"
 #include "DataChannelProtocol.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo* dataChannelLog = PR_NewLogModule("DataChannel");
+PRLogModuleInfo*
+GetDataChannelLog()
+{
+  static PRLogModuleInfo* sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("DataChannel");
+  return sLog;
+}
 #endif
 
 static bool sctp_initialized;
 
 namespace mozilla {
 
 class DataChannelShutdown;
 nsCOMPtr<DataChannelShutdown> gDataChannelShutdown;
--- a/netwerk/sctp/datachannel/DataChannelLog.h
+++ b/netwerk/sctp/datachannel/DataChannelLog.h
@@ -14,15 +14,15 @@
 #if defined(PR_LOG)
 #error "This file must be #included before any IPDL-generated files or other files that #include prlog.h"
 #endif
 
 #include "base/basictypes.h"
 #include "prlog.h"
 
 #ifdef PR_LOGGING
-extern PRLogModuleInfo* dataChannelLog;
+extern PRLogModuleInfo* GetDataChannelLog();
 #endif
 
 #undef LOG
-#define LOG(args) PR_LOG(dataChannelLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetDataChannelLog(), PR_LOG_DEBUG, args)
 
 #endif
--- a/parser/htmlparser/src/nsExpatDriver.cpp
+++ b/parser/htmlparser/src/nsExpatDriver.cpp
@@ -28,17 +28,24 @@
 #include "nsXPCOMCIDInternal.h"
 #include "nsUnicharInputStream.h"
 
 #define kExpatSeparatorChar 0xFFFF
 
 static const PRUnichar kUTF16[] = { 'U', 'T', 'F', '-', '1', '6', '\0' };
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *gExpatDriverLog = PR_NewLogModule("expatdriver");
+static PRLogModuleInfo *
+GetExpatDriverLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("expatdriver");
+  return sLog;
+}
 #endif
 
 /***************************** EXPAT CALL BACKS ******************************/
 // The callback handlers that get called from the expat parser.
 
 static void
 Driver_HandleXMLDeclaration(void *aUserData,
                             const XML_Char *aVersion,
@@ -1026,17 +1033,17 @@ nsExpatDriver::ConsumeToken(nsScanner& a
   nsScannerIterator start = currentExpatPosition;
   start.advance(mExpatBuffered);
 
   // This is the end of the last buffer (at this point, more data could come in
   // later).
   nsScannerIterator end;
   aScanner.EndReading(end);
 
-  PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
+  PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
          ("Remaining in expat's buffer: %i, remaining in scanner: %i.",
           mExpatBuffered, Distance(start, end)));
 
   // We want to call Expat if we have more buffers, or if we know there won't
   // be more buffers (and so we want to flush the remaining data), or if we're
   // currently blocked and there's data in Expat's buffer.
   while (start != end || (mIsFinalChunk && !mMadeFinalCallToExpat) ||
          (BlockedOrInterrupted() && mExpatBuffered > 0)) {
@@ -1048,38 +1055,38 @@ nsExpatDriver::ConsumeToken(nsScanner& a
     if (blocked || noMoreBuffers) {
       // If we're blocked we just resume Expat so we don't need a buffer, if
       // there aren't any more buffers we pass a null buffer to Expat.
       buffer = nullptr;
       length = 0;
 
 #if defined(PR_LOGGING) || defined (DEBUG)
       if (blocked) {
-        PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
+        PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
                ("Resuming Expat, will parse data remaining in Expat's "
                 "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
                 NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
                                       mExpatBuffered).get()));
       }
       else {
         NS_ASSERTION(mExpatBuffered == Distance(currentExpatPosition, end),
                      "Didn't pass all the data to Expat?");
-        PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
+        PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
                ("Last call to Expat, will parse data remaining in Expat's "
                 "buffer.\nContent of Expat's buffer:\n-----\n%s\n-----\n",
                 NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
                                       mExpatBuffered).get()));
       }
 #endif
     }
     else {
       buffer = start.get();
       length = uint32_t(start.size_forward());
 
-      PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
+      PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
              ("Calling Expat, will parse data remaining in Expat's buffer and "
               "new data.\nContent of Expat's buffer:\n-----\n%s\n-----\nNew "
               "data:\n-----\n%s\n-----\n",
               NS_ConvertUTF16toUTF8(currentExpatPosition.get(),
                                     mExpatBuffered).get(),
               NS_ConvertUTF16toUTF8(start.get(), length).get()));
     }
 
@@ -1109,17 +1116,17 @@ nsExpatDriver::ConsumeToken(nsScanner& a
         // data.
         AppendUnicodeTo(oldExpatPosition, currentExpatPosition, mLastLine);
       }
     }
 
     mExpatBuffered += length - consumed;
 
     if (BlockedOrInterrupted()) {
-      PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
+      PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
              ("Blocked or interrupted parser (probably for loading linked "
               "stylesheets or scripts)."));
 
       aScanner.SetPosition(currentExpatPosition, true);
       aScanner.Mark();
 
       return mInternalState;
     }
@@ -1170,17 +1177,17 @@ nsExpatDriver::ConsumeToken(nsScanner& a
     // (e.g. if we spun the event loop in an inline script). Reload end now
     // to compensate.
     aScanner.EndReading(end);
   }
 
   aScanner.SetPosition(currentExpatPosition, true);
   aScanner.Mark();
 
-  PR_LOG(gExpatDriverLog, PR_LOG_DEBUG,
+  PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
          ("Remaining in expat's buffer: %i, remaining in scanner: %i.",
           mExpatBuffered, Distance(currentExpatPosition, end)));
 
   return NS_SUCCEEDED(mInternalState) ? kEOF : NS_OK;
 }
 
 NS_IMETHODIMP
 nsExpatDriver::WillBuildModel(const CParserContext& aParserContext,
--- a/security/manager/boot/src/nsStrictTransportSecurityService.cpp
+++ b/security/manager/boot/src/nsStrictTransportSecurityService.cpp
@@ -28,20 +28,27 @@
 // STS_KNOCKOUT.
 #include "nsSTSPreloadList.inc"
 
 #define STS_SET (nsIPermissionManager::ALLOW_ACTION)
 #define STS_UNSET (nsIPermissionManager::UNKNOWN_ACTION)
 #define STS_KNOCKOUT (nsIPermissionManager::DENY_ACTION)
 
 #if defined(PR_LOGGING)
-PRLogModuleInfo *gSTSLog = PR_NewLogModule("nsSTSService");
+static PRLogModuleInfo *
+GetSTSLog()
+{
+  static PRLogModuleInfo *gSTSLog;
+  if (!gSTSLog)
+    gSTSLog = PR_NewLogModule("nsSTSService");
+  return gSTSLog;
+}
 #endif
 
-#define STSLOG(args) PR_LOG(gSTSLog, 4, args)
+#define STSLOG(args) PR_LOG(GetSTSLog(), 4, args)
 
 #define STS_PARSER_FAIL_IF(test,args) \
   if (test) { \
     STSLOG(args); \
     return NS_ERROR_FAILURE; \
   }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/security/manager/ssl/src/nsNTLMAuthModule.cpp
+++ b/security/manager/ssl/src/nsNTLMAuthModule.cpp
@@ -17,20 +17,27 @@
 #include "nsString.h"
 #include "prsystem.h"
 #include "nss.h"
 #include "pk11func.h"
 #include "md4.h"
 #include "mozilla/Likely.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo *gNTLMLog = PR_NewLogModule("NTLM");
+static PRLogModuleInfo *
+GetNTLMLog()
+{
+  static PRLogModuleInfo *sNTLMLog;
+  if (!sNTLMLog)
+    sNTLMLog = PR_NewLogModule("NTLM");
+  return sNTLMLog;
+}
 
-#define LOG(x) PR_LOG(gNTLMLog, PR_LOG_DEBUG, x)
-#define LOG_ENABLED() PR_LOG_TEST(gNTLMLog, PR_LOG_DEBUG)
+#define LOG(x) PR_LOG(GetNTLMLog(), PR_LOG_DEBUG, x)
+#define LOG_ENABLED() PR_LOG_TEST(GetNTLMLog(), PR_LOG_DEBUG)
 #else
 #define LOG(x)
 #endif
 
 static void des_makekey(const uint8_t *raw, uint8_t *key);
 static void des_encrypt(const uint8_t *key, const uint8_t *src, uint8_t *hash);
 static void md5sum(const uint8_t *input, uint32_t inputLen, uint8_t *result);
 
--- a/toolkit/mozapps/extensions/ChromeManifestParser.jsm
+++ b/toolkit/mozapps/extensions/ChromeManifestParser.jsm
@@ -1,159 +1,159 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-var EXPORTED_SYMBOLS = ["ChromeManifestParser"];
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cr = Components.results;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/NetUtil.jsm");
-
-const MSG_JAR_FLUSH = "AddonJarFlush";
-
-
-/**
- * Sends local and remote notifications to flush a JAR file cache entry
- *
- * @param aJarFile
- *        The ZIP/XPI/JAR file as a nsIFile
- */
-function flushJarCache(aJarFile) {
-  Services.obs.notifyObservers(aJarFile, "flush-cache-entry", null);
-  Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageBroadcaster)
-    .broadcastAsyncMessage(MSG_JAR_FLUSH, aJarFile.path);
-}
-
-
-/**
- * Parses chrome manifest files.
- */
-var ChromeManifestParser = {
-
-  /**
-   * Reads and parses a chrome manifest file located at a specified URI, and all
-   * secondary manifests it references.
-   *
-   * @param  aURI
-   *         A nsIURI pointing to a chrome manifest.
-   *         Typically a file: or jar: URI.
-   * @return Array of objects describing each manifest instruction, in the form:
-   *         { type: instruction-type, baseURI: string-uri, args: [arguments] }
-   **/
-  parseSync: function CMP_parseSync(aURI) {
-    function parseLine(aLine) {
-      let line = aLine.trim();
-      if (line.length == 0 || line.charAt(0) == '#')
-        return;
-      let tokens = line.split(/\s+/);
-      let type = tokens.shift();
-      if (type == "manifest") {
-        let uri = NetUtil.newURI(tokens.shift(), null, aURI);
-        data = data.concat(this.parseSync(uri));
-      } else {
-        data.push({type: type, baseURI: baseURI, args: tokens});
-      }
-    }
-
-    let contents = "";
-    try {
-      if (aURI.scheme == "jar")
-        contents = this._readFromJar(aURI);
-      else
-        contents = this._readFromFile(aURI);
-    } catch (e) {
-      // Silently fail.
-    }
-
-    if (!contents)
-      return [];
-
-    let baseURI = NetUtil.newURI(".", null, aURI).spec;
-
-    let data = [];
-    let lines = contents.split("\n");
-    lines.forEach(parseLine.bind(this));
-    return data;
-  },
-  
-  _readFromJar: function CMP_readFromJar(aURI) {
-    let data = "";
-    let entries = [];
-    let readers = [];
-    
-    try {
-      // Deconstrict URI, which can be nested jar: URIs. 
-      let uri = aURI.clone();
-      while (uri instanceof Ci.nsIJARURI) {
-        entries.push(uri.JAREntry);
-        uri = uri.JARFile;
-      }
-
-      // Open the base jar.
-      let reader = Cc["@mozilla.org/libjar/zip-reader;1"].
-                   createInstance(Ci.nsIZipReader);
-      reader.open(uri.QueryInterface(Ci.nsIFileURL).file);
-      readers.push(reader);
-  
-      // Open the nested jars.
-      for (let i = entries.length - 1; i > 0; i--) {
-        let innerReader = Cc["@mozilla.org/libjar/zip-reader;1"].
-                          createInstance(Ci.nsIZipReader);
-        innerReader.openInner(reader, entries[i]);
-        readers.push(innerReader);
-        reader = innerReader;
-      }
-      
-      // First entry is the actual file we want to read.
-      let zis = reader.getInputStream(entries[0]);
-      data = NetUtil.readInputStreamToString(zis, zis.available());
-    }
-    finally {
-      // Close readers in reverse order.
-      for (let i = readers.length - 1; i >= 0; i--) {
-        readers[i].close();
-        flushJarCache(readers[i].file);
-      }
-    }
-    
-    return data;
-  },
-  
-  _readFromFile: function CMP_readFromFile(aURI) {
-    let file = aURI.QueryInterface(Ci.nsIFileURL).file;
-    if (!file.exists() || !file.isFile())
-      return "";
-    
-    let data = "";
-    let fis = Cc["@mozilla.org/network/file-input-stream;1"].
-              createInstance(Ci.nsIFileInputStream);
-    try {
-      fis.init(file, -1, -1, false);
-      data = NetUtil.readInputStreamToString(fis, fis.available());
-    } finally {
-      fis.close();
-    }
-    return data;
-  },
-
-  /**
-  * Detects if there were any instructions of a specified type in a given
-  * chrome manifest.
-  *
-  * @param  aManifest
-  *         Manifest data, as returned by ChromeManifestParser.parseSync().
-  * @param  aType
-  *         Instruction type to filter by.
-  * @return True if any matching instructions were found in the manifest.
-  */
-  hasType: function CMP_hasType(aManifest, aType) {
-    return aManifest.some(function hasType_matchEntryType(aEntry) {
-      return aEntry.type == aType;
-    });
-  }
-};
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+var EXPORTED_SYMBOLS = ["ChromeManifestParser"];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+
+const MSG_JAR_FLUSH = "AddonJarFlush";
+
+
+/**
+ * Sends local and remote notifications to flush a JAR file cache entry
+ *
+ * @param aJarFile
+ *        The ZIP/XPI/JAR file as a nsIFile
+ */
+function flushJarCache(aJarFile) {
+  Services.obs.notifyObservers(aJarFile, "flush-cache-entry", null);
+  Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageBroadcaster)
+    .broadcastAsyncMessage(MSG_JAR_FLUSH, aJarFile.path);
+}
+
+
+/**
+ * Parses chrome manifest files.
+ */
+var ChromeManifestParser = {
+
+  /**
+   * Reads and parses a chrome manifest file located at a specified URI, and all
+   * secondary manifests it references.
+   *
+   * @param  aURI
+   *         A nsIURI pointing to a chrome manifest.
+   *         Typically a file: or jar: URI.
+   * @return Array of objects describing each manifest instruction, in the form:
+   *         { type: instruction-type, baseURI: string-uri, args: [arguments] }
+   **/
+  parseSync: function CMP_parseSync(aURI) {
+    function parseLine(aLine) {
+      let line = aLine.trim();
+      if (line.length == 0 || line.charAt(0) == '#')
+        return;
+      let tokens = line.split(/\s+/);
+      let type = tokens.shift();
+      if (type == "manifest") {
+        let uri = NetUtil.newURI(tokens.shift(), null, aURI);
+        data = data.concat(this.parseSync(uri));
+      } else {
+        data.push({type: type, baseURI: baseURI, args: tokens});
+      }
+    }
+
+    let contents = "";
+    try {
+      if (aURI.scheme == "jar")
+        contents = this._readFromJar(aURI);
+      else
+        contents = this._readFromFile(aURI);
+    } catch (e) {
+      // Silently fail.
+    }
+
+    if (!contents)
+      return [];
+
+    let baseURI = NetUtil.newURI(".", null, aURI).spec;
+
+    let data = [];
+    let lines = contents.split("\n");
+    lines.forEach(parseLine.bind(this));
+    return data;
+  },
+  
+  _readFromJar: function CMP_readFromJar(aURI) {
+    let data = "";
+    let entries = [];
+    let readers = [];
+    
+    try {
+      // Deconstrict URI, which can be nested jar: URIs. 
+      let uri = aURI.clone();
+      while (uri instanceof Ci.nsIJARURI) {
+        entries.push(uri.JAREntry);
+        uri = uri.JARFile;
+      }
+
+      // Open the base jar.
+      let reader = Cc["@mozilla.org/libjar/zip-reader;1"].
+                   createInstance(Ci.nsIZipReader);
+      reader.open(uri.QueryInterface(Ci.nsIFileURL).file);
+      readers.push(reader);
+  
+      // Open the nested jars.
+      for (let i = entries.length - 1; i > 0; i--) {
+        let innerReader = Cc["@mozilla.org/libjar/zip-reader;1"].
+                          createInstance(Ci.nsIZipReader);
+        innerReader.openInner(reader, entries[i]);
+        readers.push(innerReader);
+        reader = innerReader;
+      }
+      
+      // First entry is the actual file we want to read.
+      let zis = reader.getInputStream(entries[0]);
+      data = NetUtil.readInputStreamToString(zis, zis.available());
+    }
+    finally {
+      // Close readers in reverse order.
+      for (let i = readers.length - 1; i >= 0; i--) {
+        readers[i].close();
+        flushJarCache(readers[i].file);
+      }
+    }
+    
+    return data;
+  },
+  
+  _readFromFile: function CMP_readFromFile(aURI) {
+    let file = aURI.QueryInterface(Ci.nsIFileURL).file;
+    if (!file.exists() || !file.isFile())
+      return "";
+    
+    let data = "";
+    let fis = Cc["@mozilla.org/network/file-input-stream;1"].
+              createInstance(Ci.nsIFileInputStream);
+    try {
+      fis.init(file, -1, -1, false);
+      data = NetUtil.readInputStreamToString(fis, fis.available());
+    } finally {
+      fis.close();
+    }
+    return data;
+  },
+
+  /**
+  * Detects if there were any instructions of a specified type in a given
+  * chrome manifest.
+  *
+  * @param  aManifest
+  *         Manifest data, as returned by ChromeManifestParser.parseSync().
+  * @param  aType
+  *         Instruction type to filter by.
+  * @return True if any matching instructions were found in the manifest.
+  */
+  hasType: function CMP_hasType(aManifest, aType) {
+    return aManifest.some(function hasType_matchEntryType(aEntry) {
+      return aEntry.type == aType;
+    });
+  }
+};
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -66,19 +66,26 @@
 //
 // A similar #define lives in updater.cpp and should be kept in sync with this.
 //
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
 #define USE_EXECV
 #endif
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *sUpdateLog = PR_NewLogModule("updatedriver");
+static PRLogModuleInfo *
+GetUpdateLog()
+{
+  static PRLogModuleInfo *sUpdateLog;
+  if (!sUpdateLog)
+    sUpdateLog = PR_NewLogModule("updatedriver");
+  return sUpdateLog;
+}
 #endif
-#define LOG(args) PR_LOG(sUpdateLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetUpdateLog(), PR_LOG_DEBUG, args)
 
 #ifdef XP_WIN
 static const char kUpdaterBin[] = "updater.exe";
 #else
 static const char kUpdaterBin[] = "updater";
 #endif
 static const char kUpdaterINI[] = "updater.ini";
 #ifdef XP_MACOSX
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -204,17 +204,18 @@ Java_org_mozilla_gecko_GeckoAppShell_not
         obs->NotifyObservers(message, kSmsReceivedObserverTopic, nullptr);
         return NS_OK;
       }
 
     private:
       SmsMessageData mMessageData;
     };
 
-    SmsMessageData message(0, eDeliveryState_Received, nsJNIString(aSender, jenv), EmptyString(),
+    SmsMessageData message(0, eDeliveryState_Received, eDeliveryStatus_Success,
+                           nsJNIString(aSender, jenv), EmptyString(),
                            nsJNIString(aBody, jenv), aTimestamp, false);
 
     nsCOMPtr<nsIRunnable> runnable = new NotifySmsReceivedRunnable(message);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT int32_t JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_saveMessageInSentbox(JNIEnv* jenv, jclass,
@@ -289,55 +290,60 @@ Java_org_mozilla_gecko_GeckoAppShell_not
       }
 
     private:
       SmsMessageData mMessageData;
       int32_t        mRequestId;
       uint64_t       mProcessId;
     };
 
-    SmsMessageData message(aId, eDeliveryState_Sent, EmptyString(),
-                           nsJNIString(aReceiver, jenv),
+    SmsMessageData message(aId, eDeliveryState_Sent, eDeliveryStatus_Pending,
+                           EmptyString(), nsJNIString(aReceiver, jenv),
                            nsJNIString(aBody, jenv), aTimestamp, true);
 
     nsCOMPtr<nsIRunnable> runnable = new NotifySmsSentRunnable(message, aRequestId, aProcessId);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT void JNICALL
-Java_org_mozilla_gecko_GeckoAppShell_notifySmsDelivered(JNIEnv* jenv, jclass,
-                                                        jint aId,
-                                                        jstring aReceiver,
-                                                        jstring aBody,
-                                                        jlong aTimestamp)
+Java_org_mozilla_gecko_GeckoAppShell_notifySmsDelivery(JNIEnv* jenv, jclass,
+                                                       jint aId,
+                                                       jint aDeliveryStatus,
+                                                       jstring aReceiver,
+                                                       jstring aBody,
+                                                       jlong aTimestamp)
 {
     class NotifySmsDeliveredRunnable : public nsRunnable {
     public:
       NotifySmsDeliveredRunnable(const SmsMessageData& aMessageData)
         : mMessageData(aMessageData)
       {}
 
       NS_IMETHODIMP Run() {
         nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
         if (!obs) {
           return NS_OK;
         }
 
         nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(mMessageData);
-        obs->NotifyObservers(message, kSmsDeliveredObserverTopic, nullptr);
+        const char* topic = (mMessageData.deliveryStatus() == eDeliveryStatus_Success)
+                            ? kSmsDeliverySuccessObserverTopic
+                            : kSmsDeliveryErrorObserverTopic;
+        obs->NotifyObservers(message, topic, nullptr);
 
         return NS_OK;
       }
 
     private:
       SmsMessageData mMessageData;
     };
 
-    SmsMessageData message(aId, eDeliveryState_Sent, EmptyString(),
-                           nsJNIString(aReceiver, jenv),
+    SmsMessageData message(aId, eDeliveryState_Sent,
+                           static_cast<DeliveryStatus>(aDeliveryStatus),
+                           EmptyString(), nsJNIString(aReceiver, jenv),
                            nsJNIString(aBody, jenv), aTimestamp, true);
 
     nsCOMPtr<nsIRunnable> runnable = new NotifySmsDeliveredRunnable(message);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifySmsSendFailed(JNIEnv* jenv, jclass,
@@ -386,16 +392,17 @@ Java_org_mozilla_gecko_GeckoAppShell_not
     nsCOMPtr<nsIRunnable> runnable =
       new NotifySmsSendFailedRunnable(aError, aRequestId, aProcessId);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifyGetSms(JNIEnv* jenv, jclass,
                                                   jint aId,
+                                                  jint aDeliveryStatus,
                                                   jstring aReceiver,
                                                   jstring aSender,
                                                   jstring aBody,
                                                   jlong aTimestamp,
                                                   jint aRequestId,
                                                   jlong aProcessId)
 {
     class NotifyGetSmsRunnable : public nsRunnable {
@@ -435,17 +442,19 @@ Java_org_mozilla_gecko_GeckoAppShell_not
       uint64_t       mProcessId;
     };
 
     nsJNIString receiver = nsJNIString(aReceiver, jenv);
     DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
                                              : eDeliveryState_Sent;
 
     // TODO Need to add the message `read` parameter value. Bug 748391
-    SmsMessageData message(aId, state, nsJNIString(aSender, jenv), receiver,
+    SmsMessageData message(aId, state,
+                           static_cast<DeliveryStatus>(aDeliveryStatus),
+                           nsJNIString(aSender, jenv), receiver,
                            nsJNIString(aBody, jenv), aTimestamp, true);
 
     nsCOMPtr<nsIRunnable> runnable = new NotifyGetSmsRunnable(message, aRequestId, aProcessId);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifyGetSmsFailed(JNIEnv* jenv, jclass,
@@ -635,16 +644,17 @@ Java_org_mozilla_gecko_GeckoAppShell_not
       new NotifyNoMessageInListRunnable(aRequestId, aProcessId);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifyListCreated(JNIEnv* jenv, jclass,
                                                        jint aListId,
                                                        jint aMessageId,
+                                                       jint aDeliveryStatus,
                                                        jstring aReceiver,
                                                        jstring aSender,
                                                        jstring aBody,
                                                        jlong aTimestamp,
                                                        jint aRequestId,
                                                        jlong aProcessId)
 {
     class NotifyCreateMessageListRunnable : public nsRunnable {
@@ -691,27 +701,30 @@ Java_org_mozilla_gecko_GeckoAppShell_not
     };
 
 
     nsJNIString receiver = nsJNIString(aReceiver, jenv);
     DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
                                              : eDeliveryState_Sent;
 
     // TODO Need to add the message `read` parameter value. Bug 748391
-    SmsMessageData message(aMessageId, state, nsJNIString(aSender, jenv),
-                           receiver, nsJNIString(aBody, jenv), aTimestamp, true);
+    SmsMessageData message(aMessageId, state,
+                           static_cast<DeliveryStatus>(aDeliveryStatus),
+                           nsJNIString(aSender, jenv), receiver,
+                           nsJNIString(aBody, jenv), aTimestamp, true);
 
     nsCOMPtr<nsIRunnable> runnable =
       new NotifyCreateMessageListRunnable(aListId, message, aRequestId, aProcessId);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifyGotNextMessage(JNIEnv* jenv, jclass,
                                                           jint aMessageId,
+                                                          jint aDeliveryStatus,
                                                           jstring aReceiver,
                                                           jstring aSender,
                                                           jstring aBody,
                                                           jlong aTimestamp,
                                                           jint aRequestId,
                                                           jlong aProcessId)
 {
     class NotifyGotNextMessageRunnable : public nsRunnable {
@@ -752,18 +765,20 @@ Java_org_mozilla_gecko_GeckoAppShell_not
     };
 
 
     nsJNIString receiver = nsJNIString(aReceiver, jenv);
     DeliveryState state = receiver.IsEmpty() ? eDeliveryState_Received
                                              : eDeliveryState_Sent;
  
     // TODO Need to add the message `read` parameter value. Bug 748391
-    SmsMessageData message(aMessageId, state, nsJNIString(aSender, jenv),
-                           receiver, nsJNIString(aBody, jenv), aTimestamp, true);
+    SmsMessageData message(aMessageId, state,
+                           static_cast<DeliveryStatus>(aDeliveryStatus),
+                           nsJNIString(aSender, jenv), receiver,
+                           nsJNIString(aBody, jenv), aTimestamp, true);
 
     nsCOMPtr<nsIRunnable> runnable =
       new NotifyGotNextMessageRunnable(message, aRequestId, aProcessId);
     NS_DispatchToMainThread(runnable);
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifyReadingMessageListFailed(JNIEnv* jenv, jclass,
--- a/widget/gtk2/nsDeviceContextSpecG.cpp
+++ b/widget/gtk2/nsDeviceContextSpecG.cpp
@@ -37,20 +37,27 @@
 
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING 
-static PRLogModuleInfo *DeviceContextSpecGTKLM = PR_NewLogModule("DeviceContextSpecGTK");
+static PRLogModuleInfo *
+GetDeviceContextSpecGTKLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("DeviceContextSpecGTK");
+  return sLog;
+}
 #endif /* PR_LOGGING */
 /* Macro to make lines shorter */
-#define DO_PR_DEBUG_LOG(x) PR_LOG(DeviceContextSpecGTKLM, PR_LOG_DEBUG, x)
+#define DO_PR_DEBUG_LOG(x) PR_LOG(GetDeviceContextSpecGTKLog(), PR_LOG_DEBUG, x)
 
 //----------------------------------------------------------------------------------
 // The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecGTK
 // The PrinterEnumerator creates the printer info
 // but the nsDeviceContextSpecGTK cleans it up
 // If it gets created (via the Page Setup Dialog) but the user never prints anything
 // then it will never be delete, so this class takes care of that.
 class GlobalPrinters {
--- a/widget/gtk2/nsWindow.cpp
+++ b/widget/gtk2/nsWindow.cpp
@@ -1809,61 +1809,64 @@ nsWindow::EnableDragDrop(bool aEnable)
 NS_IMETHODIMP
 nsWindow::CaptureMouse(bool aCapture)
 {
     LOG(("CaptureMouse %p\n", (void *)this));
 
     if (!mGdkWindow)
         return NS_OK;
 
-    GtkWidget *widget = GetMozContainerWidget();
-    if (!widget)
+    if (!mShell)
         return NS_ERROR_FAILURE;
 
     if (aCapture) {
-        gtk_grab_add(widget);
+        gtk_grab_add(mShell);
         GrabPointer(GetLastUserInputTime());
     }
     else {
         ReleaseGrabs();
-        gtk_grab_remove(widget);
+        gtk_grab_remove(mShell);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::CaptureRollupEvents(nsIRollupListener *aListener,
                               bool               aDoCapture)
 {
     if (!mGdkWindow)
         return NS_OK;
 
-    GtkWidget *widget = GetMozContainerWidget();
-    if (!widget)
+    if (!mShell)
         return NS_ERROR_FAILURE;
 
     LOG(("CaptureRollupEvents %p\n", (void *)this));
 
     if (aDoCapture) {
         gRollupListener = aListener;
         // real grab is only done when there is no dragging
         if (!nsWindow::DragInProgress()) {
-            gtk_grab_add(widget);
+            // This widget grab ensures that a Gecko GtkWidget receives mouse
+            // events even when embedded in non-Gecko-owned GtkWidgets.
+            // The grab is placed on the toplevel GtkWindow instead of the
+            // MozContainer to avoid double dispatch of keyboard events
+            // (bug 707623).
+            gtk_grab_add(mShell);
             GrabPointer(GetLastUserInputTime());
         }
     }
     else {
         if (!nsWindow::DragInProgress()) {
             ReleaseGrabs();
         }
         // There may not have been a drag in process when aDoCapture was set,
         // so make sure to remove any added grab.  This is a no-op if the grab
         // was not added to this widget.
-        gtk_grab_remove(widget);
+        gtk_grab_remove(mShell);
         gRollupListener = nullptr;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::GetAttention(int32_t aCycleCount)
--- a/xpcom/build/perfprobe.cpp
+++ b/xpcom/build/perfprobe.cpp
@@ -12,18 +12,25 @@
 
 #include "perfprobe.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace probes {
 
 #if defined(MOZ_LOGGING)
-static PRLogModuleInfo *gProbeLog = PR_NewLogModule("SysProbe");
-#define LOG(x)  PR_LOG(gProbeLog, PR_LOG_DEBUG, x)
+static PRLogModuleInfo *
+GetProbeLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("SysProbe");
+  return sLog;
+}
+#define LOG(x)  PR_LOG(GetProbeLog(), PR_LOG_DEBUG, x)
 #else
 #define LOG(x)
 #endif
 
 //Utility function
 GUID CID_to_GUID(const nsCID &aCID)
 {
   GUID result;
--- a/xpcom/ds/TimeStamp_windows.cpp
+++ b/xpcom/ds/TimeStamp_windows.cpp
@@ -63,18 +63,25 @@ HasStableTSC()
 //
 // To enable logging (see prlog.h for full details):
 //
 //    set NSPR_LOG_MODULES=TimeStampWindows:5
 //    set NSPR_LOG_FILE=nspr.log
 //
 // this enables PR_LOG_DEBUG level information and places all output in
 // the file nspr.log
-  PRLogModuleInfo* timeStampLog = PR_NewLogModule("TimeStampWindows");
-  #define LOG(x)  PR_LOG(timeStampLog, PR_LOG_DEBUG, x)
+static PRLogModuleInfo*
+GetTimeStampLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("TimeStampWindows");
+  return sLog;
+}
+  #define LOG(x)  PR_LOG(GetTimeStampLog(), PR_LOG_DEBUG, x)
 #else
   #define LOG(x)
 #endif /* PR_LOGGING */
 
 // Estimate of the smallest duration of time we can measure.
 static volatile ULONGLONG sResolution;
 static volatile ULONGLONG sResolutionSigDigs;
 static const double   kNsPerSecd  = 1000000000.0;
--- a/xpcom/ds/nsObserverService.cpp
+++ b/xpcom/ds/nsObserverService.cpp
@@ -25,18 +25,25 @@
 //
 // To enable logging (see prlog.h for full details):
 //
 //    set NSPR_LOG_MODULES=ObserverService:5
 //    set NSPR_LOG_FILE=nspr.log
 //
 // this enables PR_LOG_DEBUG level information and places all output in
 // the file nspr.log
-  PRLogModuleInfo* observerServiceLog = PR_NewLogModule("ObserverService");
-  #define LOG(x)  PR_LOG(observerServiceLog, PR_LOG_DEBUG, x)
+static PRLogModuleInfo*
+GetObserverServiceLog()
+{
+    static PRLogModuleInfo *sLog;
+    if (!sLog)
+        sLog = PR_NewLogModule("ObserverService");
+    return sLog;
+}
+  #define LOG(x)  PR_LOG(GetObserverServiceLog(), PR_LOG_DEBUG, x)
 #else
   #define LOG(x)
 #endif /* PR_LOGGING */
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsObserverService Implementation
 
 
--- a/xpcom/io/nsInputStreamTee.cpp
+++ b/xpcom/io/nsInputStreamTee.cpp
@@ -14,18 +14,25 @@
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsIEventTarget.h"
 #include "nsThreadUtils.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo* gInputStreamTeeLog = PR_NewLogModule("nsInputStreamTee");
-#define LOG(args) PR_LOG(gInputStreamTeeLog, PR_LOG_DEBUG, args)
+static PRLogModuleInfo*
+GetTeeLog()
+{
+    static PRLogModuleInfo *sLog;
+    if (!sLog)
+        sLog = PR_NewLogModule("nsInputStreamTee");
+    return sLog;
+}
+#define LOG(args) PR_LOG(GetTeeLog(), PR_LOG_DEBUG, args)
 #else
 #define LOG(args)
 #endif
 
 class nsInputStreamTee MOZ_FINAL : public nsIInputStreamTee
 {
 public:
     NS_DECL_ISUPPORTS
--- a/xpcom/io/nsPipe3.cpp
+++ b/xpcom/io/nsPipe3.cpp
@@ -18,18 +18,25 @@
 #include "nsAlgorithm.h"
 
 using namespace mozilla;
 
 #if defined(PR_LOGGING)
 //
 // set NSPR_LOG_MODULES=nsPipe:5
 //
-static PRLogModuleInfo *gPipeLog = PR_NewLogModule("nsPipe");
-#define LOG(args) PR_LOG(gPipeLog, PR_LOG_DEBUG, args)
+static PRLogModuleInfo *
+GetPipeLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsPipe");
+  return sLog;
+}
+#define LOG(args) PR_LOG(GetPipeLog(), PR_LOG_DEBUG, args)
 #else
 #define LOG(args)
 #endif
 
 #define DEFAULT_SEGMENT_SIZE  4096
 #define DEFAULT_SEGMENT_COUNT 16
 
 class nsPipe;
--- a/xpcom/io/nsStorageStream.cpp
+++ b/xpcom/io/nsStorageStream.cpp
@@ -31,19 +31,26 @@
 // To enable logging (see prlog.h for full details):
 //
 //    set NSPR_LOG_MODULES=StorageStreamLog:5
 //    set NSPR_LOG_FILE=nspr.log
 //
 // this enables PR_LOG_DEBUG level information and places all output in
 // the file nspr.log
 //
-static PRLogModuleInfo* sLog = PR_NewLogModule("nsStorageStream");
+static PRLogModuleInfo*
+GetStorageStreamLog()
+{
+    static PRLogModuleInfo *sLog;
+    if (!sLog)
+        sLog = PR_NewLogModule("nsStorageStream");
+    return sLog;
+}
 #endif
-#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetStorageStreamLog(), PR_LOG_DEBUG, args)
 
 nsStorageStream::nsStorageStream()
     : mSegmentedBuffer(0), mSegmentSize(0), mWriteInProgress(false),
       mLastSegmentNum(-1), mWriteCursor(0), mSegmentEnd(0), mLogicalLength(0)
 {
     LOG(("Creating nsStorageStream [%p].\n", this));
 }
 
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -70,17 +70,17 @@ TimerObserverRunnable::Run()
   }
   return NS_OK;
 }
 
 } // anonymous namespace
 
 nsresult TimerThread::Init()
 {
-  PR_LOG(gTimerLog, PR_LOG_DEBUG, ("TimerThread::Init [%d]\n", mInitialized));
+  PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("TimerThread::Init [%d]\n", mInitialized));
 
   if (mInitialized) {
     if (!mThread)
       return NS_ERROR_FAILURE;
 
     return NS_OK;
   }
 
@@ -116,17 +116,17 @@ nsresult TimerThread::Init()
   if (!mThread)
     return NS_ERROR_FAILURE;
 
   return NS_OK;
 }
 
 nsresult TimerThread::Shutdown()
 {
-  PR_LOG(gTimerLog, PR_LOG_DEBUG, ("TimerThread::Shutdown begin\n"));
+  PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("TimerThread::Shutdown begin\n"));
 
   if (!mThread)
     return NS_ERROR_NOT_INITIALIZED;
 
   nsTArray<nsTimerImpl*> timers;
   {   // lock scope
     MonitorAutoLock lock(mMonitor);
 
@@ -150,17 +150,17 @@ nsresult TimerThread::Shutdown()
   for (uint32_t i = 0; i < timersCount; i++) {
     nsTimerImpl *timer = timers[i];
     timer->ReleaseCallback();
     ReleaseTimerInternal(timer);
   }
 
   mThread->Shutdown();    // wait for the thread to die
 
-  PR_LOG(gTimerLog, PR_LOG_DEBUG, ("TimerThread::Shutdown end\n"));
+  PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("TimerThread::Shutdown end\n"));
   return NS_OK;
 }
 
 // Keep track of how early (positive slack) or late (negative slack) timers
 // are running, and use the filtered slack number to adaptively estimate how
 // early timers should fire to be "on time".
 void TimerThread::UpdateFilter(uint32_t aDelay, TimeStamp aTimeout,
                                TimeStamp aNow)
@@ -202,17 +202,17 @@ void TimerThread::UpdateFilter(uint32_t 
       smoothSlack += mDelayLine[(mDelayLineCounter-i) & DELAY_LINE_LENGTH_MASK];
     smoothSlack /= filterLength;
 
     // XXXbe do we need amplification?  hacking a fudge factor, need testing...
     mTimeoutAdjustment = TimeDuration::FromMilliseconds(smoothSlack * 1.5);
   }
 
 #ifdef DEBUG_TIMERS
-  PR_LOG(gTimerLog, PR_LOG_DEBUG,
+  PR_LOG(GetTimerLog(), PR_LOG_DEBUG,
          ("UpdateFilter: smoothSlack = %g, filterLength = %u\n",
           smoothSlack, filterLength));
 #endif
 }
 
 /* void Run(); */
 NS_IMETHODIMP TimerThread::Run()
 {
@@ -268,18 +268,18 @@ NS_IMETHODIMP TimerThread::Run()
           NS_ADDREF(timer);
           RemoveTimerInternal(timer);
 
           {
             // We release mMonitor around the Fire call to avoid deadlock.
             MonitorAutoUnlock unlock(mMonitor);
 
 #ifdef DEBUG_TIMERS
-            if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
-              PR_LOG(gTimerLog, PR_LOG_DEBUG,
+            if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {
+              PR_LOG(GetTimerLog(), PR_LOG_DEBUG,
                      ("Timer thread woke up %fms from when it was supposed to\n",
                       fabs((now - timer->mTimeout).ToMilliseconds())));
             }
 #endif
 
             // We are going to let the call to PostTimerEvent here handle the
             // release of the timer so that we don't end up releasing the timer
             // on the TimerThread instead of on the thread it targets.
@@ -328,22 +328,22 @@ NS_IMETHODIMP TimerThread::Run()
         if (microseconds < halfMicrosecondsIntervalResolution)
           goto next; // round down; execute event now
         waitFor = PR_MicrosecondsToInterval(microseconds);
         if (waitFor == 0)
           waitFor = 1; // round up, wait the minimum time we can wait
       }
 
 #ifdef DEBUG_TIMERS
-      if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+      if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {
         if (waitFor == PR_INTERVAL_NO_TIMEOUT)
-          PR_LOG(gTimerLog, PR_LOG_DEBUG,
+          PR_LOG(GetTimerLog(), PR_LOG_DEBUG,
                  ("waiting for PR_INTERVAL_NO_TIMEOUT\n"));
         else
-          PR_LOG(gTimerLog, PR_LOG_DEBUG,
+          PR_LOG(GetTimerLog(), PR_LOG_DEBUG,
                  ("waiting for %u\n", PR_IntervalToMilliseconds(waitFor)));
       }
 #endif
     }
 
     mWaiting = true;
     mMonitor.Wait(waitFor);
     mWaiting = false;
--- a/xpcom/threads/nsEventQueue.cpp
+++ b/xpcom/threads/nsEventQueue.cpp
@@ -7,19 +7,26 @@
 #include "nsEventQueue.h"
 #include "nsAutoPtr.h"
 #include "prlog.h"
 #include "nsThreadUtils.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *sLog = PR_NewLogModule("nsEventQueue");
+static PRLogModuleInfo *
+GetLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsEventQueue");
+  return sLog;
+}
 #endif
-#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetLog(), PR_LOG_DEBUG, args)
 
 nsEventQueue::nsEventQueue()
   : mReentrantMonitor("nsEventQueue.mReentrantMonitor")
   , mHead(nullptr)
   , mTail(nullptr)
   , mOffsetHead(0)
   , mOffsetTail(0)
 {
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -36,19 +36,26 @@
 #endif
 #ifdef NS_FUNCTION_TIMER
 #include "nsCRT.h"
 #endif
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *sLog = PR_NewLogModule("nsThread");
+static PRLogModuleInfo *
+GetThreadLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsThread");
+  return sLog;
+}
 #endif
-#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetThreadLog(), PR_LOG_DEBUG, args)
 
 NS_DECL_CI_INTERFACE_GETTER(nsThread)
 
 nsIThreadObserver* nsThread::sMainThreadObserver = nullptr;
 
 namespace mozilla {
 
 // Fun fact: Android's GCC won't convert bool* to int32_t*, so we can't
--- a/xpcom/threads/nsThreadPool.cpp
+++ b/xpcom/threads/nsThreadPool.cpp
@@ -11,19 +11,26 @@
 #include "nsMemory.h"
 #include "nsAutoPtr.h"
 #include "prinrval.h"
 #include "prlog.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *sLog = PR_NewLogModule("nsThreadPool");
+static PRLogModuleInfo *
+GetThreadPoolLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsThreadPool");
+  return sLog;
+}
 #endif
-#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
+#define LOG(args) PR_LOG(GetThreadPoolLog(), PR_LOG_DEBUG, args)
 
 // DESIGN:
 //  o  Allocate anonymous threads.
 //  o  Use nsThreadPool::Run as the main routine for each thread.
 //  o  Each thread waits on the event queue's monitor, checking for
 //     pending events and rescheduling itself as an idle thread.
 
 #define DEFAULT_THREAD_LIMIT 4
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -14,16 +14,26 @@
 
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 
 static int32_t          gGenerator = 0;
 static TimerThread*     gThread = nullptr;
 
 #ifdef DEBUG_TIMERS
+
+PRLogModuleInfo*
+GetTimerLog()
+{
+  static PRLogModuleInfo *sLog;
+  if (!sLog)
+    sLog = PR_NewLogModule("nsTimerImpl");
+  return sLog;
+}
+
 #include <math.h>
 
 double nsTimerImpl::sDeltaSumSquared = 0;
 double nsTimerImpl::sDeltaSum = 0;
 double nsTimerImpl::sDeltaNum = 0;
 
 static void
 myNS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
@@ -217,22 +227,22 @@ nsTimerImpl::Startup()
   }
 
   return rv;
 }
 
 void nsTimerImpl::Shutdown()
 {
 #ifdef DEBUG_TIMERS
-  if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+  if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {
     double mean = 0, stddev = 0;
     myNS_MeanAndStdDev(sDeltaNum, sDeltaSum, sDeltaSumSquared, &mean, &stddev);
 
-    PR_LOG(gTimerLog, PR_LOG_DEBUG, ("sDeltaNum = %f, sDeltaSum = %f, sDeltaSumSquared = %f\n", sDeltaNum, sDeltaSum, sDeltaSumSquared));
-    PR_LOG(gTimerLog, PR_LOG_DEBUG, ("mean: %fms, stddev: %fms\n", mean, stddev));
+    PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("sDeltaNum = %f, sDeltaSum = %f, sDeltaSumSquared = %f\n", sDeltaNum, sDeltaSum, sDeltaSumSquared));
+    PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("mean: %fms, stddev: %fms\n", mean, stddev));
   }
 #endif
 
   if (!gThread)
     return;
 
   gThread->Shutdown();
   NS_RELEASE(gThread);
@@ -420,29 +430,29 @@ void nsTimerImpl::Fire()
 {
   if (mCanceled)
     return;
 
   SAMPLE_LABEL("Timer", "Fire");
 
   TimeStamp now = TimeStamp::Now();
 #ifdef DEBUG_TIMERS
-  if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+  if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {
     TimeDuration   a = now - mStart; // actual delay in intervals
     TimeDuration   b = TimeDuration::FromMilliseconds(mDelay); // expected delay in intervals
     TimeDuration   delta = (a > b) ? a - b : b - a;
     uint32_t       d = delta.ToMilliseconds(); // delta in ms
     sDeltaSum += d;
     sDeltaSumSquared += double(d) * double(d);
     sDeltaNum++;
 
-    PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] expected delay time %4ums\n", this, mDelay));
-    PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] actual delay time   %fms\n", this, a.ToMilliseconds()));
-    PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] (mType is %d)       -------\n", this, mType));
-    PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p]     delta           %4dms\n", this, (a > b) ? (int32_t)d : -(int32_t)d));
+    PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("[this=%p] expected delay time %4ums\n", this, mDelay));
+    PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("[this=%p] actual delay time   %fms\n", this, a.ToMilliseconds()));
+    PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("[this=%p] (mType is %d)       -------\n", this, mType));
+    PR_LOG(GetTimerLog(), PR_LOG_DEBUG, ("[this=%p]     delta           %4dms\n", this, (a > b) ? (int32_t)d : -(int32_t)d));
 
     mStart = mStart2;
     mStart2 = TimeStamp();
   }
 #endif
 
   TimeStamp timeout = mTimeout;
   if (IsRepeatingPrecisely()) {
@@ -495,18 +505,18 @@ void nsTimerImpl::Fire()
     else if (callbackType == CALLBACK_TYPE_OBSERVER)
       NS_RELEASE(callback.o);
   }
 
   mFiring = false;
   mTimerCallbackWhileFiring = nullptr;
 
 #ifdef DEBUG_TIMERS
-  if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
-    PR_LOG(gTimerLog, PR_LOG_DEBUG,
+  if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {
+    PR_LOG(GetTimerLog(), PR_LOG_DEBUG,
            ("[this=%p] Took %fms to fire timer callback\n",
             this, (TimeStamp::Now() - now).ToMilliseconds()));
   }
 #endif
 
   // Reschedule repeating timers, except REPEATING_PRECISE which already did
   // that in PostTimerEvent, but make sure that we aren't armed already (which
   // can happen if the callback reinitialized the timer).
@@ -539,19 +549,19 @@ NS_IMETHODIMP nsTimerEvent::Run()
 {
   nsRefPtr<nsTimerImpl> timer;
   timer.swap(mTimer);
 
   if (mGeneration != timer->GetGeneration())
     return NS_OK;
 
 #ifdef DEBUG_TIMERS
-  if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+  if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {
     TimeStamp now = TimeStamp::Now();
-    PR_LOG(gTimerLog, PR_LOG_DEBUG,
+    PR_LOG(GetTimerLog(), PR_LOG_DEBUG,
            ("[this=%p] time between PostTimerEvent() and Fire(): %fms\n",
             this, (now - mInitTime).ToMilliseconds()));
   }
 #endif
 
   timer->Fire();
 
   return NS_OK;
@@ -566,17 +576,17 @@ nsresult nsTimerImpl::PostTimerEvent()
   // from this timer into the event, so we can avoid firing a timer that was
   // re-initialized after being canceled.
 
   nsRefPtr<nsTimerEvent> event = new nsTimerEvent(this, mGeneration);
   if (!event)
     return NS_ERROR_OUT_OF_MEMORY;
 
 #ifdef DEBUG_TIMERS
-  if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+  if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {
     event->mInitTime = TimeStamp::Now();
   }
 #endif
 
   // If this is a repeating precise timer, we need to calculate the time for
   // the next timer to fire before we make the callback.
   if (IsRepeatingPrecisely()) {
     SetDelayInternal(mDelay);
@@ -603,17 +613,17 @@ void nsTimerImpl::SetDelayInternal(uint3
 
   TimeStamp now = TimeStamp::Now();
   if (mTimeout.IsNull() || mType != TYPE_REPEATING_PRECISE)
     mTimeout = now;
 
   mTimeout += delayInterval;
 
 #ifdef DEBUG_TIMERS
-  if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
+  if (PR_LOG_TEST(GetTimerLog(), PR_LOG_DEBUG)) {
     if (mStart.IsNull())
       mStart = now;
     else
       mStart2 = now;
   }
 #endif
 }
 
--- a/xpcom/threads/nsTimerImpl.h
+++ b/xpcom/threads/nsTimerImpl.h
@@ -14,17 +14,17 @@
 
 #include "nsCOMPtr.h"
 
 #include "prlog.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Attributes.h"
 
 #if defined(PR_LOGGING)
-static PRLogModuleInfo *gTimerLog = PR_NewLogModule("nsTimerImpl");
+extern PRLogModuleInfo *GetTimerLog();
 #define DEBUG_TIMERS 1
 #else
 #undef DEBUG_TIMERS
 #endif
 
 #define NS_TIMER_CLASSNAME "Timer"
 #define NS_TIMER_CID \
 { /* 5ff24248-1dd2-11b2-8427-fbab44f29bc8 */         \