LCOV - code coverage report
Current view: top level - netwerk/protocol/http - nsHttpHandler.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 820 1172 70.0 %
Date: 2017-07-14 16:53:18 Functions: 43 69 62.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim:set ts=4 sw=4 sts=4 et cin: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : // HttpLog.h should generally be included first
       8             : #include "HttpLog.h"
       9             : 
      10             : #include "prsystem.h"
      11             : 
      12             : #include "nsHttp.h"
      13             : #include "nsHttpHandler.h"
      14             : #include "nsHttpChannel.h"
      15             : #include "nsHttpAuthCache.h"
      16             : #include "nsStandardURL.h"
      17             : #include "nsIDOMWindow.h"
      18             : #include "nsIDOMNavigator.h"
      19             : #include "nsIMozNavigatorNetwork.h"
      20             : #include "nsINetworkProperties.h"
      21             : #include "nsIHttpChannel.h"
      22             : #include "nsIStandardURL.h"
      23             : #include "LoadContextInfo.h"
      24             : #include "nsCategoryManagerUtils.h"
      25             : #include "nsIPrefService.h"
      26             : #include "nsIPrefBranch.h"
      27             : #include "nsIPrefLocalizedString.h"
      28             : #include "nsISocketProviderService.h"
      29             : #include "nsISocketProvider.h"
      30             : #include "nsPrintfCString.h"
      31             : #include "nsCOMPtr.h"
      32             : #include "nsNetCID.h"
      33             : #include "mozilla/Printf.h"
      34             : #include "mozilla/Sprintf.h"
      35             : #include "nsAsyncRedirectVerifyHelper.h"
      36             : #include "nsSocketTransportService2.h"
      37             : #include "nsAlgorithm.h"
      38             : #include "ASpdySession.h"
      39             : #include "EventTokenBucket.h"
      40             : #include "Tickler.h"
      41             : #include "nsIXULAppInfo.h"
      42             : #include "nsICookieService.h"
      43             : #include "nsIObserverService.h"
      44             : #include "nsISiteSecurityService.h"
      45             : #include "nsIStreamConverterService.h"
      46             : #include "nsCRT.h"
      47             : #include "nsIMemoryReporter.h"
      48             : #include "nsIParentalControlsService.h"
      49             : #include "nsPIDOMWindow.h"
      50             : #include "nsINetworkLinkService.h"
      51             : #include "nsHttpChannelAuthProvider.h"
      52             : #include "nsServiceManagerUtils.h"
      53             : #include "nsComponentManagerUtils.h"
      54             : #include "nsSocketTransportService2.h"
      55             : #include "nsIOService.h"
      56             : #include "nsISupportsPrimitives.h"
      57             : #include "nsIXULRuntime.h"
      58             : #include "nsCharSeparatedTokenizer.h"
      59             : #include "nsRFPService.h"
      60             : 
      61             : #include "mozilla/net/NeckoChild.h"
      62             : #include "mozilla/net/NeckoParent.h"
      63             : #include "mozilla/ipc/URIUtils.h"
      64             : #include "mozilla/Telemetry.h"
      65             : #include "mozilla/Unused.h"
      66             : #include "mozilla/BasePrincipal.h"
      67             : 
      68             : #include "mozilla/dom/ContentParent.h"
      69             : 
      70             : #if defined(XP_UNIX)
      71             : #include <sys/utsname.h>
      72             : #endif
      73             : 
      74             : #if defined(XP_WIN)
      75             : #include <windows.h>
      76             : #endif
      77             : 
      78             : #if defined(XP_MACOSX)
      79             : #include <CoreServices/CoreServices.h>
      80             : #include "nsCocoaFeatures.h"
      81             : #endif
      82             : 
      83             : #ifdef MOZ_TASK_TRACER
      84             : #include "GeckoTaskTracer.h"
      85             : #endif
      86             : 
      87             : //-----------------------------------------------------------------------------
      88             : #include "mozilla/net/HttpChannelChild.h"
      89             : 
      90             : 
      91             : #define UA_PREF_PREFIX          "general.useragent."
      92             : #ifdef XP_WIN
      93             : #define UA_SPARE_PLATFORM
      94             : #endif
      95             : 
      96             : #define HTTP_PREF_PREFIX        "network.http."
      97             : #define INTL_ACCEPT_LANGUAGES   "intl.accept_languages"
      98             : #define BROWSER_PREF_PREFIX     "browser.cache."
      99             : #define DONOTTRACK_HEADER_ENABLED "privacy.donottrackheader.enabled"
     100             : #define H2MANDATORY_SUITE        "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256"
     101             : #define TELEMETRY_ENABLED        "toolkit.telemetry.enabled"
     102             : #define ALLOW_EXPERIMENTS        "network.allow-experiments"
     103             : #define SAFE_HINT_HEADER_VALUE   "safeHint.enabled"
     104             : #define SECURITY_PREFIX          "security."
     105             : 
     106             : #define TCP_FAST_OPEN_ENABLE        "network.tcp.tcp_fastopen_enable"
     107             : #define TCP_FAST_OPEN_FAILURE_LIMIT "network.tcp.tcp_fastopen_consecutive_failure_limit"
     108             : 
     109             : #define UA_PREF(_pref) UA_PREF_PREFIX _pref
     110             : #define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
     111             : #define BROWSER_PREF(_pref) BROWSER_PREF_PREFIX _pref
     112             : 
     113             : #define NS_HTTP_PROTOCOL_FLAGS (URI_STD | ALLOWS_PROXY | ALLOWS_PROXY_HTTP | URI_LOADABLE_BY_ANYONE)
     114             : 
     115             : //-----------------------------------------------------------------------------
     116             : 
     117             : namespace mozilla {
     118             : namespace net {
     119             : 
     120             : LazyLogModule gHttpLog("nsHttp");
     121             : 
     122             : static nsresult
     123         130 : NewURI(const nsACString &aSpec,
     124             :        const char *aCharset,
     125             :        nsIURI *aBaseURI,
     126             :        int32_t aDefaultPort,
     127             :        nsIURI **aURI)
     128             : {
     129         260 :     RefPtr<nsStandardURL> url = new nsStandardURL();
     130             : 
     131         130 :     nsresult rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY,
     132         130 :                             aDefaultPort, aSpec, aCharset, aBaseURI);
     133         130 :     if (NS_FAILED(rv)) {
     134           0 :         return rv;
     135             :     }
     136             : 
     137         130 :     url.forget(aURI);
     138         130 :     return NS_OK;
     139             : }
     140             : 
     141             : #ifdef ANDROID
     142             : static nsCString
     143             : GetDeviceModelId() {
     144             :     // Assumed to be running on the main thread
     145             :     // We need the device property in either case
     146             :     nsAutoCString deviceModelId;
     147             :     nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
     148             :     MOZ_ASSERT(infoService, "Could not find a system info service");
     149             :     nsAutoString androidDevice;
     150             :     nsresult rv = infoService->GetPropertyAsAString(NS_LITERAL_STRING("device"), androidDevice);
     151             :     if (NS_SUCCEEDED(rv)) {
     152             :         deviceModelId = NS_LossyConvertUTF16toASCII(androidDevice);
     153             :     }
     154             :     nsAutoCString deviceString;
     155             :     rv = Preferences::GetCString(UA_PREF("device_string"), &deviceString);
     156             :     if (NS_SUCCEEDED(rv)) {
     157             :         deviceString.Trim(" ", true, true);
     158             :         deviceString.ReplaceSubstring(NS_LITERAL_CSTRING("%DEVICEID%"), deviceModelId);
     159             :         return deviceString;
     160             :     }
     161             :     return deviceModelId;
     162             : }
     163             : #endif
     164             : 
     165             : //-----------------------------------------------------------------------------
     166             : // nsHttpHandler <public>
     167             : //-----------------------------------------------------------------------------
     168             : 
     169             : nsHttpHandler *gHttpHandler = nullptr;
     170             : 
     171           2 : nsHttpHandler::nsHttpHandler()
     172             :     : mHttpVersion(NS_HTTP_VERSION_1_1)
     173             :     , mProxyHttpVersion(NS_HTTP_VERSION_1_1)
     174             :     , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
     175             :     , mReferrerLevel(0xff) // by default we always send a referrer
     176             :     , mSpoofReferrerSource(false)
     177             :     , mHideOnionReferrerSource(false)
     178             :     , mReferrerTrimmingPolicy(0)
     179             :     , mReferrerXOriginTrimmingPolicy(0)
     180             :     , mReferrerXOriginPolicy(0)
     181             :     , mFastFallbackToIPv4(false)
     182           2 :     , mIdleTimeout(PR_SecondsToInterval(10))
     183           2 :     , mSpdyTimeout(PR_SecondsToInterval(180))
     184           2 :     , mResponseTimeout(PR_SecondsToInterval(300))
     185             :     , mResponseTimeoutEnabled(false)
     186             :     , mNetworkChangedTimeout(5000)
     187             :     , mMaxRequestAttempts(6)
     188             :     , mMaxRequestDelay(10)
     189             :     , mIdleSynTimeout(250)
     190             :     , mH2MandatorySuiteEnabled(false)
     191             :     , mMaxUrgentExcessiveConns(3)
     192             :     , mMaxConnections(24)
     193             :     , mMaxPersistentConnectionsPerServer(2)
     194             :     , mMaxPersistentConnectionsPerProxy(4)
     195             :     , mThrottleEnabled(true)
     196             :     , mThrottleSuspendFor(3000)
     197             :     , mThrottleResumeFor(200)
     198             :     , mThrottleResumeIn(400)
     199             :     , mUrgentStartEnabled(true)
     200             :     , mRedirectionLimit(10)
     201             :     , mPhishyUserPassLength(1)
     202             :     , mQoSBits(0x00)
     203             :     , mEnforceAssocReq(false)
     204           2 :     , mLastUniqueID(NowInSeconds())
     205             :     , mSessionStartTime(0)
     206             :     , mLegacyAppName("Mozilla")
     207             :     , mLegacyAppVersion("5.0")
     208             :     , mProduct("Gecko")
     209             :     , mCompatFirefoxEnabled(false)
     210             :     , mUserAgentIsDirty(true)
     211             :     , mAcceptLanguagesIsDirty(true)
     212             :     , mPromptTempRedirect(true)
     213             :     , mEnablePersistentHttpsCaching(false)
     214             :     , mDoNotTrackEnabled(false)
     215             :     , mSafeHintEnabled(false)
     216             :     , mParentalControlEnabled(false)
     217             :     , mHandlerActive(false)
     218             :     , mTelemetryEnabled(false)
     219             :     , mAllowExperiments(true)
     220             :     , mDebugObservations(false)
     221             :     , mEnableSpdy(false)
     222             :     , mHttp2Enabled(true)
     223             :     , mUseH2Deps(true)
     224             :     , mEnforceHttp2TlsProfile(true)
     225             :     , mCoalesceSpdy(true)
     226             :     , mSpdyPersistentSettings(false)
     227             :     , mAllowPush(true)
     228             :     , mEnableAltSvc(false)
     229             :     , mEnableAltSvcOE(false)
     230             :     , mEnableOriginExtension(false)
     231             :     , mSpdySendingChunkSize(ASpdySession::kSendingChunkSize)
     232             :     , mSpdySendBufferSize(ASpdySession::kTCPSendBufferSize)
     233             :     , mSpdyPushAllowance(32768)
     234             :     , mSpdyPullAllowance(ASpdySession::kInitialRwin)
     235             :     , mDefaultSpdyConcurrent(ASpdySession::kDefaultMaxConcurrent)
     236           2 :     , mSpdyPingThreshold(PR_SecondsToInterval(58))
     237           2 :     , mSpdyPingTimeout(PR_SecondsToInterval(8))
     238             :     , mConnectTimeout(90000)
     239             :     , mParallelSpeculativeConnectLimit(6)
     240             :     , mRequestTokenBucketEnabled(true)
     241             :     , mRequestTokenBucketMinParallelism(6)
     242             :     , mRequestTokenBucketHz(100)
     243             :     , mRequestTokenBucketBurst(32)
     244             :     , mCriticalRequestPrioritization(true)
     245             :     , mTCPKeepaliveShortLivedEnabled(false)
     246             :     , mTCPKeepaliveShortLivedTimeS(60)
     247             :     , mTCPKeepaliveShortLivedIdleTimeS(10)
     248             :     , mTCPKeepaliveLongLivedEnabled(false)
     249             :     , mTCPKeepaliveLongLivedIdleTimeS(600)
     250             :     , mEnforceH1Framing(FRAMECHECK_BARELY)
     251             :     , mKeepEmptyResponseHeadersAsEmtpyString(false)
     252             :     , mDefaultHpackBuffer(4096)
     253             :     , mMaxHttpResponseHeaderSize(393216)
     254             :     , mFocusedWindowTransactionRatio(0.9f)
     255             :     , mUseFastOpen(true)
     256             :     , mFastOpenConsecutiveFailureLimit(5)
     257             :     , mFastOpenConsecutiveFailureCounter(0)
     258             :     , mProcessId(0)
     259          14 :     , mNextChannelId(1)
     260             : {
     261           2 :     LOG(("Creating nsHttpHandler [this=%p].\n", this));
     262             : 
     263           2 :     MOZ_ASSERT(!gHttpHandler, "HTTP handler already created!");
     264           2 :     gHttpHandler = this;
     265           4 :     nsCOMPtr<nsIXULRuntime> runtime = do_GetService("@mozilla.org/xre/runtime;1");
     266           2 :     if (runtime) {
     267           2 :         runtime->GetProcessID(&mProcessId);
     268             :     }
     269           2 :     SetFastOpenOSSupport();
     270           2 : }
     271             : 
     272             : void
     273           2 : nsHttpHandler::SetFastOpenOSSupport()
     274             : {
     275           2 :     mFastOpenSupported = false;
     276             : #if !defined(XP_WIN) && !defined(XP_LINUX) && !defined(ANDROID) && !defined(HAS_CONNECTX)
     277             :     return;
     278             : #else
     279             : 
     280           4 :     nsAutoCString version;
     281             :     nsresult rv;
     282             : #ifdef ANDROID
     283             :     nsCOMPtr<nsIPropertyBag2> infoService =
     284             :         do_GetService("@mozilla.org/system-info;1");
     285             :     MOZ_ASSERT(infoService, "Could not find a system info service");
     286             :     rv = infoService->GetPropertyAsACString(
     287             :         NS_LITERAL_STRING("sdk_version"), version);
     288             : #else
     289             :     char buf[SYS_INFO_BUFFER_LENGTH];
     290           2 :     if (PR_GetSystemInfo(PR_SI_RELEASE, buf, sizeof(buf)) == PR_SUCCESS) {
     291           2 :         version = buf;
     292           2 :         rv = NS_OK;
     293             :     } else {
     294           0 :         rv = NS_ERROR_FAILURE;
     295             :     }
     296             : #endif
     297             : 
     298           2 :     LOG(("nsHttpHandler::SetFastOpenOSSupport version %s", version.get()));
     299             : 
     300           2 :     if (NS_SUCCEEDED(rv)) {
     301             :         // set min version minus 1.
     302             : #ifdef XP_WIN
     303             :         int min_version[] = {10, 0};
     304             : #elif XP_MACOSX
     305             :         int min_version[] = {15, 0};
     306             : #elif ANDROID
     307             :         int min_version[] = {4, 4};
     308             : #elif XP_LINUX
     309           2 :         int min_version[] = {3, 6};
     310             : #endif
     311           2 :         int inx = 0;
     312           2 :         nsCCharSeparatedTokenizer tokenizer(version, '.');
     313           2 :         while ((inx < 2) && tokenizer.hasMoreTokens()) {
     314           2 :             nsAutoCString token(tokenizer.nextToken());
     315           2 :             const char* nondigit = NS_strspnp("0123456789", token.get());
     316           2 :             if (nondigit && *nondigit) {
     317           0 :                 break;
     318             :             }
     319             :             nsresult rv;
     320           2 :             int32_t ver = token.ToInteger(&rv);
     321           2 :             if (NS_FAILED(rv)) {
     322           0 :                 break;
     323             :             }
     324           2 :             if (ver > min_version[inx]) {
     325           2 :                 mFastOpenSupported = true;
     326           2 :                 break;
     327           0 :             } else if (ver == min_version[inx] && inx == 1) {
     328           0 :                 mFastOpenSupported = true;
     329           0 :             } else if (ver < min_version[inx]) {
     330           0 :                 break;
     331             :             }
     332           0 :             inx++;
     333             :         }
     334             :     }
     335             : #endif
     336             : 
     337             : #ifdef XP_WIN
     338             :   if (mFastOpenSupported) {
     339             :     // We have some problems with lavasoft software and tcp fast open.
     340             :     if (GetModuleHandleW(L"pmls64.dll") || GetModuleHandleW(L"rlls64.dll")) {
     341             :       mFastOpenSupported = false;
     342             :     }
     343             :   }
     344             : #endif
     345             : 
     346           2 :     LOG(("nsHttpHandler::SetFastOpenOSSupport %s supported.\n",
     347             :          mFastOpenSupported ? "" : "not"));
     348           2 : }
     349             : 
     350             : void
     351           7 : nsHttpHandler::EnsureUAOverridesInit()
     352             : {
     353           7 :     MOZ_ASSERT(XRE_IsParentProcess());
     354           7 :     MOZ_ASSERT(NS_IsMainThread());
     355             : 
     356             :     nsresult rv;
     357             :     nsCOMPtr<nsISupports> bootstrapper
     358          14 :         = do_GetService("@mozilla.org/network/ua-overrides-bootstrapper;1", &rv);
     359           7 :     MOZ_ASSERT(bootstrapper);
     360           7 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
     361           7 : }
     362             : 
     363           0 : nsHttpHandler::~nsHttpHandler()
     364             : {
     365           0 :     LOG(("Deleting nsHttpHandler [this=%p]\n", this));
     366             : 
     367             :     // make sure the connection manager is shutdown
     368           0 :     if (mConnMgr) {
     369           0 :         nsresult rv = mConnMgr->Shutdown();
     370           0 :         if (NS_FAILED(rv)) {
     371           0 :             LOG(("nsHttpHandler [this=%p] "
     372             :                  "failed to shutdown connection manager (%08x)\n",
     373             :                  this, static_cast<uint32_t>(rv)));
     374             :         }
     375           0 :         mConnMgr = nullptr;
     376             :     }
     377             : 
     378             :     // Note: don't call NeckoChild::DestroyNeckoChild() here, as it's too late
     379             :     // and it'll segfault.  NeckoChild will get cleaned up by process exit.
     380             : 
     381           0 :     nsHttp::DestroyAtomTable();
     382           0 :     gHttpHandler = nullptr;
     383           0 : }
     384             : 
     385             : nsresult
     386           2 : nsHttpHandler::Init()
     387             : {
     388             :     nsresult rv;
     389             : 
     390           2 :     LOG(("nsHttpHandler::Init\n"));
     391           2 :     MOZ_ASSERT(NS_IsMainThread());
     392             : 
     393           2 :     rv = nsHttp::CreateAtomTable();
     394           2 :     if (NS_FAILED(rv))
     395           0 :         return rv;
     396             : 
     397           4 :     nsCOMPtr<nsIIOService> service = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
     398           2 :     if (NS_FAILED(rv)) {
     399           0 :         NS_WARNING("unable to continue without io service");
     400           0 :         return rv;
     401             :     }
     402             :     mIOService = new nsMainThreadPtrHolder<nsIIOService>(
     403           4 :       "nsHttpHandler::mIOService", service);
     404             : 
     405           2 :     if (IsNeckoChild())
     406           1 :         NeckoChild::InitNeckoChild();
     407             : 
     408           2 :     InitUserAgentComponents();
     409             : 
     410             :     // monitor some preference changes
     411           4 :     nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
     412           2 :     if (prefBranch) {
     413           2 :         prefBranch->AddObserver(HTTP_PREF_PREFIX, this, true);
     414           2 :         prefBranch->AddObserver(UA_PREF_PREFIX, this, true);
     415           2 :         prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, true);
     416           2 :         prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true);
     417           2 :         prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true);
     418           2 :         prefBranch->AddObserver(TELEMETRY_ENABLED, this, true);
     419           2 :         prefBranch->AddObserver(H2MANDATORY_SUITE, this, true);
     420           2 :         prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.short_lived_connections"), this, true);
     421           2 :         prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.long_lived_connections"), this, true);
     422           2 :         prefBranch->AddObserver(SAFE_HINT_HEADER_VALUE, this, true);
     423           2 :         prefBranch->AddObserver(SECURITY_PREFIX, this, true);
     424           2 :         prefBranch->AddObserver(TCP_FAST_OPEN_ENABLE, this, true);
     425           2 :         prefBranch->AddObserver(TCP_FAST_OPEN_FAILURE_LIMIT, this, true);
     426           2 :         PrefsChanged(prefBranch, nullptr);
     427             :     }
     428             : 
     429           2 :     nsHttpChannelAuthProvider::InitializePrefs();
     430             : 
     431           2 :     mMisc.AssignLiteral("rv:" MOZILLA_UAVERSION);
     432             : 
     433           2 :     mCompatFirefox.AssignLiteral("Firefox/" MOZILLA_UAVERSION);
     434             : 
     435             :     nsCOMPtr<nsIXULAppInfo> appInfo =
     436           4 :         do_GetService("@mozilla.org/xre/app-info;1");
     437             : 
     438           2 :     mAppName.AssignLiteral(MOZ_APP_UA_NAME);
     439           2 :     if (mAppName.Length() == 0 && appInfo) {
     440             :         // Try to get the UA name from appInfo, falling back to the name
     441           2 :         appInfo->GetUAName(mAppName);
     442           2 :         if (mAppName.Length() == 0) {
     443           2 :           appInfo->GetName(mAppName);
     444             :         }
     445           2 :         appInfo->GetVersion(mAppVersion);
     446           2 :         mAppName.StripChars(R"( ()<>@,;:\"/[]?={})");
     447             :     } else {
     448           0 :         mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION);
     449             :     }
     450             : 
     451             :     // Generating the spoofed userAgent for fingerprinting resistance. We will
     452             :     // round the version to the nearest 10. By doing so, the anonymity group will
     453             :     // cover more versions instead of one version.
     454           2 :     uint32_t spoofedVersion = mAppVersion.ToInteger(&rv);
     455           2 :     if (NS_SUCCEEDED(rv)) {
     456           2 :         spoofedVersion = spoofedVersion - (spoofedVersion % 10);
     457           4 :         mSpoofedUserAgent.Assign(nsPrintfCString(
     458             :             "Mozilla/5.0 (%s; rv:%d.0) Gecko/%s Firefox/%d.0",
     459           2 :             SPOOFED_OSCPU, spoofedVersion, LEGACY_BUILD_ID, spoofedVersion));
     460             :     }
     461             : 
     462           2 :     mSessionStartTime = NowInSeconds();
     463           2 :     mHandlerActive = true;
     464             : 
     465           2 :     rv = mAuthCache.Init();
     466           2 :     if (NS_FAILED(rv)) return rv;
     467             : 
     468           2 :     rv = mPrivateAuthCache.Init();
     469           2 :     if (NS_FAILED(rv)) return rv;
     470             : 
     471           2 :     rv = InitConnectionMgr();
     472           2 :     if (NS_FAILED(rv)) return rv;
     473             : 
     474             :     mRequestContextService =
     475           2 :         do_GetService("@mozilla.org/network/request-context-service;1");
     476             : 
     477             : #if defined(ANDROID) || defined(MOZ_MULET)
     478             :     mProductSub.AssignLiteral(MOZILLA_UAVERSION);
     479             : #else
     480           2 :     mProductSub.AssignLiteral(LEGACY_BUILD_ID);
     481             : #endif
     482             : 
     483             : #if DEBUG
     484             :     // dump user agent prefs
     485           2 :     LOG(("> legacy-app-name = %s\n", mLegacyAppName.get()));
     486           2 :     LOG(("> legacy-app-version = %s\n", mLegacyAppVersion.get()));
     487           2 :     LOG(("> platform = %s\n", mPlatform.get()));
     488           2 :     LOG(("> oscpu = %s\n", mOscpu.get()));
     489           2 :     LOG(("> misc = %s\n", mMisc.get()));
     490           2 :     LOG(("> product = %s\n", mProduct.get()));
     491           2 :     LOG(("> product-sub = %s\n", mProductSub.get()));
     492           2 :     LOG(("> app-name = %s\n", mAppName.get()));
     493           2 :     LOG(("> app-version = %s\n", mAppVersion.get()));
     494           2 :     LOG(("> compat-firefox = %s\n", mCompatFirefox.get()));
     495           2 :     LOG(("> user-agent = %s\n", UserAgent().get()));
     496             : #endif
     497             : 
     498             :     // Startup the http category
     499             :     // Bring alive the objects in the http-protocol-startup category
     500             :     NS_CreateServicesFromCategory(NS_HTTP_STARTUP_CATEGORY,
     501             :                                   static_cast<nsISupports*>(static_cast<void*>(this)),
     502           2 :                                   NS_HTTP_STARTUP_TOPIC);
     503             : 
     504           4 :     nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
     505           2 :     if (obsService) {
     506             :         // register the handler object as a weak callback as we don't need to worry
     507             :         // about shutdown ordering.
     508           2 :         obsService->AddObserver(this, "profile-change-net-teardown", true);
     509           2 :         obsService->AddObserver(this, "profile-change-net-restore", true);
     510           2 :         obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
     511           2 :         obsService->AddObserver(this, "net:clear-active-logins", true);
     512           2 :         obsService->AddObserver(this, "net:prune-dead-connections", true);
     513             :         // Sent by the TorButton add-on in the Tor Browser
     514           2 :         obsService->AddObserver(this, "net:prune-all-connections", true);
     515           2 :         obsService->AddObserver(this, "last-pb-context-exited", true);
     516           2 :         obsService->AddObserver(this, "browser:purge-session-history", true);
     517           2 :         obsService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true);
     518           2 :         obsService->AddObserver(this, "application-background", true);
     519           4 :         obsService->AddObserver(this,
     520             :                                 "net:current-toplevel-outer-content-windowid",
     521           4 :                                 true);
     522             : 
     523           2 :         if (mFastOpenSupported) {
     524           2 :             obsService->AddObserver(this, "captive-portal-login", true);
     525           2 :             obsService->AddObserver(this, "captive-portal-login-success", true);
     526             :         }
     527             : 
     528             :         // disabled as its a nop right now
     529             :         // obsService->AddObserver(this, "net:failed-to-process-uri-content", true);
     530             :     }
     531             : 
     532           2 :     MakeNewRequestTokenBucket();
     533           2 :     mWifiTickler = new Tickler();
     534           2 :     if (NS_FAILED(mWifiTickler->Init()))
     535           2 :         mWifiTickler = nullptr;
     536             : 
     537           4 :     nsCOMPtr<nsIParentalControlsService> pc = do_CreateInstance("@mozilla.org/parental-controls-service;1");
     538           2 :     if (pc) {
     539           2 :         pc->GetParentalControlsEnabled(&mParentalControlEnabled);
     540             :     }
     541           2 :     return NS_OK;
     542             : }
     543             : 
     544             : void
     545           4 : nsHttpHandler::MakeNewRequestTokenBucket()
     546             : {
     547           4 :     LOG(("nsHttpHandler::MakeNewRequestTokenBucket this=%p child=%d\n",
     548             :          this, IsNeckoChild()));
     549           4 :     if (!mConnMgr || IsNeckoChild()) {
     550           3 :         return;
     551             :     }
     552             :     RefPtr<EventTokenBucket> tokenBucket =
     553           3 :         new EventTokenBucket(RequestTokenBucketHz(), RequestTokenBucketBurst());
     554             :     // NOTE The thread or socket may be gone already.
     555           1 :     nsresult rv = mConnMgr->UpdateRequestTokenBucket(tokenBucket);
     556           1 :     if (NS_FAILED(rv)) {
     557           0 :         LOG(("    failed to update request token bucket\n"));
     558             :     }
     559             : }
     560             : 
     561             : nsresult
     562           2 : nsHttpHandler::InitConnectionMgr()
     563             : {
     564             :     // Init ConnectionManager only on parent!
     565           2 :     if (IsNeckoChild()) {
     566           1 :         return NS_OK;
     567             :     }
     568             : 
     569             :     nsresult rv;
     570             : 
     571           1 :     if (!mConnMgr) {
     572           1 :         mConnMgr = new nsHttpConnectionMgr();
     573             :     }
     574             : 
     575           6 :     rv = mConnMgr->Init(mMaxUrgentExcessiveConns,
     576           1 :                         mMaxConnections,
     577           1 :                         mMaxPersistentConnectionsPerServer,
     578           1 :                         mMaxPersistentConnectionsPerProxy,
     579           1 :                         mMaxRequestDelay,
     580           1 :                         mThrottleEnabled,
     581             :                         mThrottleSuspendFor,
     582             :                         mThrottleResumeFor,
     583           1 :                         mThrottleResumeIn);
     584           1 :     return rv;
     585             : }
     586             : 
     587             : nsresult
     588          10 : nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request, bool isSecure)
     589             : {
     590             :     nsresult rv;
     591             : 
     592             :     // Add the "User-Agent" header
     593          10 :     rv = request->SetHeader(nsHttp::User_Agent, UserAgent(),
     594          10 :                             false, nsHttpHeaderArray::eVarietyRequestDefault);
     595          10 :     if (NS_FAILED(rv)) return rv;
     596             : 
     597             :     // MIME based content negotiation lives!
     598             :     // Add the "Accept" header.  Note, this is set as an override because the
     599             :     // service worker expects to see it.  The other "default" headers are
     600             :     // hidden from service worker interception.
     601          10 :     rv = request->SetHeader(nsHttp::Accept, mAccept,
     602          10 :                             false, nsHttpHeaderArray::eVarietyRequestOverride);
     603          10 :     if (NS_FAILED(rv)) return rv;
     604             : 
     605             :     // Add the "Accept-Language" header.  This header is also exposed to the
     606             :     // service worker.
     607          10 :     if (mAcceptLanguagesIsDirty) {
     608           2 :         rv = SetAcceptLanguages();
     609           2 :         MOZ_ASSERT(NS_SUCCEEDED(rv));
     610             :     }
     611             : 
     612             :     // Add the "Accept-Language" header
     613          10 :     if (!mAcceptLanguages.IsEmpty()) {
     614          10 :         rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages,
     615             :                                 false,
     616          10 :                                 nsHttpHeaderArray::eVarietyRequestOverride);
     617          10 :         if (NS_FAILED(rv)) return rv;
     618             :     }
     619             : 
     620             :     // Add the "Accept-Encoding" header
     621          10 :     if (isSecure) {
     622           0 :         rv = request->SetHeader(nsHttp::Accept_Encoding, mHttpsAcceptEncodings,
     623             :                                 false,
     624           0 :                                 nsHttpHeaderArray::eVarietyRequestDefault);
     625             :     } else {
     626          10 :         rv = request->SetHeader(nsHttp::Accept_Encoding, mHttpAcceptEncodings,
     627             :                                 false,
     628          10 :                                 nsHttpHeaderArray::eVarietyRequestDefault);
     629             :     }
     630          10 :     if (NS_FAILED(rv)) return rv;
     631             : 
     632             :     // add the "Send Hint" header
     633          10 :     if (mSafeHintEnabled || mParentalControlEnabled) {
     634           0 :       rv = request->SetHeader(nsHttp::Prefer, NS_LITERAL_CSTRING("safe"),
     635             :                               false,
     636           0 :                               nsHttpHeaderArray::eVarietyRequestDefault);
     637           0 :       if (NS_FAILED(rv)) return rv;
     638             :     }
     639          10 :     return NS_OK;
     640             : }
     641             : 
     642             : nsresult
     643           6 : nsHttpHandler::AddConnectionHeader(nsHttpRequestHead *request,
     644             :                                    uint32_t caps)
     645             : {
     646             :     // RFC2616 section 19.6.2 states that the "Connection: keep-alive"
     647             :     // and "Keep-alive" request headers should not be sent by HTTP/1.1
     648             :     // user-agents.  But this is not a problem in practice, and the
     649             :     // alternative proxy-connection is worse. see 570283
     650             : 
     651           6 :     NS_NAMED_LITERAL_CSTRING(close, "close");
     652           6 :     NS_NAMED_LITERAL_CSTRING(keepAlive, "keep-alive");
     653             : 
     654           6 :     const nsLiteralCString *connectionType = &close;
     655           6 :     if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
     656           6 :         connectionType = &keepAlive;
     657             :     }
     658             : 
     659           6 :     return request->SetHeader(nsHttp::Connection, *connectionType);
     660             : }
     661             : 
     662             : bool
     663           0 : nsHttpHandler::IsAcceptableEncoding(const char *enc, bool isSecure)
     664             : {
     665           0 :     if (!enc)
     666           0 :         return false;
     667             : 
     668             :     // we used to accept x-foo anytime foo was acceptable, but that's just
     669             :     // continuing bad behavior.. so limit it to known x-* patterns
     670             :     bool rv;
     671           0 :     if (isSecure) {
     672           0 :         rv = nsHttp::FindToken(mHttpsAcceptEncodings.get(), enc, HTTP_LWS ",") != nullptr;
     673             :     } else {
     674           0 :         rv = nsHttp::FindToken(mHttpAcceptEncodings.get(), enc, HTTP_LWS ",") != nullptr;
     675             :     }
     676             :     // gzip and deflate are inherently acceptable in modern HTTP - always
     677             :     // process them if a stream converter can also be found.
     678           0 :     if (!rv &&
     679           0 :         (!PL_strcasecmp(enc, "gzip") || !PL_strcasecmp(enc, "deflate") ||
     680           0 :          !PL_strcasecmp(enc, "x-gzip") || !PL_strcasecmp(enc, "x-deflate"))) {
     681           0 :         rv = true;
     682             :     }
     683           0 :     LOG(("nsHttpHandler::IsAceptableEncoding %s https=%d %d\n",
     684             :          enc, isSecure, rv));
     685           0 :     return rv;
     686             : }
     687             : 
     688             : void
     689           0 : nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter()
     690             : {
     691           0 :     LOG(("nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter - "
     692             :          "failed=%d failure_limit=%d", mFastOpenConsecutiveFailureCounter,
     693             :          mFastOpenConsecutiveFailureLimit));
     694           0 :     if (mFastOpenConsecutiveFailureCounter < mFastOpenConsecutiveFailureLimit) {
     695           0 :         mFastOpenConsecutiveFailureCounter++;
     696           0 :         if (mFastOpenConsecutiveFailureCounter == mFastOpenConsecutiveFailureLimit) {
     697           0 :             LOG(("nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter - "
     698             :                  "Fast open failed too many times"));
     699             :         }
     700             :     }
     701           0 : }
     702             : 
     703             : nsresult
     704           0 : nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
     705             : {
     706           0 :     if (!mStreamConvSvc) {
     707             :         nsresult rv;
     708             :         nsCOMPtr<nsIStreamConverterService> service =
     709           0 :             do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
     710           0 :         if (NS_FAILED(rv))
     711           0 :             return rv;
     712             :         mStreamConvSvc = new nsMainThreadPtrHolder<nsIStreamConverterService>(
     713           0 :           "nsHttpHandler::mStreamConvSvc", service);
     714             :     }
     715           0 :     *result = mStreamConvSvc;
     716           0 :     NS_ADDREF(*result);
     717           0 :     return NS_OK;
     718             : }
     719             : 
     720             : nsISiteSecurityService*
     721           9 : nsHttpHandler::GetSSService()
     722             : {
     723           9 :     if (!mSSService) {
     724           4 :         nsCOMPtr<nsISiteSecurityService> service = do_GetService(NS_SSSERVICE_CONTRACTID);
     725             :         mSSService = new nsMainThreadPtrHolder<nsISiteSecurityService>(
     726           4 :           "nsHttpHandler::mSSService", service);
     727             :     }
     728           9 :     return mSSService;
     729             : }
     730             : 
     731             : nsICookieService *
     732           6 : nsHttpHandler::GetCookieService()
     733             : {
     734           6 :     if (!mCookieService) {
     735           2 :         nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
     736             :         mCookieService = new nsMainThreadPtrHolder<nsICookieService>(
     737           2 :           "nsHttpHandler::mCookieService", service);
     738             :     }
     739           6 :     return mCookieService;
     740             : }
     741             : 
     742             : nsresult
     743           0 : nsHttpHandler::GetIOService(nsIIOService** result)
     744             : {
     745           0 :     NS_ENSURE_ARG_POINTER(result);
     746             : 
     747           0 :     NS_ADDREF(*result = mIOService);
     748           0 :     return NS_OK;
     749             : }
     750             : 
     751             : uint32_t
     752           0 : nsHttpHandler::Get32BitsOfPseudoRandom()
     753             : {
     754             :     // only confirm rand seeding on socket thread
     755           0 :     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
     756             : 
     757             :     // rand() provides different amounts of PRNG on different platforms.
     758             :     // 15 or 31 bits are common amounts.
     759             : 
     760             :     static_assert(RAND_MAX >= 0xfff, "RAND_MAX should be >= 12 bits");
     761             : 
     762             : #if RAND_MAX < 0xffffU
     763             :     return ((uint16_t) rand() << 20) |
     764             :             (((uint16_t) rand() & 0xfff) << 8) |
     765             :             ((uint16_t) rand() & 0xff);
     766             : #elif RAND_MAX < 0xffffffffU
     767           0 :     return ((uint16_t) rand() << 16) | ((uint16_t) rand() & 0xffff);
     768             : #else
     769             :     return (uint32_t) rand();
     770             : #endif
     771             : }
     772             : 
     773             : void
     774          22 : nsHttpHandler::NotifyObservers(nsIHttpChannel *chan, const char *event)
     775             : {
     776          22 :     LOG(("nsHttpHandler::NotifyObservers [chan=%p event=\"%s\"]\n", chan, event));
     777          44 :     nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
     778          22 :     if (obsService)
     779          22 :         obsService->NotifyObservers(chan, event, nullptr);
     780          22 : }
     781             : 
     782             : nsresult
     783           0 : nsHttpHandler::AsyncOnChannelRedirect(nsIChannel* oldChan,
     784             :                                       nsIChannel* newChan,
     785             :                                       uint32_t flags,
     786             :                                       nsIEventTarget* mainThreadEventTarget)
     787             : {
     788             :     // TODO E10S This helper has to be initialized on the other process
     789             :     RefPtr<nsAsyncRedirectVerifyHelper> redirectCallbackHelper =
     790           0 :         new nsAsyncRedirectVerifyHelper();
     791             : 
     792           0 :     return redirectCallbackHelper->Init(oldChan,
     793             :                                         newChan,
     794             :                                         flags,
     795           0 :                                         mainThreadEventTarget);
     796             : }
     797             : 
     798             : /* static */ nsresult
     799          10 : nsHttpHandler::GenerateHostPort(const nsCString& host, int32_t port,
     800             :                                 nsACString& hostLine)
     801             : {
     802          10 :     return NS_GenerateHostPort(host, port, hostLine);
     803             : }
     804             : 
     805             : //-----------------------------------------------------------------------------
     806             : // nsHttpHandler <private>
     807             : //-----------------------------------------------------------------------------
     808             : 
     809             : const nsCString&
     810          12 : nsHttpHandler::UserAgent()
     811             : {
     812          12 :     if (nsContentUtils::ShouldResistFingerprinting() &&
     813           0 :         !mSpoofedUserAgent.IsEmpty()) {
     814           0 :         LOG(("using spoofed userAgent : %s\n", mSpoofedUserAgent.get()));
     815           0 :         return mSpoofedUserAgent;
     816             :     }
     817             : 
     818          12 :     if (mUserAgentOverride) {
     819           0 :         LOG(("using general.useragent.override : %s\n", mUserAgentOverride.get()));
     820           0 :         return mUserAgentOverride;
     821             :     }
     822             : 
     823          12 :     if (mUserAgentIsDirty) {
     824           2 :         BuildUserAgent();
     825           2 :         mUserAgentIsDirty = false;
     826             :     }
     827             : 
     828          12 :     return mUserAgent;
     829             : }
     830             : 
     831             : void
     832           2 : nsHttpHandler::BuildUserAgent()
     833             : {
     834           2 :     LOG(("nsHttpHandler::BuildUserAgent\n"));
     835             : 
     836           2 :     MOZ_ASSERT(!mLegacyAppName.IsEmpty() &&
     837             :                !mLegacyAppVersion.IsEmpty(),
     838             :                "HTTP cannot send practical requests without this much");
     839             : 
     840             :     // preallocate to worst-case size, which should always be better
     841             :     // than if we didn't preallocate at all.
     842           6 :     mUserAgent.SetCapacity(mLegacyAppName.Length() +
     843           4 :                            mLegacyAppVersion.Length() +
     844             : #ifndef UA_SPARE_PLATFORM
     845           4 :                            mPlatform.Length() +
     846             : #endif
     847           4 :                            mOscpu.Length() +
     848           4 :                            mMisc.Length() +
     849           4 :                            mProduct.Length() +
     850           4 :                            mProductSub.Length() +
     851           4 :                            mAppName.Length() +
     852           4 :                            mAppVersion.Length() +
     853           4 :                            mCompatFirefox.Length() +
     854           4 :                            mCompatDevice.Length() +
     855           2 :                            mDeviceModelId.Length() +
     856           2 :                            13);
     857             : 
     858             :     // Application portion
     859           2 :     mUserAgent.Assign(mLegacyAppName);
     860           2 :     mUserAgent += '/';
     861           2 :     mUserAgent += mLegacyAppVersion;
     862           2 :     mUserAgent += ' ';
     863             : 
     864             :     // Application comment
     865           2 :     mUserAgent += '(';
     866             : #ifndef UA_SPARE_PLATFORM
     867           2 :     if (!mPlatform.IsEmpty()) {
     868           2 :       mUserAgent += mPlatform;
     869           2 :       mUserAgent.AppendLiteral("; ");
     870             :     }
     871             : #endif
     872           2 :     if (!mCompatDevice.IsEmpty()) {
     873           0 :         mUserAgent += mCompatDevice;
     874           0 :         mUserAgent.AppendLiteral("; ");
     875             :     }
     876           2 :     else if (!mOscpu.IsEmpty()) {
     877           2 :       mUserAgent += mOscpu;
     878           2 :       mUserAgent.AppendLiteral("; ");
     879             :     }
     880           2 :     if (!mDeviceModelId.IsEmpty()) {
     881           0 :         mUserAgent += mDeviceModelId;
     882           0 :         mUserAgent.AppendLiteral("; ");
     883             :     }
     884           2 :     mUserAgent += mMisc;
     885           2 :     mUserAgent += ')';
     886             : 
     887             :     // Product portion
     888           2 :     mUserAgent += ' ';
     889           2 :     mUserAgent += mProduct;
     890           2 :     mUserAgent += '/';
     891           2 :     mUserAgent += mProductSub;
     892             : 
     893           2 :     bool isFirefox = mAppName.EqualsLiteral("Firefox");
     894           2 :     if (isFirefox || mCompatFirefoxEnabled) {
     895             :         // "Firefox/x.y" (compatibility) app token
     896           2 :         mUserAgent += ' ';
     897           2 :         mUserAgent += mCompatFirefox;
     898             :     }
     899           2 :     if (!isFirefox) {
     900             :         // App portion
     901           0 :         mUserAgent += ' ';
     902           0 :         mUserAgent += mAppName;
     903           0 :         mUserAgent += '/';
     904           0 :         mUserAgent += mAppVersion;
     905             :     }
     906           2 : }
     907             : 
     908             : #ifdef XP_WIN
     909             : #define WNT_BASE "Windows NT %ld.%ld"
     910             : #define W64_PREFIX "; Win64"
     911             : #endif
     912             : 
     913             : void
     914           2 : nsHttpHandler::InitUserAgentComponents()
     915             : {
     916             : #ifndef MOZ_UA_OS_AGNOSTIC
     917             :     // Gather platform.
     918           2 :     mPlatform.AssignLiteral(
     919             : #if defined(ANDROID)
     920             :     "Android"
     921             : #elif defined(XP_WIN)
     922             :     "Windows"
     923             : #elif defined(XP_MACOSX)
     924             :     "Macintosh"
     925             : #elif defined(XP_UNIX)
     926             :     // We historically have always had X11 here,
     927             :     // and there seems little a webpage can sensibly do
     928             :     // based on it being something else, so use X11 for
     929             :     // backwards compatibility in all cases.
     930             :     "X11"
     931             : #endif
     932           2 :     );
     933             : #endif
     934             : 
     935             : 
     936             : #ifdef ANDROID
     937             :     nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
     938             :     MOZ_ASSERT(infoService, "Could not find a system info service");
     939             :     nsresult rv;
     940             :     // Add the Android version number to the Fennec platform identifier.
     941             : #if defined MOZ_WIDGET_ANDROID
     942             : #ifndef MOZ_UA_OS_AGNOSTIC // Don't add anything to mPlatform since it's empty.
     943             :     nsAutoString androidVersion;
     944             :     rv = infoService->GetPropertyAsAString(
     945             :         NS_LITERAL_STRING("release_version"), androidVersion);
     946             :     if (NS_SUCCEEDED(rv)) {
     947             :       mPlatform += " ";
     948             :       // If the 2nd character is a ".", we know the major version is a single
     949             :       // digit. If we're running on a version below 4 we pretend to be on
     950             :       // Android KitKat (4.4) to work around scripts sniffing for low versions.
     951             :       if (androidVersion[1] == 46 && androidVersion[0] < 52) {
     952             :         mPlatform += "4.4";
     953             :       } else {
     954             :         mPlatform += NS_LossyConvertUTF16toASCII(androidVersion);
     955             :       }
     956             :     }
     957             : #endif
     958             : #endif
     959             :     // Add the `Mobile` or `Tablet` or `TV` token when running on device.
     960             :     bool isTablet;
     961             :     rv = infoService->GetPropertyAsBool(NS_LITERAL_STRING("tablet"), &isTablet);
     962             :     if (NS_SUCCEEDED(rv) && isTablet) {
     963             :         mCompatDevice.AssignLiteral("Tablet");
     964             :     } else {
     965             :         bool isTV;
     966             :         rv = infoService->GetPropertyAsBool(NS_LITERAL_STRING("tv"), &isTV);
     967             :         if (NS_SUCCEEDED(rv) && isTV) {
     968             :             mCompatDevice.AssignLiteral("TV");
     969             :         } else {
     970             :             mCompatDevice.AssignLiteral("Mobile");
     971             :         }
     972             :     }
     973             : 
     974             :     if (Preferences::GetBool(UA_PREF("use_device"), false)) {
     975             :         mDeviceModelId = mozilla::net::GetDeviceModelId();
     976             :     }
     977             : #endif // ANDROID
     978             : 
     979             : #ifdef MOZ_MULET
     980             :     {
     981             :         // Add the `Mobile` or `Tablet` or `TV` token when running in the b2g
     982             :         // desktop simulator via preference.
     983             :         nsCString deviceType;
     984             :         nsresult rv = Preferences::GetCString("devtools.useragent.device_type", &deviceType);
     985             :         if (NS_SUCCEEDED(rv)) {
     986             :             mCompatDevice.Assign(deviceType);
     987             :         } else {
     988             :             mCompatDevice.AssignLiteral("Mobile");
     989             :         }
     990             :     }
     991             : #endif // MOZ_MULET
     992             : 
     993             : #ifndef MOZ_UA_OS_AGNOSTIC
     994             :     // Gather OS/CPU.
     995             : #if defined(XP_WIN)
     996             :     OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
     997             : #pragma warning(push)
     998             : #pragma warning(disable:4996)
     999             :     if (GetVersionEx(&info)) {
    1000             : #pragma warning(pop)
    1001             :         const char *format;
    1002             : #if defined _M_IA64
    1003             :         format = WNT_BASE W64_PREFIX "; IA64";
    1004             : #elif defined _M_X64 || defined _M_AMD64
    1005             :         format = WNT_BASE W64_PREFIX "; x64";
    1006             : #else
    1007             :         BOOL isWow64 = FALSE;
    1008             :         if (!IsWow64Process(GetCurrentProcess(), &isWow64)) {
    1009             :             isWow64 = FALSE;
    1010             :         }
    1011             :         format = isWow64
    1012             :           ? WNT_BASE "; WOW64"
    1013             :           : WNT_BASE;
    1014             : #endif
    1015             :         SmprintfPointer buf = mozilla::Smprintf(format,
    1016             :                                                 info.dwMajorVersion,
    1017             :                                                 info.dwMinorVersion);
    1018             :         if (buf) {
    1019             :             mOscpu = buf.get();
    1020             :         }
    1021             :     }
    1022             : #elif defined (XP_MACOSX)
    1023             : #if defined(__ppc__)
    1024             :     mOscpu.AssignLiteral("PPC Mac OS X");
    1025             : #elif defined(__i386__) || defined(__x86_64__)
    1026             :     mOscpu.AssignLiteral("Intel Mac OS X");
    1027             : #endif
    1028             :     SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor();
    1029             :     SInt32 minorVersion = nsCocoaFeatures::OSXVersionMinor();
    1030             :     mOscpu += nsPrintfCString(" %d.%d", static_cast<int>(majorVersion),
    1031             :                               static_cast<int>(minorVersion));
    1032             : #elif defined (XP_UNIX)
    1033             :     struct utsname name;
    1034             : 
    1035           2 :     int ret = uname(&name);
    1036           2 :     if (ret >= 0) {
    1037           4 :         nsAutoCString buf;
    1038           2 :         buf =  (char*)name.sysname;
    1039             : 
    1040             :         if (strcmp(name.machine, "x86_64") == 0 &&
    1041             :             sizeof(void *) == sizeof(int32_t)) {
    1042             :             // We're running 32-bit code on x86_64. Make this browser
    1043             :             // look like it's running on i686 hardware, but append "
    1044             :             // (x86_64)" to the end of the oscpu identifier to be able
    1045             :             // to differentiate this from someone running 64-bit code
    1046             :             // on x86_64..
    1047             : 
    1048             :             buf += " i686 on x86_64";
    1049             :         } else {
    1050           2 :             buf += ' ';
    1051             : 
    1052             : #ifdef AIX
    1053             :             // AIX uname returns machine specific info in the uname.machine
    1054             :             // field and does not return the cpu type like other platforms.
    1055             :             // We use the AIX version and release numbers instead.
    1056             :             buf += (char*)name.version;
    1057             :             buf += '.';
    1058             :             buf += (char*)name.release;
    1059             : #else
    1060           2 :             buf += (char*)name.machine;
    1061             : #endif
    1062             :         }
    1063             : 
    1064           2 :         mOscpu.Assign(buf);
    1065             :     }
    1066             : #endif
    1067             : #endif
    1068             : 
    1069           2 :     mUserAgentIsDirty = true;
    1070           2 : }
    1071             : 
    1072             : uint32_t
    1073           4 : nsHttpHandler::MaxSocketCount()
    1074             : {
    1075             :     PR_CallOnce(&nsSocketTransportService::gMaxCountInitOnce,
    1076           4 :                 nsSocketTransportService::DiscoverMaxCount);
    1077             :     // Don't use the full max count because sockets can be held in
    1078             :     // the persistent connection pool for a long time and that could
    1079             :     // starve other users.
    1080             : 
    1081           4 :     uint32_t maxCount = nsSocketTransportService::gMaxCount;
    1082           4 :     if (maxCount <= 8)
    1083           0 :         maxCount = 1;
    1084             :     else
    1085           4 :         maxCount -= 8;
    1086             : 
    1087           4 :     return maxCount;
    1088             : }
    1089             : 
    1090             : void
    1091           2 : nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
    1092             : {
    1093           2 :     nsresult rv = NS_OK;
    1094             :     int32_t val;
    1095             : 
    1096           2 :     LOG(("nsHttpHandler::PrefsChanged [pref=%s]\n", pref));
    1097             : 
    1098             : #define PREF_CHANGED(p) ((pref == nullptr) || !PL_strcmp(pref, p))
    1099             : #define MULTI_PREF_CHANGED(p) \
    1100             :   ((pref == nullptr) || !PL_strncmp(pref, p, sizeof(p) - 1))
    1101             : 
    1102             :     // If a security pref changed, lets clear our connection pool reuse
    1103           2 :     if (MULTI_PREF_CHANGED(SECURITY_PREFIX)) {
    1104           2 :         LOG(("nsHttpHandler::PrefsChanged Security Pref Changed %s\n", pref));
    1105           2 :         if (mConnMgr) {
    1106           0 :             rv = mConnMgr->DoShiftReloadConnectionCleanup(nullptr);
    1107           0 :             if (NS_FAILED(rv)) {
    1108           0 :                 LOG(("nsHttpHandler::PrefsChanged "
    1109             :                      "DoShiftReloadConnectionCleanup failed (%08x)\n", static_cast<uint32_t>(rv)));
    1110             :             }
    1111           0 :             rv = mConnMgr->PruneDeadConnections();
    1112           0 :             if (NS_FAILED(rv)) {
    1113           0 :                 LOG(("nsHttpHandler::PrefsChanged "
    1114             :                      "PruneDeadConnections failed (%08x)\n", static_cast<uint32_t>(rv)));
    1115             :             }
    1116             :         }
    1117             :     }
    1118             : 
    1119             :     //
    1120             :     // UA components
    1121             :     //
    1122             : 
    1123           2 :     bool cVar = false;
    1124             : 
    1125           2 :     if (PREF_CHANGED(UA_PREF("compatMode.firefox"))) {
    1126           2 :         rv = prefs->GetBoolPref(UA_PREF("compatMode.firefox"), &cVar);
    1127           2 :         mCompatFirefoxEnabled = (NS_SUCCEEDED(rv) && cVar);
    1128           2 :         mUserAgentIsDirty = true;
    1129             :     }
    1130             : 
    1131             :     // general.useragent.override
    1132           2 :     if (PREF_CHANGED(UA_PREF("override"))) {
    1133           2 :         prefs->GetCharPref(UA_PREF("override"),
    1134           4 :                             getter_Copies(mUserAgentOverride));
    1135           2 :         mUserAgentIsDirty = true;
    1136             :     }
    1137             : 
    1138             : #ifdef ANDROID
    1139             :     // general.useragent.use_device
    1140             :     if (PREF_CHANGED(UA_PREF("use_device"))) {
    1141             :         if (Preferences::GetBool(UA_PREF("use_device"), false)) {
    1142             :             mDeviceModelId = mozilla::net::GetDeviceModelId();
    1143             :         } else {
    1144             :             mDeviceModelId = EmptyCString();
    1145             :         }
    1146             :         mUserAgentIsDirty = true;
    1147             :     }
    1148             : #endif
    1149             : 
    1150             :     //
    1151             :     // HTTP options
    1152             :     //
    1153             : 
    1154           2 :     if (PREF_CHANGED(HTTP_PREF("keep-alive.timeout"))) {
    1155           2 :         rv = prefs->GetIntPref(HTTP_PREF("keep-alive.timeout"), &val);
    1156           2 :         if (NS_SUCCEEDED(rv))
    1157           2 :             mIdleTimeout = PR_SecondsToInterval(clamped(val, 1, 0xffff));
    1158             :     }
    1159             : 
    1160           2 :     if (PREF_CHANGED(HTTP_PREF("request.max-attempts"))) {
    1161           2 :         rv = prefs->GetIntPref(HTTP_PREF("request.max-attempts"), &val);
    1162           2 :         if (NS_SUCCEEDED(rv))
    1163           2 :             mMaxRequestAttempts = (uint16_t) clamped(val, 1, 0xffff);
    1164             :     }
    1165             : 
    1166           2 :     if (PREF_CHANGED(HTTP_PREF("request.max-start-delay"))) {
    1167           2 :         rv = prefs->GetIntPref(HTTP_PREF("request.max-start-delay"), &val);
    1168           2 :         if (NS_SUCCEEDED(rv)) {
    1169           2 :             mMaxRequestDelay = (uint16_t) clamped(val, 0, 0xffff);
    1170           2 :             if (mConnMgr) {
    1171           0 :                 rv = mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_REQUEST_DELAY,
    1172           0 :                                            mMaxRequestDelay);
    1173           0 :                 if (NS_FAILED(rv)) {
    1174           0 :                     LOG(("nsHttpHandler::PrefsChanged (request.max-start-delay)"
    1175             :                          "UpdateParam failed (%08x)\n", static_cast<uint32_t>(rv)));
    1176             :                 }
    1177             :             }
    1178             :         }
    1179             :     }
    1180             : 
    1181           2 :     if (PREF_CHANGED(HTTP_PREF("response.timeout"))) {
    1182           2 :         rv = prefs->GetIntPref(HTTP_PREF("response.timeout"), &val);
    1183           2 :         if (NS_SUCCEEDED(rv))
    1184           2 :             mResponseTimeout = PR_SecondsToInterval(clamped(val, 0, 0xffff));
    1185             :     }
    1186             : 
    1187           2 :     if (PREF_CHANGED(HTTP_PREF("network-changed.timeout"))) {
    1188           2 :         rv = prefs->GetIntPref(HTTP_PREF("network-changed.timeout"), &val);
    1189           2 :         if (NS_SUCCEEDED(rv))
    1190           2 :             mNetworkChangedTimeout = clamped(val, 1, 600) * 1000;
    1191             :     }
    1192             : 
    1193           2 :     if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
    1194           2 :         rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
    1195           2 :         if (NS_SUCCEEDED(rv)) {
    1196             : 
    1197           6 :             mMaxConnections = (uint16_t) clamped((uint32_t)val,
    1198           8 :                                                  (uint32_t)1, MaxSocketCount());
    1199             : 
    1200           2 :             if (mConnMgr) {
    1201           0 :                 rv = mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
    1202           0 :                                            mMaxConnections);
    1203           0 :                 if (NS_FAILED(rv)) {
    1204           0 :                     LOG(("nsHttpHandler::PrefsChanged (max-connections)"
    1205             :                          "UpdateParam failed (%08x)\n", static_cast<uint32_t>(rv)));
    1206             :                 }
    1207             :             }
    1208             :         }
    1209             :     }
    1210             : 
    1211           2 :     if (PREF_CHANGED(HTTP_PREF("max-urgent-start-excessive-connections-per-host"))) {
    1212           2 :         rv = prefs->GetIntPref(HTTP_PREF("max-urgent-start-excessive-connections-per-host"), &val);
    1213           2 :         if (NS_SUCCEEDED(rv)) {
    1214           2 :             mMaxUrgentExcessiveConns = (uint8_t) clamped(val, 1, 0xff);
    1215           2 :             if (mConnMgr) {
    1216           0 :                 rv = mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_URGENT_START_Q,
    1217           0 :                                            mMaxUrgentExcessiveConns);
    1218           0 :                 if (NS_FAILED(rv)) {
    1219           0 :                     LOG(("nsHttpHandler::PrefsChanged (max-urgent-start-excessive-connections-per-host)"
    1220             :                          "UpdateParam failed (%08x)\n", static_cast<uint32_t>(rv)));
    1221             :                 }
    1222             :              }
    1223             :           }
    1224             :     }
    1225             : 
    1226           2 :     if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-server"))) {
    1227           2 :         rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-server"), &val);
    1228           2 :         if (NS_SUCCEEDED(rv)) {
    1229           2 :             mMaxPersistentConnectionsPerServer = (uint8_t) clamped(val, 1, 0xff);
    1230           2 :             if (mConnMgr) {
    1231           0 :                 rv = mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_HOST,
    1232           0 :                                            mMaxPersistentConnectionsPerServer);
    1233           0 :                 if (NS_FAILED(rv)) {
    1234           0 :                     LOG(("nsHttpHandler::PrefsChanged (max-persistent-connections-per-server)"
    1235             :                          "UpdateParam failed (%08x)\n", static_cast<uint32_t>(rv)));
    1236             :                 }
    1237             :             }
    1238             :         }
    1239             :     }
    1240             : 
    1241           2 :     if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-proxy"))) {
    1242           2 :         rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-proxy"), &val);
    1243           2 :         if (NS_SUCCEEDED(rv)) {
    1244           2 :             mMaxPersistentConnectionsPerProxy = (uint8_t) clamped(val, 1, 0xff);
    1245           2 :             if (mConnMgr) {
    1246           0 :                 rv = mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
    1247           0 :                                            mMaxPersistentConnectionsPerProxy);
    1248           0 :                 if (NS_FAILED(rv)) {
    1249           0 :                     LOG(("nsHttpHandler::PrefsChanged (max-persistent-connections-per-proxy)"
    1250             :                          "UpdateParam failed (%08x)\n", static_cast<uint32_t>(rv)));
    1251             :                 }
    1252             :             }
    1253             :         }
    1254             :     }
    1255             : 
    1256           2 :     if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
    1257           2 :         rv = prefs->GetIntPref(HTTP_PREF("sendRefererHeader"), &val);
    1258           2 :         if (NS_SUCCEEDED(rv))
    1259           2 :             mReferrerLevel = (uint8_t) clamped(val, 0, 0xff);
    1260             :     }
    1261             : 
    1262           2 :     if (PREF_CHANGED(HTTP_PREF("referer.spoofSource"))) {
    1263           2 :         rv = prefs->GetBoolPref(HTTP_PREF("referer.spoofSource"), &cVar);
    1264           2 :         if (NS_SUCCEEDED(rv))
    1265           2 :             mSpoofReferrerSource = cVar;
    1266             :     }
    1267             : 
    1268           2 :     if (PREF_CHANGED(HTTP_PREF("referer.hideOnionSource"))) {
    1269           2 :         rv = prefs->GetBoolPref(HTTP_PREF("referer.hideOnionSource"), &cVar);
    1270           2 :         if (NS_SUCCEEDED(rv))
    1271           2 :             mHideOnionReferrerSource = cVar;
    1272             :     }
    1273             : 
    1274           2 :     if (PREF_CHANGED(HTTP_PREF("referer.trimmingPolicy"))) {
    1275           2 :         rv = prefs->GetIntPref(HTTP_PREF("referer.trimmingPolicy"), &val);
    1276           2 :         if (NS_SUCCEEDED(rv))
    1277           2 :             mReferrerTrimmingPolicy = (uint8_t) clamped(val, 0, 2);
    1278             :     }
    1279             : 
    1280           2 :     if (PREF_CHANGED(HTTP_PREF("referer.XOriginTrimmingPolicy"))) {
    1281           2 :         rv = prefs->GetIntPref(HTTP_PREF("referer.XOriginTrimmingPolicy"), &val);
    1282           2 :         if (NS_SUCCEEDED(rv))
    1283           2 :             mReferrerXOriginTrimmingPolicy = (uint8_t) clamped(val, 0, 2);
    1284             :     }
    1285             : 
    1286           2 :     if (PREF_CHANGED(HTTP_PREF("referer.XOriginPolicy"))) {
    1287           2 :         rv = prefs->GetIntPref(HTTP_PREF("referer.XOriginPolicy"), &val);
    1288           2 :         if (NS_SUCCEEDED(rv))
    1289           2 :             mReferrerXOriginPolicy = (uint8_t) clamped(val, 0, 0xff);
    1290             :     }
    1291             : 
    1292           2 :     if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
    1293           2 :         rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
    1294           2 :         if (NS_SUCCEEDED(rv))
    1295           2 :             mRedirectionLimit = (uint8_t) clamped(val, 0, 0xff);
    1296             :     }
    1297             : 
    1298           2 :     if (PREF_CHANGED(HTTP_PREF("connection-retry-timeout"))) {
    1299           2 :         rv = prefs->GetIntPref(HTTP_PREF("connection-retry-timeout"), &val);
    1300           2 :         if (NS_SUCCEEDED(rv))
    1301           2 :             mIdleSynTimeout = (uint16_t) clamped(val, 0, 3000);
    1302             :     }
    1303             : 
    1304           2 :     if (PREF_CHANGED(HTTP_PREF("fast-fallback-to-IPv4"))) {
    1305           2 :         rv = prefs->GetBoolPref(HTTP_PREF("fast-fallback-to-IPv4"), &cVar);
    1306           2 :         if (NS_SUCCEEDED(rv))
    1307           2 :             mFastFallbackToIPv4 = cVar;
    1308             :     }
    1309             : 
    1310           2 :     if (PREF_CHANGED(HTTP_PREF("version"))) {
    1311           4 :         nsXPIDLCString httpVersion;
    1312           2 :         prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));
    1313           2 :         if (httpVersion) {
    1314           2 :             if (!PL_strcmp(httpVersion, "1.1"))
    1315           2 :                 mHttpVersion = NS_HTTP_VERSION_1_1;
    1316           0 :             else if (!PL_strcmp(httpVersion, "0.9"))
    1317           0 :                 mHttpVersion = NS_HTTP_VERSION_0_9;
    1318             :             else
    1319           0 :                 mHttpVersion = NS_HTTP_VERSION_1_0;
    1320             :         }
    1321             :     }
    1322             : 
    1323           2 :     if (PREF_CHANGED(HTTP_PREF("proxy.version"))) {
    1324           4 :         nsXPIDLCString httpVersion;
    1325           2 :         prefs->GetCharPref(HTTP_PREF("proxy.version"), getter_Copies(httpVersion));
    1326           2 :         if (httpVersion) {
    1327           2 :             if (!PL_strcmp(httpVersion, "1.1"))
    1328           2 :                 mProxyHttpVersion = NS_HTTP_VERSION_1_1;
    1329             :             else
    1330           0 :                 mProxyHttpVersion = NS_HTTP_VERSION_1_0;
    1331             :             // it does not make sense to issue a HTTP/0.9 request to a proxy server
    1332             :         }
    1333             :     }
    1334             : 
    1335           2 :     if (PREF_CHANGED(HTTP_PREF("qos"))) {
    1336           2 :         rv = prefs->GetIntPref(HTTP_PREF("qos"), &val);
    1337           2 :         if (NS_SUCCEEDED(rv))
    1338           2 :             mQoSBits = (uint8_t) clamped(val, 0, 0xff);
    1339             :     }
    1340             : 
    1341           2 :     if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
    1342           4 :         nsXPIDLCString accept;
    1343           2 :         rv = prefs->GetCharPref(HTTP_PREF("accept.default"),
    1344           4 :                                   getter_Copies(accept));
    1345           2 :         if (NS_SUCCEEDED(rv)) {
    1346           2 :             rv = SetAccept(accept);
    1347           2 :             MOZ_ASSERT(NS_SUCCEEDED(rv));
    1348             :         }
    1349             :     }
    1350             : 
    1351           2 :     if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
    1352           4 :         nsXPIDLCString acceptEncodings;
    1353           2 :         rv = prefs->GetCharPref(HTTP_PREF("accept-encoding"),
    1354           4 :                                   getter_Copies(acceptEncodings));
    1355           2 :         if (NS_SUCCEEDED(rv)) {
    1356           2 :             rv = SetAcceptEncodings(acceptEncodings, false);
    1357           2 :             MOZ_ASSERT(NS_SUCCEEDED(rv));
    1358             :         }
    1359             :     }
    1360             : 
    1361           2 :     if (PREF_CHANGED(HTTP_PREF("accept-encoding.secure"))) {
    1362           4 :         nsXPIDLCString acceptEncodings;
    1363           2 :         rv = prefs->GetCharPref(HTTP_PREF("accept-encoding.secure"),
    1364           4 :                                   getter_Copies(acceptEncodings));
    1365           2 :         if (NS_SUCCEEDED(rv)) {
    1366           2 :             rv = SetAcceptEncodings(acceptEncodings, true);
    1367           2 :             MOZ_ASSERT(NS_SUCCEEDED(rv));
    1368             :         }
    1369             :     }
    1370             : 
    1371           2 :     if (PREF_CHANGED(HTTP_PREF("default-socket-type"))) {
    1372           4 :         nsXPIDLCString sval;
    1373           2 :         rv = prefs->GetCharPref(HTTP_PREF("default-socket-type"),
    1374           4 :                                 getter_Copies(sval));
    1375           2 :         if (NS_SUCCEEDED(rv)) {
    1376           2 :             if (sval.IsEmpty())
    1377           2 :                 mDefaultSocketType.Adopt(nullptr);
    1378             :             else {
    1379             :                 // verify that this socket type is actually valid
    1380             :                 nsCOMPtr<nsISocketProviderService> sps(
    1381           0 :                         do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID));
    1382           0 :                 if (sps) {
    1383           0 :                     nsCOMPtr<nsISocketProvider> sp;
    1384           0 :                     rv = sps->GetSocketProvider(sval, getter_AddRefs(sp));
    1385           0 :                     if (NS_SUCCEEDED(rv)) {
    1386             :                         // OK, this looks like a valid socket provider.
    1387           0 :                         mDefaultSocketType.Assign(sval);
    1388             :                     }
    1389             :                 }
    1390             :             }
    1391             :         }
    1392             :     }
    1393             : 
    1394           2 :     if (PREF_CHANGED(HTTP_PREF("prompt-temp-redirect"))) {
    1395           2 :         rv = prefs->GetBoolPref(HTTP_PREF("prompt-temp-redirect"), &cVar);
    1396           2 :         if (NS_SUCCEEDED(rv)) {
    1397           2 :             mPromptTempRedirect = cVar;
    1398             :         }
    1399             :     }
    1400             : 
    1401           2 :     if (PREF_CHANGED(HTTP_PREF("assoc-req.enforce"))) {
    1402           2 :         cVar = false;
    1403           2 :         rv = prefs->GetBoolPref(HTTP_PREF("assoc-req.enforce"), &cVar);
    1404           2 :         if (NS_SUCCEEDED(rv))
    1405           2 :             mEnforceAssocReq = cVar;
    1406             :     }
    1407             : 
    1408             :     // enable Persistent caching for HTTPS - bug#205921
    1409           2 :     if (PREF_CHANGED(BROWSER_PREF("disk_cache_ssl"))) {
    1410           2 :         cVar = false;
    1411           2 :         rv = prefs->GetBoolPref(BROWSER_PREF("disk_cache_ssl"), &cVar);
    1412           2 :         if (NS_SUCCEEDED(rv))
    1413           2 :             mEnablePersistentHttpsCaching = cVar;
    1414             :     }
    1415             : 
    1416           2 :     if (PREF_CHANGED(HTTP_PREF("phishy-userpass-length"))) {
    1417           2 :         rv = prefs->GetIntPref(HTTP_PREF("phishy-userpass-length"), &val);
    1418           2 :         if (NS_SUCCEEDED(rv))
    1419           0 :             mPhishyUserPassLength = (uint8_t) clamped(val, 0, 0xff);
    1420             :     }
    1421             : 
    1422           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.enabled"))) {
    1423           2 :         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled"), &cVar);
    1424           2 :         if (NS_SUCCEEDED(rv))
    1425           2 :             mEnableSpdy = cVar;
    1426             :     }
    1427             : 
    1428           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.enabled.http2"))) {
    1429           2 :         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled.http2"), &cVar);
    1430           2 :         if (NS_SUCCEEDED(rv))
    1431           2 :             mHttp2Enabled = cVar;
    1432             :     }
    1433             : 
    1434           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.enabled.deps"))) {
    1435           2 :         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled.deps"), &cVar);
    1436           2 :         if (NS_SUCCEEDED(rv))
    1437           2 :             mUseH2Deps = cVar;
    1438             :     }
    1439             : 
    1440           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.enforce-tls-profile"))) {
    1441           2 :         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enforce-tls-profile"), &cVar);
    1442           2 :         if (NS_SUCCEEDED(rv))
    1443           2 :             mEnforceHttp2TlsProfile = cVar;
    1444             :     }
    1445             : 
    1446           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.coalesce-hostnames"))) {
    1447           2 :         rv = prefs->GetBoolPref(HTTP_PREF("spdy.coalesce-hostnames"), &cVar);
    1448           2 :         if (NS_SUCCEEDED(rv))
    1449           2 :             mCoalesceSpdy = cVar;
    1450             :     }
    1451             : 
    1452           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.persistent-settings"))) {
    1453             :         rv = prefs->GetBoolPref(HTTP_PREF("spdy.persistent-settings"),
    1454           2 :                                 &cVar);
    1455           2 :         if (NS_SUCCEEDED(rv))
    1456           2 :             mSpdyPersistentSettings = cVar;
    1457             :     }
    1458             : 
    1459           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.timeout"))) {
    1460           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.timeout"), &val);
    1461           2 :         if (NS_SUCCEEDED(rv))
    1462           2 :             mSpdyTimeout = PR_SecondsToInterval(clamped(val, 1, 0xffff));
    1463             :     }
    1464             : 
    1465           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.chunk-size"))) {
    1466             :         // keep this within http/2 ranges of 1 to 2^14-1
    1467           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.chunk-size"), &val);
    1468           2 :         if (NS_SUCCEEDED(rv))
    1469           2 :             mSpdySendingChunkSize = (uint32_t) clamped(val, 1, 0x3fff);
    1470             :     }
    1471             : 
    1472             :     // The amount of idle seconds on a spdy connection before initiating a
    1473             :     // server ping. 0 will disable.
    1474           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.ping-threshold"))) {
    1475           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.ping-threshold"), &val);
    1476           2 :         if (NS_SUCCEEDED(rv))
    1477           2 :             mSpdyPingThreshold =
    1478           4 :                 PR_SecondsToInterval((uint16_t) clamped(val, 0, 0x7fffffff));
    1479             :     }
    1480             : 
    1481             :     // The amount of seconds to wait for a spdy ping response before
    1482             :     // closing the session.
    1483           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.ping-timeout"))) {
    1484           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.ping-timeout"), &val);
    1485           2 :         if (NS_SUCCEEDED(rv))
    1486           2 :             mSpdyPingTimeout =
    1487           4 :                 PR_SecondsToInterval((uint16_t) clamped(val, 0, 0x7fffffff));
    1488             :     }
    1489             : 
    1490           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.allow-push"))) {
    1491             :         rv = prefs->GetBoolPref(HTTP_PREF("spdy.allow-push"),
    1492           2 :                                 &cVar);
    1493           2 :         if (NS_SUCCEEDED(rv))
    1494           2 :             mAllowPush = cVar;
    1495             :     }
    1496             : 
    1497           2 :     if (PREF_CHANGED(HTTP_PREF("altsvc.enabled"))) {
    1498             :         rv = prefs->GetBoolPref(HTTP_PREF("altsvc.enabled"),
    1499           2 :                                 &cVar);
    1500           2 :         if (NS_SUCCEEDED(rv))
    1501           2 :             mEnableAltSvc = cVar;
    1502             :     }
    1503             : 
    1504             : 
    1505           2 :     if (PREF_CHANGED(HTTP_PREF("altsvc.oe"))) {
    1506             :         rv = prefs->GetBoolPref(HTTP_PREF("altsvc.oe"),
    1507           2 :                                 &cVar);
    1508           2 :         if (NS_SUCCEEDED(rv))
    1509           2 :             mEnableAltSvcOE = cVar;
    1510             :     }
    1511             : 
    1512           2 :     if (PREF_CHANGED(HTTP_PREF("originextension"))) {
    1513             :         rv = prefs->GetBoolPref(HTTP_PREF("originextension"),
    1514           2 :                                 &cVar);
    1515           2 :         if (NS_SUCCEEDED(rv))
    1516           2 :             mEnableOriginExtension = cVar;
    1517             :     }
    1518             : 
    1519           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.push-allowance"))) {
    1520           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.push-allowance"), &val);
    1521           2 :         if (NS_SUCCEEDED(rv)) {
    1522           2 :             mSpdyPushAllowance =
    1523           2 :                 static_cast<uint32_t>
    1524           4 :                 (clamped(val, 1024, static_cast<int32_t>(ASpdySession::kInitialRwin)));
    1525             :         }
    1526             :     }
    1527             : 
    1528           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.pull-allowance"))) {
    1529           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.pull-allowance"), &val);
    1530           2 :         if (NS_SUCCEEDED(rv)) {
    1531           2 :             mSpdyPullAllowance =
    1532           4 :                 static_cast<uint32_t>(clamped(val, 1024, 0x7fffffff));
    1533             :         }
    1534             :     }
    1535             : 
    1536           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.default-concurrent"))) {
    1537           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.default-concurrent"), &val);
    1538           2 :         if (NS_SUCCEEDED(rv)) {
    1539           2 :             mDefaultSpdyConcurrent =
    1540           4 :                 static_cast<uint32_t>(std::max<int32_t>(std::min<int32_t>(val, 9999), 1));
    1541             :         }
    1542             :     }
    1543             : 
    1544             :     // The amount of seconds to wait for a spdy ping response before
    1545             :     // closing the session.
    1546           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.send-buffer-size"))) {
    1547           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.send-buffer-size"), &val);
    1548           2 :         if (NS_SUCCEEDED(rv))
    1549           2 :             mSpdySendBufferSize = (uint32_t) clamped(val, 1500, 0x7fffffff);
    1550             :     }
    1551             : 
    1552             :     // The maximum amount of time to wait for socket transport to be
    1553             :     // established
    1554           2 :     if (PREF_CHANGED(HTTP_PREF("connection-timeout"))) {
    1555           2 :         rv = prefs->GetIntPref(HTTP_PREF("connection-timeout"), &val);
    1556           2 :         if (NS_SUCCEEDED(rv))
    1557             :             // the pref is in seconds, but the variable is in milliseconds
    1558           2 :             mConnectTimeout = clamped(val, 1, 0xffff) * PR_MSEC_PER_SEC;
    1559             :     }
    1560             : 
    1561             :     // The maximum number of current global half open sockets allowable
    1562             :     // for starting a new speculative connection.
    1563           2 :     if (PREF_CHANGED(HTTP_PREF("speculative-parallel-limit"))) {
    1564           2 :         rv = prefs->GetIntPref(HTTP_PREF("speculative-parallel-limit"), &val);
    1565           2 :         if (NS_SUCCEEDED(rv))
    1566           2 :             mParallelSpeculativeConnectLimit = (uint32_t) clamped(val, 0, 1024);
    1567             :     }
    1568             : 
    1569             :     // Whether or not to block requests for non head js/css items (e.g. media)
    1570             :     // while those elements load.
    1571           2 :     if (PREF_CHANGED(HTTP_PREF("rendering-critical-requests-prioritization"))) {
    1572           2 :         rv = prefs->GetBoolPref(HTTP_PREF("rendering-critical-requests-prioritization"), &cVar);
    1573           2 :         if (NS_SUCCEEDED(rv))
    1574           2 :             mCriticalRequestPrioritization = cVar;
    1575             :     }
    1576             : 
    1577             :     // on transition of network.http.diagnostics to true print
    1578             :     // a bunch of information to the console
    1579           2 :     if (pref && PREF_CHANGED(HTTP_PREF("diagnostics"))) {
    1580           0 :         rv = prefs->GetBoolPref(HTTP_PREF("diagnostics"), &cVar);
    1581           0 :         if (NS_SUCCEEDED(rv) && cVar) {
    1582           0 :             if (mConnMgr)
    1583           0 :                 mConnMgr->PrintDiagnostics();
    1584             :         }
    1585             :     }
    1586             : 
    1587           2 :     if (PREF_CHANGED(HTTP_PREF("max_response_header_size"))) {
    1588           2 :         rv = prefs->GetIntPref(HTTP_PREF("max_response_header_size"), &val);
    1589           2 :         if (NS_SUCCEEDED(rv)) {
    1590           2 :             mMaxHttpResponseHeaderSize = val;
    1591             :         }
    1592             :     }
    1593             : 
    1594           2 :     if (PREF_CHANGED(HTTP_PREF("throttle.enable"))) {
    1595           2 :         rv = prefs->GetBoolPref(HTTP_PREF("throttle.enable"), &mThrottleEnabled);
    1596           2 :         if (NS_SUCCEEDED(rv) && mConnMgr) {
    1597           0 :             Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_ENABLED,
    1598           0 :                                             static_cast<int32_t>(mThrottleEnabled));
    1599             :         }
    1600             :     }
    1601             : 
    1602           2 :     if (PREF_CHANGED(HTTP_PREF("throttle.suspend-for"))) {
    1603           2 :         rv = prefs->GetIntPref(HTTP_PREF("throttle.suspend-for"), &val);
    1604           2 :         mThrottleSuspendFor = (uint32_t)clamped(val, 0, 120000);
    1605           2 :         if (NS_SUCCEEDED(rv) && mConnMgr) {
    1606           0 :             Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_SUSPEND_FOR,
    1607           0 :                                             mThrottleSuspendFor);
    1608             :         }
    1609             :     }
    1610             : 
    1611           2 :     if (PREF_CHANGED(HTTP_PREF("throttle.resume-for"))) {
    1612           2 :         rv = prefs->GetIntPref(HTTP_PREF("throttle.resume-for"), &val);
    1613           2 :         mThrottleResumeFor = (uint32_t)clamped(val, 0, 120000);
    1614           2 :         if (NS_SUCCEEDED(rv) && mConnMgr) {
    1615           0 :             Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_RESUME_FOR,
    1616           0 :                                             mThrottleResumeFor);
    1617             :         }
    1618             :     }
    1619             : 
    1620           2 :     if (PREF_CHANGED(HTTP_PREF("throttle.resume-background-in"))) {
    1621           2 :         rv = prefs->GetIntPref(HTTP_PREF("throttle.resume-background-in"), &val);
    1622           2 :         mThrottleResumeIn = (uint32_t)clamped(val, 0, 120000);
    1623           2 :         if (NS_SUCCEEDED(rv) && mConnMgr) {
    1624           0 :             Unused << mConnMgr->UpdateParam(nsHttpConnectionMgr::THROTTLING_RESUME_IN,
    1625           0 :                                             mThrottleResumeIn);
    1626             :         }
    1627             :     }
    1628             : 
    1629           2 :     if (PREF_CHANGED(HTTP_PREF("on_click_priority"))) {
    1630           2 :         Unused << prefs->GetBoolPref(HTTP_PREF("on_click_priority"), &mUrgentStartEnabled);
    1631             :     }
    1632             : 
    1633           2 :     if (PREF_CHANGED(HTTP_PREF("focused_window_transaction_ratio"))) {
    1634           2 :         float ratio = 0;
    1635           2 :         rv = prefs->GetFloatPref(HTTP_PREF("focused_window_transaction_ratio"), &ratio);
    1636           2 :         if (NS_SUCCEEDED(rv)) {
    1637           2 :             if (ratio > 0 && ratio < 1) {
    1638           2 :                 mFocusedWindowTransactionRatio = ratio;
    1639             :             } else {
    1640           0 :                 NS_WARNING("Wrong value for focused_window_transaction_ratio");
    1641             :             }
    1642             :         }
    1643             :     }
    1644             : 
    1645             :     //
    1646             :     // INTL options
    1647             :     //
    1648             : 
    1649           2 :     if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) {
    1650             :         // We don't want to set the new accept languages here since
    1651             :         // this pref is a complex type and it may be racy with flushing
    1652             :         // string resources.
    1653           2 :         mAcceptLanguagesIsDirty = true;
    1654             :     }
    1655             : 
    1656             :     //
    1657             :     // Tracking options
    1658             :     //
    1659             : 
    1660           2 :     if (PREF_CHANGED(DONOTTRACK_HEADER_ENABLED)) {
    1661           2 :         cVar = false;
    1662           2 :         rv = prefs->GetBoolPref(DONOTTRACK_HEADER_ENABLED, &cVar);
    1663           2 :         if (NS_SUCCEEDED(rv)) {
    1664           2 :             mDoNotTrackEnabled = cVar;
    1665             :         }
    1666             :     }
    1667             :     // Hint option
    1668           2 :     if (PREF_CHANGED(SAFE_HINT_HEADER_VALUE)) {
    1669           2 :         cVar = false;
    1670           2 :         rv = prefs->GetBoolPref(SAFE_HINT_HEADER_VALUE, &cVar);
    1671           2 :         if (NS_SUCCEEDED(rv)) {
    1672           0 :             mSafeHintEnabled = cVar;
    1673             :         }
    1674             :     }
    1675             : 
    1676             :     // toggle to true anytime a token bucket related pref is changed.. that
    1677             :     // includes telemetry and allow-experiments because of the abtest profile
    1678           2 :     bool requestTokenBucketUpdated = false;
    1679             : 
    1680             :     //
    1681             :     // Telemetry
    1682             :     //
    1683             : 
    1684           2 :     if (PREF_CHANGED(TELEMETRY_ENABLED)) {
    1685           2 :         cVar = false;
    1686           2 :         requestTokenBucketUpdated = true;
    1687           2 :         rv = prefs->GetBoolPref(TELEMETRY_ENABLED, &cVar);
    1688           2 :         if (NS_SUCCEEDED(rv)) {
    1689           2 :             mTelemetryEnabled = cVar;
    1690             :         }
    1691             :     }
    1692             : 
    1693             :     // "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256" is the required h2 interop
    1694             :     // suite.
    1695             : 
    1696           2 :     if (PREF_CHANGED(H2MANDATORY_SUITE)) {
    1697           2 :         cVar = false;
    1698           2 :         rv = prefs->GetBoolPref(H2MANDATORY_SUITE, &cVar);
    1699           2 :         if (NS_SUCCEEDED(rv)) {
    1700           2 :             mH2MandatorySuiteEnabled = cVar;
    1701             :         }
    1702             :     }
    1703             : 
    1704             :     //
    1705             :     // network.allow-experiments
    1706             :     //
    1707           2 :     if (PREF_CHANGED(ALLOW_EXPERIMENTS)) {
    1708           2 :         cVar = true;
    1709           2 :         requestTokenBucketUpdated = true;
    1710           2 :         rv = prefs->GetBoolPref(ALLOW_EXPERIMENTS, &cVar);
    1711           2 :         if (NS_SUCCEEDED(rv)) {
    1712           2 :             mAllowExperiments = cVar;
    1713             :         }
    1714             :     }
    1715             : 
    1716             :     // network.http.debug-observations
    1717           2 :     if (PREF_CHANGED("network.http.debug-observations")) {
    1718           2 :         cVar = false;
    1719           2 :         rv = prefs->GetBoolPref("network.http.debug-observations", &cVar);
    1720           2 :         if (NS_SUCCEEDED(rv)) {
    1721           0 :             mDebugObservations = cVar;
    1722             :         }
    1723             :     }
    1724             : 
    1725           2 :     if (PREF_CHANGED(HTTP_PREF("pacing.requests.enabled"))) {
    1726           2 :         rv = prefs->GetBoolPref(HTTP_PREF("pacing.requests.enabled"), &cVar);
    1727           2 :         if (NS_SUCCEEDED(rv)) {
    1728           2 :             mRequestTokenBucketEnabled = cVar;
    1729           2 :             requestTokenBucketUpdated = true;
    1730             :         }
    1731             :     }
    1732           2 :     if (PREF_CHANGED(HTTP_PREF("pacing.requests.min-parallelism"))) {
    1733           2 :         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.min-parallelism"), &val);
    1734           2 :         if (NS_SUCCEEDED(rv)) {
    1735           2 :             mRequestTokenBucketMinParallelism = static_cast<uint16_t>(clamped(val, 1, 1024));
    1736           2 :             requestTokenBucketUpdated = true;
    1737             :         }
    1738             :     }
    1739           2 :     if (PREF_CHANGED(HTTP_PREF("pacing.requests.hz"))) {
    1740           2 :         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.hz"), &val);
    1741           2 :         if (NS_SUCCEEDED(rv)) {
    1742           2 :             mRequestTokenBucketHz = static_cast<uint32_t>(clamped(val, 1, 10000));
    1743           2 :             requestTokenBucketUpdated = true;
    1744             :         }
    1745             :     }
    1746           2 :     if (PREF_CHANGED(HTTP_PREF("pacing.requests.burst"))) {
    1747           2 :         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.burst"), &val);
    1748           2 :         if (NS_SUCCEEDED(rv)) {
    1749           2 :             mRequestTokenBucketBurst = val ? val : 1;
    1750           2 :             requestTokenBucketUpdated = true;
    1751             :         }
    1752             :     }
    1753           2 :     if (requestTokenBucketUpdated) {
    1754           2 :         MakeNewRequestTokenBucket();
    1755             :     }
    1756             : 
    1757             :     // Keepalive values for initial and idle connections.
    1758           2 :     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.short_lived_connections"))) {
    1759             :         rv = prefs->GetBoolPref(
    1760           2 :             HTTP_PREF("tcp_keepalive.short_lived_connections"), &cVar);
    1761           2 :         if (NS_SUCCEEDED(rv) && cVar != mTCPKeepaliveShortLivedEnabled) {
    1762           2 :             mTCPKeepaliveShortLivedEnabled = cVar;
    1763             :         }
    1764             :     }
    1765             : 
    1766           2 :     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.short_lived_time"))) {
    1767             :         rv = prefs->GetIntPref(
    1768           2 :             HTTP_PREF("tcp_keepalive.short_lived_time"), &val);
    1769           2 :         if (NS_SUCCEEDED(rv) && val > 0)
    1770           2 :             mTCPKeepaliveShortLivedTimeS = clamped(val, 1, 300); // Max 5 mins.
    1771             :     }
    1772             : 
    1773           2 :     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.short_lived_idle_time"))) {
    1774             :         rv = prefs->GetIntPref(
    1775           2 :             HTTP_PREF("tcp_keepalive.short_lived_idle_time"), &val);
    1776           2 :         if (NS_SUCCEEDED(rv) && val > 0)
    1777           2 :             mTCPKeepaliveShortLivedIdleTimeS = clamped(val,
    1778           4 :                                                        1, kMaxTCPKeepIdle);
    1779             :     }
    1780             : 
    1781             :     // Keepalive values for Long-lived Connections.
    1782           2 :     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.long_lived_connections"))) {
    1783             :         rv = prefs->GetBoolPref(
    1784           2 :             HTTP_PREF("tcp_keepalive.long_lived_connections"), &cVar);
    1785           2 :         if (NS_SUCCEEDED(rv) && cVar != mTCPKeepaliveLongLivedEnabled) {
    1786           2 :             mTCPKeepaliveLongLivedEnabled = cVar;
    1787             :         }
    1788             :     }
    1789             : 
    1790           2 :     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.long_lived_idle_time"))) {
    1791             :         rv = prefs->GetIntPref(
    1792           2 :             HTTP_PREF("tcp_keepalive.long_lived_idle_time"), &val);
    1793           2 :         if (NS_SUCCEEDED(rv) && val > 0)
    1794           2 :             mTCPKeepaliveLongLivedIdleTimeS = clamped(val,
    1795           4 :                                                       1, kMaxTCPKeepIdle);
    1796             :     }
    1797             : 
    1798           4 :     if (PREF_CHANGED(HTTP_PREF("enforce-framing.http1")) ||
    1799           0 :         PREF_CHANGED(HTTP_PREF("enforce-framing.soft")) ) {
    1800           2 :         rv = prefs->GetBoolPref(HTTP_PREF("enforce-framing.http1"), &cVar);
    1801           2 :         if (NS_SUCCEEDED(rv) && cVar) {
    1802           0 :             mEnforceH1Framing = FRAMECHECK_STRICT;
    1803             :         } else {
    1804           2 :             rv = prefs->GetBoolPref(HTTP_PREF("enforce-framing.soft"), &cVar);
    1805           2 :             if (NS_SUCCEEDED(rv) && cVar) {
    1806           2 :                 mEnforceH1Framing = FRAMECHECK_BARELY;
    1807             :             } else {
    1808           0 :                 mEnforceH1Framing = FRAMECHECK_LAX;
    1809             :             }
    1810             :         }
    1811             :     }
    1812             : 
    1813           2 :     if (PREF_CHANGED(TCP_FAST_OPEN_ENABLE)) {
    1814           2 :         rv = prefs->GetBoolPref(TCP_FAST_OPEN_ENABLE, &cVar);
    1815           2 :         if (NS_SUCCEEDED(rv)) {
    1816           2 :             mUseFastOpen = cVar;
    1817             :         }
    1818             :     }
    1819             : 
    1820           2 :     if (PREF_CHANGED(TCP_FAST_OPEN_FAILURE_LIMIT)) {
    1821           2 :         rv = prefs->GetIntPref(TCP_FAST_OPEN_FAILURE_LIMIT, &val);
    1822           2 :         if (NS_SUCCEEDED(rv)) {
    1823           2 :             if (val < 0) {
    1824           0 :                 val = 0;
    1825             :             }
    1826           2 :             mFastOpenConsecutiveFailureLimit = val;
    1827             :         }
    1828             :     }
    1829             : 
    1830           2 :     if (PREF_CHANGED(HTTP_PREF("keep_empty_response_headers_as_empty_string"))) {
    1831             :         rv = prefs->GetBoolPref(HTTP_PREF("keep_empty_response_headers_as_empty_string"),
    1832           2 :                                 &cVar);
    1833           2 :         if (NS_SUCCEEDED(rv)) {
    1834           2 :             mKeepEmptyResponseHeadersAsEmtpyString = cVar;
    1835             :         }
    1836             :     }
    1837             : 
    1838           2 :     if (PREF_CHANGED(HTTP_PREF("spdy.hpack-default-buffer"))) {
    1839           2 :         rv = prefs->GetIntPref(HTTP_PREF("spdy.default-hpack-buffer"), &val);
    1840           2 :         if (NS_SUCCEEDED(rv)) {
    1841           2 :             mDefaultHpackBuffer = val;
    1842             :         }
    1843             :     }
    1844             : 
    1845             :     // Enable HTTP response timeout if TCP Keepalives are disabled.
    1846           2 :     mResponseTimeoutEnabled = !mTCPKeepaliveShortLivedEnabled &&
    1847           0 :                               !mTCPKeepaliveLongLivedEnabled;
    1848             : 
    1849             : #undef PREF_CHANGED
    1850             : #undef MULTI_PREF_CHANGED
    1851           2 : }
    1852             : 
    1853             : 
    1854             : /**
    1855             :  * Currently, only regularizes the case of subtags.
    1856             :  */
    1857             : static void
    1858           4 : CanonicalizeLanguageTag(char *languageTag)
    1859             : {
    1860           4 :     char *s = languageTag;
    1861          32 :     while (*s != '\0') {
    1862          14 :         *s = nsCRT::ToLower(*s);
    1863          14 :         s++;
    1864             :     }
    1865             : 
    1866           4 :     s = languageTag;
    1867           4 :     bool isFirst = true;
    1868           4 :     bool seenSingleton = false;
    1869          16 :     while (*s != '\0') {
    1870           6 :         char *subTagEnd = strchr(s, '-');
    1871           6 :         if (subTagEnd == nullptr) {
    1872           4 :             subTagEnd = strchr(s, '\0');
    1873             :         }
    1874             : 
    1875           6 :         if (isFirst) {
    1876           4 :             isFirst = false;
    1877           2 :         } else if (seenSingleton) {
    1878             :             // Do nothing
    1879             :         } else {
    1880           2 :             size_t subTagLength = subTagEnd - s;
    1881           2 :             if (subTagLength == 1) {
    1882           0 :                 seenSingleton = true;
    1883           2 :             } else if (subTagLength == 2) {
    1884           2 :                 *s = nsCRT::ToUpper(*s);
    1885           2 :                 *(s + 1) = nsCRT::ToUpper(*(s + 1));
    1886           0 :             } else if (subTagLength == 4) {
    1887           0 :                 *s = nsCRT::ToUpper(*s);
    1888             :             }
    1889             :         }
    1890             : 
    1891           6 :         s = subTagEnd;
    1892           6 :         if (*s != '\0') {
    1893           2 :             s++;
    1894             :         }
    1895             :     }
    1896           4 : }
    1897             : 
    1898             : /**
    1899             :  *  Allocates a C string into that contains a ISO 639 language list
    1900             :  *  notated with HTTP "q" values for output with a HTTP Accept-Language
    1901             :  *  header. Previous q values will be stripped because the order of
    1902             :  *  the langs imply the q value. The q values are calculated by dividing
    1903             :  *  1.0 amongst the number of languages present.
    1904             :  *
    1905             :  *  Ex: passing: "en, ja"
    1906             :  *      returns: "en,ja;q=0.5"
    1907             :  *
    1908             :  *      passing: "en, ja, fr_CA"
    1909             :  *      returns: "en,ja;q=0.7,fr_CA;q=0.3"
    1910             :  */
    1911             : static nsresult
    1912           2 : PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLanguages)
    1913             : {
    1914           2 :     if (!i_AcceptLanguages)
    1915           0 :         return NS_OK;
    1916             : 
    1917             :     uint32_t n, count_n, size, wrote;
    1918             :     double q, dec;
    1919             :     char *p, *p2, *token, *q_Accept, *o_Accept;
    1920             :     const char *comma;
    1921             :     int32_t available;
    1922             : 
    1923           2 :     o_Accept = strdup(i_AcceptLanguages);
    1924           2 :     if (!o_Accept)
    1925           0 :         return NS_ERROR_OUT_OF_MEMORY;
    1926          20 :     for (p = o_Accept, n = size = 0; '\0' != *p; p++) {
    1927          18 :         if (*p == ',') n++;
    1928          18 :             size++;
    1929             :     }
    1930             : 
    1931           2 :     available = size + ++n * 11 + 1;
    1932           4 :     q_Accept = new char[available];
    1933           2 :     if (!q_Accept) {
    1934           0 :         free(o_Accept);
    1935           0 :         return NS_ERROR_OUT_OF_MEMORY;
    1936             :     }
    1937           2 :     *q_Accept = '\0';
    1938           2 :     q = 1.0;
    1939           2 :     dec = q / (double) n;
    1940           2 :     count_n = 0;
    1941           2 :     p2 = q_Accept;
    1942           6 :     for (token = nsCRT::strtok(o_Accept, ",", &p);
    1943           6 :          token != nullptr;
    1944           4 :          token = nsCRT::strtok(p, ",", &p))
    1945             :     {
    1946           4 :         token = net_FindCharNotInSet(token, HTTP_LWS);
    1947             :         char* trim;
    1948           4 :         trim = net_FindCharInSet(token, ";" HTTP_LWS);
    1949           4 :         if (trim != nullptr)  // remove "; q=..." if present
    1950           4 :             *trim = '\0';
    1951             : 
    1952           4 :         if (*token != '\0') {
    1953           4 :             CanonicalizeLanguageTag(token);
    1954             : 
    1955           4 :             comma = count_n++ != 0 ? "," : ""; // delimiter if not first item
    1956           4 :             uint32_t u = QVAL_TO_UINT(q);
    1957             : 
    1958             :             // Only display q-value if less than 1.00.
    1959           4 :             if (u < 100) {
    1960             :                 const char *qval_str;
    1961             : 
    1962             :                 // With a small number of languages, one decimal place is enough to prevent duplicate q-values.
    1963             :                 // Also, trailing zeroes do not add any information, so they can be removed.
    1964           2 :                 if ((n < 10) || ((u % 10) == 0)) {
    1965           2 :                     u = (u + 5) / 10;
    1966           2 :                     qval_str = "%s%s;q=0.%u";
    1967             :                 } else {
    1968             :                     // Values below 10 require zero padding.
    1969           0 :                     qval_str = "%s%s;q=0.%02u";
    1970             :                 }
    1971             : 
    1972           2 :                 wrote = snprintf(p2, available, qval_str, comma, token, u);
    1973             :             } else {
    1974           2 :                 wrote = snprintf(p2, available, "%s%s", comma, token);
    1975             :             }
    1976             : 
    1977           4 :             q -= dec;
    1978           4 :             p2 += wrote;
    1979           4 :             available -= wrote;
    1980           4 :             MOZ_ASSERT(available > 0, "allocated string not long enough");
    1981             :         }
    1982             :     }
    1983           2 :     free(o_Accept);
    1984             : 
    1985           2 :     o_AcceptLanguages.Assign((const char *) q_Accept);
    1986           2 :     delete [] q_Accept;
    1987             : 
    1988           2 :     return NS_OK;
    1989             : }
    1990             : 
    1991             : nsresult
    1992           2 : nsHttpHandler::SetAcceptLanguages()
    1993             : {
    1994           2 :     mAcceptLanguagesIsDirty = false;
    1995             : 
    1996             :     const nsAdoptingCString& acceptLanguages =
    1997           4 :         Preferences::GetLocalizedCString(INTL_ACCEPT_LANGUAGES);
    1998             : 
    1999           4 :     nsAutoCString buf;
    2000           2 :     nsresult rv = PrepareAcceptLanguages(acceptLanguages.get(), buf);
    2001           2 :     if (NS_SUCCEEDED(rv)) {
    2002           2 :         mAcceptLanguages.Assign(buf);
    2003             :     }
    2004           4 :     return rv;
    2005             : }
    2006             : 
    2007             : nsresult
    2008           2 : nsHttpHandler::SetAccept(const char *aAccept)
    2009             : {
    2010           2 :     mAccept = aAccept;
    2011           2 :     return NS_OK;
    2012             : }
    2013             : 
    2014             : nsresult
    2015           4 : nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings, bool isSecure)
    2016             : {
    2017           4 :     if (isSecure) {
    2018           2 :         mHttpsAcceptEncodings = aAcceptEncodings;
    2019             :     } else {
    2020             :         // use legacy list if a secure override is not specified
    2021           2 :         mHttpAcceptEncodings = aAcceptEncodings;
    2022           2 :         if (mHttpsAcceptEncodings.IsEmpty()) {
    2023           2 :             mHttpsAcceptEncodings = aAcceptEncodings;
    2024             :         }
    2025             :     }
    2026             : 
    2027           4 :     return NS_OK;
    2028             : }
    2029             : 
    2030             : //-----------------------------------------------------------------------------
    2031             : // nsHttpHandler::nsISupports
    2032             : //-----------------------------------------------------------------------------
    2033             : 
    2034        2725 : NS_IMPL_ISUPPORTS(nsHttpHandler,
    2035             :                   nsIHttpProtocolHandler,
    2036             :                   nsIProxiedProtocolHandler,
    2037             :                   nsIProtocolHandler,
    2038             :                   nsIObserver,
    2039             :                   nsISupportsWeakReference,
    2040             :                   nsISpeculativeConnect)
    2041             : 
    2042             : //-----------------------------------------------------------------------------
    2043             : // nsHttpHandler::nsIProtocolHandler
    2044             : //-----------------------------------------------------------------------------
    2045             : 
    2046             : NS_IMETHODIMP
    2047           0 : nsHttpHandler::GetScheme(nsACString &aScheme)
    2048             : {
    2049           0 :     aScheme.AssignLiteral("http");
    2050           0 :     return NS_OK;
    2051             : }
    2052             : 
    2053             : NS_IMETHODIMP
    2054           6 : nsHttpHandler::GetDefaultPort(int32_t *result)
    2055             : {
    2056           6 :     *result = NS_HTTP_DEFAULT_PORT;
    2057           6 :     return NS_OK;
    2058             : }
    2059             : 
    2060             : NS_IMETHODIMP
    2061         263 : nsHttpHandler::GetProtocolFlags(uint32_t *result)
    2062             : {
    2063         263 :     *result = NS_HTTP_PROTOCOL_FLAGS;
    2064         263 :     return NS_OK;
    2065             : }
    2066             : 
    2067             : NS_IMETHODIMP
    2068          62 : nsHttpHandler::NewURI(const nsACString &aSpec,
    2069             :                       const char *aCharset,
    2070             :                       nsIURI *aBaseURI,
    2071             :                       nsIURI **aURI)
    2072             : {
    2073          62 :     return mozilla::net::NewURI(aSpec, aCharset, aBaseURI, NS_HTTP_DEFAULT_PORT, aURI);
    2074             : }
    2075             : 
    2076             : NS_IMETHODIMP
    2077           0 : nsHttpHandler::NewChannel2(nsIURI* uri,
    2078             :                            nsILoadInfo* aLoadInfo,
    2079             :                            nsIChannel** result)
    2080             : {
    2081           0 :     LOG(("nsHttpHandler::NewChannel\n"));
    2082             : 
    2083           0 :     NS_ENSURE_ARG_POINTER(uri);
    2084           0 :     NS_ENSURE_ARG_POINTER(result);
    2085             : 
    2086           0 :     bool isHttp = false, isHttps = false;
    2087             : 
    2088             :     // Verify that we have been given a valid scheme
    2089           0 :     nsresult rv = uri->SchemeIs("http", &isHttp);
    2090           0 :     if (NS_FAILED(rv)) return rv;
    2091           0 :     if (!isHttp) {
    2092           0 :         rv = uri->SchemeIs("https", &isHttps);
    2093           0 :         if (NS_FAILED(rv)) return rv;
    2094           0 :         if (!isHttps) {
    2095           0 :             NS_WARNING("Invalid URI scheme");
    2096           0 :             return NS_ERROR_UNEXPECTED;
    2097             :         }
    2098             :     }
    2099             : 
    2100           0 :     return NewProxiedChannel2(uri, nullptr, 0, nullptr, aLoadInfo, result);
    2101             : }
    2102             : 
    2103             : NS_IMETHODIMP
    2104           0 : nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
    2105             : {
    2106           0 :     return NewChannel2(uri, nullptr, result);
    2107             : }
    2108             : 
    2109             : NS_IMETHODIMP
    2110           0 : nsHttpHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
    2111             : {
    2112             :     // don't override anything.
    2113           0 :     *_retval = false;
    2114           0 :     return NS_OK;
    2115             : }
    2116             : 
    2117             : //-----------------------------------------------------------------------------
    2118             : // nsHttpHandler::nsIProxiedProtocolHandler
    2119             : //-----------------------------------------------------------------------------
    2120             : 
    2121             : NS_IMETHODIMP
    2122          10 : nsHttpHandler::NewProxiedChannel2(nsIURI *uri,
    2123             :                                   nsIProxyInfo* givenProxyInfo,
    2124             :                                   uint32_t proxyResolveFlags,
    2125             :                                   nsIURI *proxyURI,
    2126             :                                   nsILoadInfo* aLoadInfo,
    2127             :                                   nsIChannel** result)
    2128             : {
    2129          20 :     RefPtr<HttpBaseChannel> httpChannel;
    2130             : 
    2131          10 :     LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
    2132             :         givenProxyInfo));
    2133             : 
    2134             : #ifdef MOZ_TASK_TRACER
    2135             :     if (tasktracer::IsStartLogging()) {
    2136             :         nsAutoCString urispec;
    2137             :         uri->GetSpec(urispec);
    2138             :         tasktracer::AddLabel("nsHttpHandler::NewProxiedChannel2 %s", urispec.get());
    2139             :     }
    2140             : #endif
    2141             : 
    2142          20 :     nsCOMPtr<nsProxyInfo> proxyInfo;
    2143          10 :     if (givenProxyInfo) {
    2144           0 :         proxyInfo = do_QueryInterface(givenProxyInfo);
    2145           0 :         NS_ENSURE_ARG(proxyInfo);
    2146             :     }
    2147             : 
    2148             :     bool https;
    2149          10 :     nsresult rv = uri->SchemeIs("https", &https);
    2150          10 :     if (NS_FAILED(rv))
    2151           0 :         return rv;
    2152             : 
    2153          10 :     if (IsNeckoChild()) {
    2154           3 :         httpChannel = new HttpChannelChild();
    2155             :     } else {
    2156           7 :         httpChannel = new nsHttpChannel();
    2157             :     }
    2158             : 
    2159          10 :     uint32_t caps = mCapabilities;
    2160             : 
    2161          10 :     if (!IsNeckoChild()) {
    2162             :         // HACK: make sure PSM gets initialized on the main thread.
    2163           7 :         net_EnsurePSMInit();
    2164             :     }
    2165             : 
    2166          10 :     if (XRE_IsParentProcess()) {
    2167             :         // Load UserAgentOverrides.jsm before any HTTP request is issued.
    2168           7 :         EnsureUAOverridesInit();
    2169             :     }
    2170             : 
    2171             :     uint64_t channelId;
    2172          10 :     rv = NewChannelId(channelId);
    2173          10 :     NS_ENSURE_SUCCESS(rv, rv);
    2174             : 
    2175          10 :     rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI, channelId);
    2176          10 :     if (NS_FAILED(rv))
    2177           0 :         return rv;
    2178             : 
    2179             :     // set the loadInfo on the new channel
    2180          10 :     rv = httpChannel->SetLoadInfo(aLoadInfo);
    2181          10 :     if (NS_FAILED(rv)) {
    2182           0 :         return rv;
    2183             :     }
    2184             : 
    2185          10 :     httpChannel.forget(result);
    2186          10 :     return NS_OK;
    2187             : }
    2188             : 
    2189             : NS_IMETHODIMP
    2190           0 : nsHttpHandler::NewProxiedChannel(nsIURI *uri,
    2191             :                                  nsIProxyInfo* givenProxyInfo,
    2192             :                                  uint32_t proxyResolveFlags,
    2193             :                                  nsIURI *proxyURI,
    2194             :                                  nsIChannel **result)
    2195             : {
    2196             :     return NewProxiedChannel2(uri, givenProxyInfo,
    2197             :                               proxyResolveFlags, proxyURI,
    2198           0 :                               nullptr, result);
    2199             : }
    2200             : 
    2201             : //-----------------------------------------------------------------------------
    2202             : // nsHttpHandler::nsIHttpProtocolHandler
    2203             : //-----------------------------------------------------------------------------
    2204             : 
    2205             : NS_IMETHODIMP
    2206           2 : nsHttpHandler::GetUserAgent(nsACString &value)
    2207             : {
    2208           2 :     value = UserAgent();
    2209           2 :     return NS_OK;
    2210             : }
    2211             : 
    2212             : NS_IMETHODIMP
    2213           0 : nsHttpHandler::GetAppName(nsACString &value)
    2214             : {
    2215           0 :     value = mLegacyAppName;
    2216           0 :     return NS_OK;
    2217             : }
    2218             : 
    2219             : NS_IMETHODIMP
    2220           1 : nsHttpHandler::GetAppVersion(nsACString &value)
    2221             : {
    2222           1 :     value = mLegacyAppVersion;
    2223           1 :     return NS_OK;
    2224             : }
    2225             : 
    2226             : NS_IMETHODIMP
    2227           1 : nsHttpHandler::GetPlatform(nsACString &value)
    2228             : {
    2229           1 :     value = mPlatform;
    2230           1 :     return NS_OK;
    2231             : }
    2232             : 
    2233             : NS_IMETHODIMP
    2234           1 : nsHttpHandler::GetOscpu(nsACString &value)
    2235             : {
    2236           1 :     value = mOscpu;
    2237           1 :     return NS_OK;
    2238             : }
    2239             : 
    2240             : NS_IMETHODIMP
    2241           0 : nsHttpHandler::GetMisc(nsACString &value)
    2242             : {
    2243           0 :     value = mMisc;
    2244           0 :     return NS_OK;
    2245             : }
    2246             : 
    2247             : //-----------------------------------------------------------------------------
    2248             : // nsHttpHandler::nsIObserver
    2249             : //-----------------------------------------------------------------------------
    2250             : 
    2251             : NS_IMETHODIMP
    2252           4 : nsHttpHandler::Observe(nsISupports *subject,
    2253             :                        const char *topic,
    2254             :                        const char16_t *data)
    2255             : {
    2256           4 :     MOZ_ASSERT(NS_IsMainThread());
    2257           4 :     LOG(("nsHttpHandler::Observe [topic=\"%s\"]\n", topic));
    2258             : 
    2259             :     nsresult rv;
    2260           4 :     if (!strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
    2261           0 :         nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
    2262           0 :         if (prefBranch)
    2263           0 :             PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
    2264           8 :     } else if (!strcmp(topic, "profile-change-net-teardown") ||
    2265           4 :                !strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) ) {
    2266             : 
    2267           0 :         mHandlerActive = false;
    2268             : 
    2269             :         // clear cache of all authentication credentials.
    2270           0 :         Unused << mAuthCache.ClearAll();
    2271           0 :         Unused << mPrivateAuthCache.ClearAll();
    2272           0 :         if (mWifiTickler)
    2273           0 :             mWifiTickler->Cancel();
    2274             : 
    2275             :         // Inform nsIOService that network is tearing down.
    2276           0 :         gIOService->SetHttpHandlerAlreadyShutingDown();
    2277             : 
    2278           0 :         ShutdownConnectionManager();
    2279             : 
    2280             :         // need to reset the session start time since cache validation may
    2281             :         // depend on this value.
    2282           0 :         mSessionStartTime = NowInSeconds();
    2283             : 
    2284           0 :         if (!mDoNotTrackEnabled) {
    2285           0 :             Telemetry::Accumulate(Telemetry::DNT_USAGE, 2);
    2286             :         } else {
    2287           0 :             Telemetry::Accumulate(Telemetry::DNT_USAGE, 1);
    2288             :         }
    2289           4 :     } else if (!strcmp(topic, "profile-change-net-restore")) {
    2290             :         // initialize connection manager
    2291           0 :         rv = InitConnectionMgr();
    2292           0 :         MOZ_ASSERT(NS_SUCCEEDED(rv));
    2293           4 :     } else if (!strcmp(topic, "net:clear-active-logins")) {
    2294           0 :         Unused << mAuthCache.ClearAll();
    2295           0 :         Unused << mPrivateAuthCache.ClearAll();
    2296           4 :     } else if (!strcmp(topic, "net:prune-dead-connections")) {
    2297           0 :         if (mConnMgr) {
    2298           0 :             rv = mConnMgr->PruneDeadConnections();
    2299           0 :             if (NS_FAILED(rv)) {
    2300           0 :                 LOG(("    PruneDeadConnections failed (%08x)\n",
    2301             :                      static_cast<uint32_t>(rv)));
    2302             :             }
    2303             :         }
    2304           4 :     } else if (!strcmp(topic, "net:prune-all-connections")) {
    2305           0 :         if (mConnMgr) {
    2306           0 :             rv = mConnMgr->DoShiftReloadConnectionCleanup(nullptr);
    2307           0 :             if (NS_FAILED(rv)) {
    2308           0 :                 LOG(("    DoShiftReloadConnectionCleanup failed (%08x)\n",
    2309             :                      static_cast<uint32_t>(rv)));
    2310             :             }
    2311           0 :             rv = mConnMgr->PruneDeadConnections();
    2312           0 :             if (NS_FAILED(rv)) {
    2313           0 :                 LOG(("    PruneDeadConnections failed (%08x)\n",
    2314             :                      static_cast<uint32_t>(rv)));
    2315             :             }
    2316             :         }
    2317             : #if 0
    2318             :     } else if (!strcmp(topic, "net:failed-to-process-uri-content")) {
    2319             :          // nop right now - we used to cancel h1 pipelines based on this,
    2320             :          // but those are no longer implemented
    2321             :          nsCOMPtr<nsIURI> uri = do_QueryInterface(subject);
    2322             : #endif
    2323           4 :     } else if (!strcmp(topic, "last-pb-context-exited")) {
    2324           0 :         Unused << mPrivateAuthCache.ClearAll();
    2325           0 :         if (mConnMgr) {
    2326           0 :             mConnMgr->ClearAltServiceMappings();
    2327             :         }
    2328           4 :     } else if (!strcmp(topic, "browser:purge-session-history")) {
    2329           0 :         if (mConnMgr) {
    2330           0 :             if (gSocketTransportService) {
    2331           0 :               nsCOMPtr<nsIRunnable> event = NewRunnableMethod(
    2332             :                 "net::nsHttpConnectionMgr::ClearConnectionHistory",
    2333             :                 mConnMgr,
    2334           0 :                 &nsHttpConnectionMgr::ClearConnectionHistory);
    2335           0 :               gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
    2336             :             }
    2337           0 :             mConnMgr->ClearAltServiceMappings();
    2338             :         }
    2339           4 :     } else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
    2340           0 :         nsAutoCString converted = NS_ConvertUTF16toUTF8(data);
    2341           0 :         if (!strcmp(converted.get(), NS_NETWORK_LINK_DATA_CHANGED)) {
    2342           0 :             if (mConnMgr) {
    2343           0 :                 rv = mConnMgr->PruneDeadConnections();
    2344           0 :                 if (NS_FAILED(rv)) {
    2345           0 :                     LOG(("    PruneDeadConnections failed (%08x)\n",
    2346             :                          static_cast<uint32_t>(rv)));
    2347             :                 }
    2348           0 :                 rv = mConnMgr->VerifyTraffic();
    2349           0 :                 if (NS_FAILED(rv)) {
    2350           0 :                     LOG(("    VerifyTraffic failed (%08x)\n",
    2351             :                          static_cast<uint32_t>(rv)));
    2352             :                 }
    2353             :             }
    2354             :         }
    2355           4 :     } else if (!strcmp(topic, "application-background")) {
    2356             :         // going to the background on android means we should close
    2357             :         // down idle connections for power conservation
    2358           0 :         if (mConnMgr) {
    2359           0 :             rv = mConnMgr->DoShiftReloadConnectionCleanup(nullptr);
    2360           0 :             if (NS_FAILED(rv)) {
    2361           0 :                 LOG(("    DoShiftReloadConnectionCleanup failed (%08x)\n",
    2362             :                      static_cast<uint32_t>(rv)));
    2363             :             }
    2364             :         }
    2365           4 :     } else if (!strcmp(topic, "net:current-toplevel-outer-content-windowid")) {
    2366           8 :         nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(subject);
    2367           4 :         MOZ_RELEASE_ASSERT(wrapper);
    2368             : 
    2369           4 :         uint64_t windowId = 0;
    2370           4 :         wrapper->GetData(&windowId);
    2371           4 :         MOZ_ASSERT(windowId);
    2372             : 
    2373           4 :         if (IsNeckoChild()) {
    2374           2 :             if (gNeckoChild) {
    2375           2 :                 gNeckoChild->SendNotifyCurrentTopLevelOuterContentWindowId(
    2376           2 :                     windowId);
    2377             :             }
    2378             :         } else {
    2379             :             static uint64_t sCurrentTopLevelOuterContentWindowId = 0;
    2380           2 :             if (sCurrentTopLevelOuterContentWindowId != windowId) {
    2381           1 :                 sCurrentTopLevelOuterContentWindowId = windowId;
    2382           1 :                 if (mConnMgr) {
    2383           1 :                     mConnMgr->UpdateCurrentTopLevelOuterContentWindowId(
    2384           2 :                         sCurrentTopLevelOuterContentWindowId);
    2385             :                 }
    2386             :             }
    2387             :         }
    2388           0 :     } else if (!strcmp(topic, "captive-portal-login") ||
    2389           0 :                !strcmp(topic, "captive-portal-login-success")) {
    2390             :          // We have detected a captive portal and we will reset the Fast Open
    2391             :          // failure counter.
    2392           0 :          ResetFastOpenConsecutiveFailureCounter();
    2393             :     }
    2394             : 
    2395           4 :     return NS_OK;
    2396             : }
    2397             : 
    2398             : // nsISpeculativeConnect
    2399             : 
    2400             : nsresult
    2401           0 : nsHttpHandler::SpeculativeConnectInternal(nsIURI *aURI,
    2402             :                                           nsIPrincipal *aPrincipal,
    2403             :                                           nsIInterfaceRequestor *aCallbacks,
    2404             :                                           bool anonymous)
    2405             : {
    2406           0 :     if (IsNeckoChild()) {
    2407           0 :         ipc::URIParams params;
    2408           0 :         SerializeURI(aURI, params);
    2409           0 :         gNeckoChild->SendSpeculativeConnect(params,
    2410           0 :                                             IPC::Principal(aPrincipal),
    2411           0 :                                             anonymous);
    2412           0 :         return NS_OK;
    2413             :     }
    2414             : 
    2415           0 :     if (!mHandlerActive)
    2416           0 :         return NS_OK;
    2417             : 
    2418           0 :     MOZ_ASSERT(NS_IsMainThread());
    2419           0 :     nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
    2420           0 :     if (mDebugObservations && obsService) {
    2421             :         // this is basically used for test coverage of an otherwise 'hintable'
    2422             :         // feature
    2423           0 :         obsService->NotifyObservers(nullptr, "speculative-connect-request",
    2424           0 :                                     nullptr);
    2425           0 :         for (auto* cp : dom::ContentParent::AllProcesses(dom::ContentParent::eLive)) {
    2426           0 :             PNeckoParent* neckoParent = SingleManagedOrNull(cp->ManagedPNeckoParent());
    2427           0 :             if (!neckoParent) {
    2428           0 :                 continue;
    2429             :             }
    2430           0 :             Unused << neckoParent->SendSpeculativeConnectRequest();
    2431             :         }
    2432             :     }
    2433             : 
    2434           0 :     nsISiteSecurityService* sss = gHttpHandler->GetSSService();
    2435           0 :     bool isStsHost = false;
    2436           0 :     if (!sss)
    2437           0 :         return NS_OK;
    2438             : 
    2439           0 :     nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(aCallbacks);
    2440           0 :     uint32_t flags = 0;
    2441           0 :     if (loadContext && loadContext->UsePrivateBrowsing())
    2442           0 :         flags |= nsISocketProvider::NO_PERMANENT_STORAGE;
    2443             : 
    2444           0 :     OriginAttributes originAttributes;
    2445             :     // If the principal is given, we use the originAttributes from this
    2446             :     // principal. Otherwise, we use the originAttributes from the
    2447             :     // loadContext.
    2448           0 :     if (aPrincipal) {
    2449           0 :         originAttributes = aPrincipal->OriginAttributesRef();
    2450           0 :     } else if (loadContext) {
    2451           0 :         loadContext->GetOriginAttributes(originAttributes);
    2452             :     }
    2453             : 
    2454           0 :     nsCOMPtr<nsIURI> clone;
    2455           0 :     if (NS_SUCCEEDED(sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS,
    2456             :                                       aURI, flags, originAttributes,
    2457           0 :                                       nullptr, nullptr, &isStsHost)) &&
    2458             :                                       isStsHost) {
    2459           0 :         if (NS_SUCCEEDED(NS_GetSecureUpgradedURI(aURI,
    2460             :                                                  getter_AddRefs(clone)))) {
    2461           0 :             aURI = clone.get();
    2462             :             // (NOTE: We better make sure |clone| stays alive until the end
    2463             :             // of the function now, since our aURI arg now points to it!)
    2464             :         }
    2465             :     }
    2466             : 
    2467           0 :     nsAutoCString scheme;
    2468           0 :     nsresult rv = aURI->GetScheme(scheme);
    2469           0 :     if (NS_FAILED(rv))
    2470           0 :         return rv;
    2471             : 
    2472             :     // If this is HTTPS, make sure PSM is initialized as the channel
    2473             :     // creation path may have been bypassed
    2474           0 :     if (scheme.EqualsLiteral("https")) {
    2475           0 :         if (!IsNeckoChild()) {
    2476             :             // make sure PSM gets initialized on the main thread.
    2477           0 :             net_EnsurePSMInit();
    2478             :         }
    2479             :     }
    2480             :     // Ensure that this is HTTP or HTTPS, otherwise we don't do preconnect here
    2481           0 :     else if (!scheme.EqualsLiteral("http"))
    2482           0 :         return NS_ERROR_UNEXPECTED;
    2483             : 
    2484             :     // Construct connection info object
    2485           0 :     bool usingSSL = false;
    2486           0 :     rv = aURI->SchemeIs("https", &usingSSL);
    2487           0 :     if (NS_FAILED(rv))
    2488           0 :         return rv;
    2489             : 
    2490           0 :     nsAutoCString host;
    2491           0 :     rv = aURI->GetAsciiHost(host);
    2492           0 :     if (NS_FAILED(rv))
    2493           0 :         return rv;
    2494             : 
    2495           0 :     int32_t port = -1;
    2496           0 :     rv = aURI->GetPort(&port);
    2497           0 :     if (NS_FAILED(rv))
    2498           0 :         return rv;
    2499             : 
    2500           0 :     nsAutoCString username;
    2501           0 :     aURI->GetUsername(username);
    2502             : 
    2503             :     auto *ci =
    2504           0 :         new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr,
    2505           0 :                                  originAttributes, usingSSL);
    2506           0 :     ci->SetAnonymous(anonymous);
    2507             : 
    2508           0 :     return SpeculativeConnect(ci, aCallbacks);
    2509             : }
    2510             : 
    2511             : NS_IMETHODIMP
    2512           0 : nsHttpHandler::SpeculativeConnect(nsIURI *aURI,
    2513             :                                   nsIInterfaceRequestor *aCallbacks)
    2514             : {
    2515           0 :     return SpeculativeConnectInternal(aURI, nullptr, aCallbacks, false);
    2516             : }
    2517             : 
    2518             : NS_IMETHODIMP
    2519           0 : nsHttpHandler::SpeculativeConnect2(nsIURI *aURI,
    2520             :                                    nsIPrincipal *aPrincipal,
    2521             :                                    nsIInterfaceRequestor *aCallbacks)
    2522             : {
    2523           0 :     return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, false);
    2524             : }
    2525             : 
    2526             : NS_IMETHODIMP
    2527           0 : nsHttpHandler::SpeculativeAnonymousConnect(nsIURI *aURI,
    2528             :                                            nsIInterfaceRequestor *aCallbacks)
    2529             : {
    2530           0 :     return SpeculativeConnectInternal(aURI, nullptr, aCallbacks, true);
    2531             : }
    2532             : 
    2533             : NS_IMETHODIMP
    2534           0 : nsHttpHandler::SpeculativeAnonymousConnect2(nsIURI *aURI,
    2535             :                                             nsIPrincipal *aPrincipal,
    2536             :                                             nsIInterfaceRequestor *aCallbacks)
    2537             : {
    2538           0 :     return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, true);
    2539             : }
    2540             : 
    2541             : void
    2542           5 : nsHttpHandler::TickleWifi(nsIInterfaceRequestor *cb)
    2543             : {
    2544           5 :     if (!cb || !mWifiTickler)
    2545          10 :         return;
    2546             : 
    2547             :     // If B2G requires a similar mechanism nsINetworkManager, currently only avail
    2548             :     // on B2G, contains the necessary information on wifi and gateway
    2549             : 
    2550           0 :     nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(cb);
    2551           0 :     nsCOMPtr<nsPIDOMWindowOuter> piWindow = do_QueryInterface(domWindow);
    2552           0 :     if (!piWindow)
    2553           0 :         return;
    2554             : 
    2555           0 :     nsCOMPtr<nsIDOMNavigator> domNavigator = piWindow->GetNavigator();
    2556             :     nsCOMPtr<nsIMozNavigatorNetwork> networkNavigator =
    2557           0 :         do_QueryInterface(domNavigator);
    2558           0 :     if (!networkNavigator)
    2559           0 :         return;
    2560             : 
    2561           0 :     nsCOMPtr<nsINetworkProperties> networkProperties;
    2562           0 :     networkNavigator->GetProperties(getter_AddRefs(networkProperties));
    2563           0 :     if (!networkProperties)
    2564           0 :         return;
    2565             : 
    2566             :     uint32_t gwAddress;
    2567             :     bool isWifi;
    2568             :     nsresult rv;
    2569             : 
    2570           0 :     rv = networkProperties->GetDhcpGateway(&gwAddress);
    2571           0 :     if (NS_SUCCEEDED(rv))
    2572           0 :         rv = networkProperties->GetIsWifi(&isWifi);
    2573           0 :     if (NS_FAILED(rv))
    2574           0 :         return;
    2575             : 
    2576           0 :     if (!gwAddress || !isWifi)
    2577           0 :         return;
    2578             : 
    2579           0 :     mWifiTickler->SetIPV4Address(gwAddress);
    2580           0 :     mWifiTickler->Tickle();
    2581             : }
    2582             : 
    2583             : //-----------------------------------------------------------------------------
    2584             : // nsHttpsHandler implementation
    2585             : //-----------------------------------------------------------------------------
    2586             : 
    2587        1473 : NS_IMPL_ISUPPORTS(nsHttpsHandler,
    2588             :                   nsIHttpProtocolHandler,
    2589             :                   nsIProxiedProtocolHandler,
    2590             :                   nsIProtocolHandler,
    2591             :                   nsISupportsWeakReference,
    2592             :                   nsISpeculativeConnect)
    2593             : 
    2594             : nsresult
    2595           1 : nsHttpsHandler::Init()
    2596             : {
    2597             :     nsCOMPtr<nsIProtocolHandler> httpHandler(
    2598           2 :             do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http"));
    2599           1 :     MOZ_ASSERT(httpHandler.get() != nullptr);
    2600           2 :     return NS_OK;
    2601             : }
    2602             : 
    2603             : NS_IMETHODIMP
    2604           0 : nsHttpsHandler::GetScheme(nsACString &aScheme)
    2605             : {
    2606           0 :     aScheme.AssignLiteral("https");
    2607           0 :     return NS_OK;
    2608             : }
    2609             : 
    2610             : NS_IMETHODIMP
    2611           0 : nsHttpsHandler::GetDefaultPort(int32_t *aPort)
    2612             : {
    2613           0 :     *aPort = NS_HTTPS_DEFAULT_PORT;
    2614           0 :     return NS_OK;
    2615             : }
    2616             : 
    2617             : NS_IMETHODIMP
    2618         150 : nsHttpsHandler::GetProtocolFlags(uint32_t *aProtocolFlags)
    2619             : {
    2620         150 :     *aProtocolFlags = NS_HTTP_PROTOCOL_FLAGS | URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
    2621         150 :     return NS_OK;
    2622             : }
    2623             : 
    2624             : NS_IMETHODIMP
    2625          68 : nsHttpsHandler::NewURI(const nsACString &aSpec,
    2626             :                        const char *aOriginCharset,
    2627             :                        nsIURI *aBaseURI,
    2628             :                        nsIURI **_retval)
    2629             : {
    2630          68 :     return mozilla::net::NewURI(aSpec, aOriginCharset, aBaseURI, NS_HTTPS_DEFAULT_PORT, _retval);
    2631             : }
    2632             : 
    2633             : NS_IMETHODIMP
    2634           0 : nsHttpsHandler::NewChannel2(nsIURI* aURI,
    2635             :                             nsILoadInfo* aLoadInfo,
    2636             :                             nsIChannel** _retval)
    2637             : {
    2638           0 :     MOZ_ASSERT(gHttpHandler);
    2639           0 :     if (!gHttpHandler)
    2640           0 :       return NS_ERROR_UNEXPECTED;
    2641           0 :     return gHttpHandler->NewChannel2(aURI, aLoadInfo, _retval);
    2642             : }
    2643             : 
    2644             : NS_IMETHODIMP
    2645           0 : nsHttpsHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
    2646             : {
    2647           0 :     return NewChannel2(aURI, nullptr, _retval);
    2648             : }
    2649             : 
    2650             : NS_IMETHODIMP
    2651           0 : nsHttpsHandler::AllowPort(int32_t aPort, const char *aScheme, bool *_retval)
    2652             : {
    2653             :     // don't override anything.
    2654           0 :     *_retval = false;
    2655           0 :     return NS_OK;
    2656             : }
    2657             : 
    2658             : void
    2659           0 : nsHttpHandler::ShutdownConnectionManager()
    2660             : {
    2661             :     // ensure connection manager is shutdown
    2662           0 :     if (mConnMgr) {
    2663           0 :         nsresult rv = mConnMgr->Shutdown();
    2664           0 :         if (NS_FAILED(rv)) {
    2665           0 :             LOG(("nsHttpHandler::ShutdownConnectionManager\n"
    2666             :                  "    failed to shutdown connection manager\n"));
    2667             :         }
    2668             :     }
    2669           0 : }
    2670             : 
    2671             : nsresult
    2672          10 : nsHttpHandler::NewChannelId(uint64_t& channelId)
    2673             : {
    2674          10 :   MOZ_ASSERT(NS_IsMainThread());
    2675          10 :   channelId = ((static_cast<uint64_t>(mProcessId) << 32) & 0xFFFFFFFF00000000LL) | mNextChannelId++;
    2676          10 :   return NS_OK;
    2677             : }
    2678             : 
    2679             : } // namespace net
    2680             : } // namespace mozilla

Generated by: LCOV version 1.13