Bug 1407683 - use singleton factory method for nsHttpHandler. r?mayhemer draft
authorShih-Chiang Chien <schien@mozilla.com>
Thu, 12 Oct 2017 12:13:56 +0800
changeset 679174 e4c6ce7b3fe9f328d2d2c2b06d5b3a9129314f82
parent 679173 bc7a5be76b723cf6aac1a919156e74997c5f4902
child 735530 6b107e70533075a68fa43649089d0757a010dda3
push id84141
push userbmo:schien@mozilla.com
push dateThu, 12 Oct 2017 11:13:04 +0000
reviewersmayhemer
bugs1407683
milestone58.0a1
Bug 1407683 - use singleton factory method for nsHttpHandler. r?mayhemer nsHttpHandler is designed only for `getService` but we do not protect against `createInstance`. The singleton of nsHttpHandler will be replaced by new instance created via `createInstance`. gHttpHandler will hold a dangling pointer after the new instance is destroyed. MozReview-Commit-ID: DQV6pmb5BUK
netwerk/build/nsNetModule.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -261,17 +261,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsFt
 #include "nsHttpActivityDistributor.h"
 #include "ThrottleQueue.h"
 #include "BackgroundChannelRegistrar.h"
 #undef LOG
 #undef LOG_ENABLED
 namespace mozilla {
 namespace net {
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpNTLMAuth)
-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHttpHandler, Init)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsHttpHandler, nsHttpHandler::GetInstance)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHttpsHandler, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsHttpAuthManager, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpChannelAuthProvider)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpActivityDistributor)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpBasicAuth)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpDigestAuth)
 NS_GENERIC_FACTORY_CONSTRUCTOR(ThrottleQueue)
 NS_GENERIC_FACTORY_CONSTRUCTOR(BackgroundChannelRegistrar)
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -25,16 +25,17 @@
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefLocalizedString.h"
 #include "nsISocketProviderService.h"
 #include "nsISocketProvider.h"
 #include "nsPrintfCString.h"
 #include "nsCOMPtr.h"
 #include "nsNetCID.h"
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Printf.h"
 #include "mozilla/Sprintf.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 #include "nsSocketTransportService2.h"
 #include "nsAlgorithm.h"
 #include "ASpdySession.h"
 #include "EventTokenBucket.h"
 #include "Tickler.h"
@@ -163,17 +164,30 @@ GetDeviceModelId() {
     return deviceModelId;
 }
 #endif
 
 //-----------------------------------------------------------------------------
 // nsHttpHandler <public>
 //-----------------------------------------------------------------------------
 
-nsHttpHandler *gHttpHandler = nullptr;
+StaticRefPtr<nsHttpHandler> gHttpHandler;
+
+/* static */ already_AddRefed<nsHttpHandler>
+nsHttpHandler::GetInstance()
+{
+    if (!gHttpHandler) {
+        gHttpHandler = new nsHttpHandler();
+        DebugOnly<nsresult> rv = gHttpHandler->Init();
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+        ClearOnShutdown(&gHttpHandler);
+    }
+    RefPtr<nsHttpHandler> httpHandler = gHttpHandler;
+    return httpHandler.forget();
+}
 
 nsHttpHandler::nsHttpHandler()
     : mHttpVersion(NS_HTTP_VERSION_1_1)
     , mProxyHttpVersion(NS_HTTP_VERSION_1_1)
     , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
     , mReferrerLevel(0xff) // by default we always send a referrer
     , mSpoofReferrerSource(false)
     , mHideOnionReferrerSource(false)
@@ -266,17 +280,17 @@ nsHttpHandler::nsHttpHandler()
     , mProcessId(0)
     , mNextChannelId(1)
 {
     LOG(("Creating nsHttpHandler [this=%p].\n", this));
 
     mUserAgentOverride.SetIsVoid(true);
 
     MOZ_ASSERT(!gHttpHandler, "HTTP handler already created!");
-    gHttpHandler = this;
+
     nsCOMPtr<nsIXULRuntime> runtime = do_GetService("@mozilla.org/xre/runtime;1");
     if (runtime) {
         runtime->GetProcessID(&mProcessId);
     }
     SetFastOpenOSSupport();
 }
 
 void
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -6,16 +6,17 @@
 #ifndef nsHttpHandler_h__
 #define nsHttpHandler_h__
 
 #include "nsHttp.h"
 #include "nsHttpAuthCache.h"
 #include "nsHttpConnectionMgr.h"
 #include "ASpdySession.h"
 
+#include "mozilla/StaticPtr.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsWeakReference.h"
 
 #include "nsIHttpProtocolHandler.h"
 #include "nsIObserver.h"
 #include "nsISpeculativeConnect.h"
 
@@ -60,19 +61,18 @@ class nsHttpHandler final : public nsIHt
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIPROTOCOLHANDLER
     NS_DECL_NSIPROXIEDPROTOCOLHANDLER
     NS_DECL_NSIHTTPPROTOCOLHANDLER
     NS_DECL_NSIOBSERVER
     NS_DECL_NSISPECULATIVECONNECT
 
-    nsHttpHandler();
+    static already_AddRefed<nsHttpHandler> GetInstance();
 
-    MOZ_MUST_USE nsresult Init();
     MOZ_MUST_USE nsresult AddStandardRequestHeaders(nsHttpRequestHead *,
                                                     bool isSecure);
     MOZ_MUST_USE nsresult AddConnectionHeader(nsHttpRequestHead *,
                                               uint32_t capabilities);
     bool     IsAcceptableEncoding(const char *encoding, bool isSecure);
 
     const nsCString& UserAgent();
 
@@ -398,18 +398,22 @@ public:
     }
 
     bool ActiveTabPriority() const
     {
         return mActiveTabPriority;
     }
 
 private:
+    nsHttpHandler();
+
     virtual ~nsHttpHandler();
 
+    MOZ_MUST_USE nsresult Init();
+
     //
     // Useragent/prefs helper methods
     //
     void     BuildUserAgent();
     void     InitUserAgentComponents();
     void     PrefsChanged(nsIPrefBranch *prefs, const char *pref);
 
     MOZ_MUST_USE nsresult SetAccept(const char *);
@@ -679,17 +683,17 @@ private:
     // State for generating channelIds
     uint32_t mProcessId;
     uint32_t mNextChannelId;
 
 public:
     MOZ_MUST_USE nsresult NewChannelId(uint64_t& channelId);
 };
 
-extern nsHttpHandler *gHttpHandler;
+extern StaticRefPtr<nsHttpHandler> gHttpHandler;
 
 //-----------------------------------------------------------------------------
 // nsHttpsHandler - thin wrapper to distinguish the HTTP handler from the
 //                  HTTPS handler (even though they share the same impl).
 //-----------------------------------------------------------------------------
 
 class nsHttpsHandler : public nsIHttpProtocolHandler
                      , public nsSupportsWeakReference