forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			2443 lines
		
	
	
	
		
			79 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			2443 lines
		
	
	
	
		
			79 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 | |
| /* vim:set ts=4 sw=4 sts=4 et cin: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| // HttpLog.h should generally be included first
 | |
| #include "HttpLog.h"
 | |
| 
 | |
| #include "nsHttp.h"
 | |
| #include "nsHttpHandler.h"
 | |
| #include "nsHttpChannel.h"
 | |
| #include "nsHttpAuthCache.h"
 | |
| #include "nsStandardURL.h"
 | |
| #include "nsIDOMWindow.h"
 | |
| #include "nsIDOMNavigator.h"
 | |
| #include "nsIMozNavigatorNetwork.h"
 | |
| #include "nsINetworkProperties.h"
 | |
| #include "nsIHttpChannel.h"
 | |
| #include "nsIStandardURL.h"
 | |
| #include "LoadContextInfo.h"
 | |
| #include "nsCategoryManagerUtils.h"
 | |
| #include "nsIPrefService.h"
 | |
| #include "nsIPrefBranch.h"
 | |
| #include "nsIPrefLocalizedString.h"
 | |
| #include "nsISocketProviderService.h"
 | |
| #include "nsISocketProvider.h"
 | |
| #include "nsPrintfCString.h"
 | |
| #include "nsCOMPtr.h"
 | |
| #include "nsNetCID.h"
 | |
| #include "prprf.h"
 | |
| #include "mozilla/Snprintf.h"
 | |
| #include "nsAsyncRedirectVerifyHelper.h"
 | |
| #include "nsSocketTransportService2.h"
 | |
| #include "nsAlgorithm.h"
 | |
| #include "ASpdySession.h"
 | |
| #include "mozIApplicationClearPrivateDataParams.h"
 | |
| #include "EventTokenBucket.h"
 | |
| #include "Tickler.h"
 | |
| #include "nsIXULAppInfo.h"
 | |
| #include "nsICookieService.h"
 | |
| #include "nsIObserverService.h"
 | |
| #include "nsISiteSecurityService.h"
 | |
| #include "nsIStreamConverterService.h"
 | |
| #include "nsITimer.h"
 | |
| #include "nsCRT.h"
 | |
| #include "SpdyZlibReporter.h"
 | |
| #include "nsIMemoryReporter.h"
 | |
| #include "nsIParentalControlsService.h"
 | |
| #include "nsPIDOMWindow.h"
 | |
| #include "nsINetworkLinkService.h"
 | |
| #include "nsHttpChannelAuthProvider.h"
 | |
| #include "nsServiceManagerUtils.h"
 | |
| #include "nsComponentManagerUtils.h"
 | |
| #include "nsSocketTransportService2.h"
 | |
| #include "nsIOService.h"
 | |
| 
 | |
| #include "mozilla/net/NeckoChild.h"
 | |
| #include "mozilla/net/NeckoParent.h"
 | |
| #include "mozilla/ipc/URIUtils.h"
 | |
| #include "mozilla/Telemetry.h"
 | |
| #include "mozilla/unused.h"
 | |
| 
 | |
| #if defined(XP_UNIX)
 | |
| #include <sys/utsname.h>
 | |
| #endif
 | |
| 
 | |
| #if defined(XP_WIN)
 | |
| #include <windows.h>
 | |
| #endif
 | |
| 
 | |
| #if defined(XP_MACOSX)
 | |
| #include <CoreServices/CoreServices.h>
 | |
| #include "nsCocoaFeatures.h"
 | |
| #endif
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| #include "mozilla/net/HttpChannelChild.h"
 | |
| 
 | |
| 
 | |
| #define UA_PREF_PREFIX          "general.useragent."
 | |
| #ifdef XP_WIN
 | |
| #define UA_SPARE_PLATFORM
 | |
| #endif
 | |
| 
 | |
| #define HTTP_PREF_PREFIX        "network.http."
 | |
| #define INTL_ACCEPT_LANGUAGES   "intl.accept_languages"
 | |
| #define BROWSER_PREF_PREFIX     "browser.cache."
 | |
| #define DONOTTRACK_HEADER_ENABLED "privacy.donottrackheader.enabled"
 | |
| #define H2MANDATORY_SUITE        "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256"
 | |
| #define TELEMETRY_ENABLED        "toolkit.telemetry.enabled"
 | |
| #define ALLOW_EXPERIMENTS        "network.allow-experiments"
 | |
| #define SAFE_HINT_HEADER_VALUE   "safeHint.enabled"
 | |
| #define SECURITY_PREFIX          "security."
 | |
| #define NEW_TAB_REMOTE_MODE           "browser.newtabpage.remote.mode"
 | |
| 
 | |
| #define UA_PREF(_pref) UA_PREF_PREFIX _pref
 | |
| #define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
 | |
| #define BROWSER_PREF(_pref) BROWSER_PREF_PREFIX _pref
 | |
| 
 | |
| #define NS_HTTP_PROTOCOL_FLAGS (URI_STD | ALLOWS_PROXY | ALLOWS_PROXY_HTTP | URI_LOADABLE_BY_ANYONE)
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace net {
 | |
| 
 | |
| LazyLogModule gHttpLog("nsHttp");
 | |
| 
 | |
| static nsresult
 | |
| NewURI(const nsACString &aSpec,
 | |
|        const char *aCharset,
 | |
|        nsIURI *aBaseURI,
 | |
|        int32_t aDefaultPort,
 | |
|        nsIURI **aURI)
 | |
| {
 | |
|     RefPtr<nsStandardURL> url = new nsStandardURL();
 | |
| 
 | |
|     nsresult rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY,
 | |
|                             aDefaultPort, aSpec, aCharset, aBaseURI);
 | |
|     if (NS_FAILED(rv)) {
 | |
|         return rv;
 | |
|     }
 | |
| 
 | |
|     url.forget(aURI);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| #ifdef ANDROID
 | |
| static nsCString
 | |
| GetDeviceModelId() {
 | |
|     // Assumed to be running on the main thread
 | |
|     // We need the device property in either case
 | |
|     nsAutoCString deviceModelId;
 | |
|     nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
 | |
|     MOZ_ASSERT(infoService, "Could not find a system info service");
 | |
|     nsAutoString androidDevice;
 | |
|     nsresult rv = infoService->GetPropertyAsAString(NS_LITERAL_STRING("device"), androidDevice);
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|         deviceModelId = NS_LossyConvertUTF16toASCII(androidDevice);
 | |
|     }
 | |
|     nsAutoCString deviceString;
 | |
|     rv = Preferences::GetCString(UA_PREF("device_string"), &deviceString);
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|         deviceString.Trim(" ", true, true);
 | |
|         deviceString.ReplaceSubstring(NS_LITERAL_CSTRING("%DEVICEID%"), deviceModelId);
 | |
|         return deviceString;
 | |
|     }
 | |
|     return deviceModelId;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // nsHttpHandler <public>
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| nsHttpHandler *gHttpHandler = nullptr;
 | |
| 
 | |
| nsHttpHandler::nsHttpHandler()
 | |
|     : mHttpVersion(NS_HTTP_VERSION_1_1)
 | |
|     , mProxyHttpVersion(NS_HTTP_VERSION_1_1)
 | |
|     , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
 | |
|     , mReferrerLevel(0xff) // by default we always send a referrer
 | |
|     , mSpoofReferrerSource(false)
 | |
|     , mReferrerTrimmingPolicy(0)
 | |
|     , mReferrerXOriginPolicy(0)
 | |
|     , mFastFallbackToIPv4(false)
 | |
|     , mProxyPipelining(true)
 | |
|     , mIdleTimeout(PR_SecondsToInterval(10))
 | |
|     , mSpdyTimeout(PR_SecondsToInterval(180))
 | |
|     , mResponseTimeout(PR_SecondsToInterval(300))
 | |
|     , mResponseTimeoutEnabled(false)
 | |
|     , mNetworkChangedTimeout(5000)
 | |
|     , mMaxRequestAttempts(6)
 | |
|     , mMaxRequestDelay(10)
 | |
|     , mIdleSynTimeout(250)
 | |
|     , mH2MandatorySuiteEnabled(false)
 | |
|     , mPipeliningEnabled(false)
 | |
|     , mMaxConnections(24)
 | |
|     , mMaxPersistentConnectionsPerServer(2)
 | |
|     , mMaxPersistentConnectionsPerProxy(4)
 | |
|     , mMaxPipelinedRequests(32)
 | |
|     , mMaxOptimisticPipelinedRequests(4)
 | |
|     , mPipelineAggressive(false)
 | |
|     , mMaxPipelineObjectSize(300000)
 | |
|     , mPipelineRescheduleOnTimeout(true)
 | |
|     , mPipelineRescheduleTimeout(PR_MillisecondsToInterval(1500))
 | |
|     , mPipelineReadTimeout(PR_MillisecondsToInterval(30000))
 | |
|     , mRedirectionLimit(10)
 | |
|     , mPhishyUserPassLength(1)
 | |
|     , mQoSBits(0x00)
 | |
|     , mPipeliningOverSSL(false)
 | |
|     , mEnforceAssocReq(false)
 | |
|     , mLastUniqueID(NowInSeconds())
 | |
|     , mSessionStartTime(0)
 | |
|     , mLegacyAppName("Mozilla")
 | |
|     , mLegacyAppVersion("5.0")
 | |
|     , mProduct("Gecko")
 | |
|     , mCompatFirefoxEnabled(false)
 | |
|     , mUserAgentIsDirty(true)
 | |
|     , mPromptTempRedirect(true)
 | |
|     , mSendSecureXSiteReferrer(true)
 | |
|     , mEnablePersistentHttpsCaching(false)
 | |
|     , mDoNotTrackEnabled(false)
 | |
|     , mSafeHintEnabled(false)
 | |
|     , mParentalControlEnabled(false)
 | |
|     , mHandlerActive(false)
 | |
|     , mTelemetryEnabled(false)
 | |
|     , mAllowExperiments(true)
 | |
|     , mDebugObservations(false)
 | |
|     , mEnableSpdy(false)
 | |
|     , mSpdyV31(true)
 | |
|     , mHttp2Enabled(true)
 | |
|     , mUseH2Deps(true)
 | |
|     , mEnforceHttp2TlsProfile(true)
 | |
|     , mCoalesceSpdy(true)
 | |
|     , mSpdyPersistentSettings(false)
 | |
|     , mAllowPush(true)
 | |
|     , mEnableAltSvc(false)
 | |
|     , mEnableAltSvcOE(false)
 | |
|     , mSpdySendingChunkSize(ASpdySession::kSendingChunkSize)
 | |
|     , mSpdySendBufferSize(ASpdySession::kTCPSendBufferSize)
 | |
|     , mSpdyPushAllowance(32768)
 | |
|     , mSpdyPullAllowance(ASpdySession::kInitialRwin)
 | |
|     , mDefaultSpdyConcurrent(ASpdySession::kDefaultMaxConcurrent)
 | |
|     , mSpdyPingThreshold(PR_SecondsToInterval(58))
 | |
|     , mSpdyPingTimeout(PR_SecondsToInterval(8))
 | |
|     , mConnectTimeout(90000)
 | |
|     , mParallelSpeculativeConnectLimit(6)
 | |
|     , mRequestTokenBucketEnabled(true)
 | |
|     , mRequestTokenBucketMinParallelism(6)
 | |
|     , mRequestTokenBucketHz(100)
 | |
|     , mRequestTokenBucketBurst(32)
 | |
|     , mCriticalRequestPrioritization(true)
 | |
|     , mTCPKeepaliveShortLivedEnabled(false)
 | |
|     , mTCPKeepaliveShortLivedTimeS(60)
 | |
|     , mTCPKeepaliveShortLivedIdleTimeS(10)
 | |
|     , mTCPKeepaliveLongLivedEnabled(false)
 | |
|     , mTCPKeepaliveLongLivedIdleTimeS(600)
 | |
|     , mEnforceH1Framing(FRAMECHECK_BARELY)
 | |
|     , mKeepEmptyResponseHeadersAsEmtpyString(false)
 | |
| {
 | |
|     LOG(("Creating nsHttpHandler [this=%p].\n", this));
 | |
| 
 | |
|     RegisterStrongMemoryReporter(new SpdyZlibReporter());
 | |
| 
 | |
|     MOZ_ASSERT(!gHttpHandler, "HTTP handler already created!");
 | |
|     gHttpHandler = this;
 | |
| }
 | |
| 
 | |
| nsHttpHandler::~nsHttpHandler()
 | |
| {
 | |
|     LOG(("Deleting nsHttpHandler [this=%p]\n", this));
 | |
| 
 | |
|     // make sure the connection manager is shutdown
 | |
|     if (mConnMgr) {
 | |
|         mConnMgr->Shutdown();
 | |
|         mConnMgr = nullptr;
 | |
|     }
 | |
| 
 | |
|     // Note: don't call NeckoChild::DestroyNeckoChild() here, as it's too late
 | |
|     // and it'll segfault.  NeckoChild will get cleaned up by process exit.
 | |
| 
 | |
|     nsHttp::DestroyAtomTable();
 | |
|     if (mPipelineTestTimer) {
 | |
|         mPipelineTestTimer->Cancel();
 | |
|         mPipelineTestTimer = nullptr;
 | |
|     }
 | |
| 
 | |
|     gHttpHandler = nullptr;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::Init()
 | |
| {
 | |
|     nsresult rv;
 | |
| 
 | |
|     LOG(("nsHttpHandler::Init\n"));
 | |
|     MOZ_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|     rv = nsHttp::CreateAtomTable();
 | |
|     if (NS_FAILED(rv))
 | |
|         return rv;
 | |
| 
 | |
|     nsCOMPtr<nsIIOService> service = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
 | |
|     if (NS_FAILED(rv)) {
 | |
|         NS_WARNING("unable to continue without io service");
 | |
|         return rv;
 | |
|     }
 | |
|     mIOService = new nsMainThreadPtrHolder<nsIIOService>(service);
 | |
| 
 | |
|     if (IsNeckoChild())
 | |
|         NeckoChild::InitNeckoChild();
 | |
| 
 | |
|     InitUserAgentComponents();
 | |
| 
 | |
|     // monitor some preference changes
 | |
|     nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
 | |
|     if (prefBranch) {
 | |
|         prefBranch->AddObserver(HTTP_PREF_PREFIX, this, true);
 | |
|         prefBranch->AddObserver(UA_PREF_PREFIX, this, true);
 | |
|         prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, true);
 | |
|         prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true);
 | |
|         prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true);
 | |
|         prefBranch->AddObserver(TELEMETRY_ENABLED, this, true);
 | |
|         prefBranch->AddObserver(H2MANDATORY_SUITE, this, true);
 | |
|         prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.short_lived_connections"), this, true);
 | |
|         prefBranch->AddObserver(HTTP_PREF("tcp_keepalive.long_lived_connections"), this, true);
 | |
|         prefBranch->AddObserver(SAFE_HINT_HEADER_VALUE, this, true);
 | |
|         prefBranch->AddObserver(SECURITY_PREFIX, this, true);
 | |
|         prefBranch->AddObserver(NEW_TAB_REMOTE_MODE, this, true);
 | |
|         PrefsChanged(prefBranch, nullptr);
 | |
|     }
 | |
| 
 | |
|     rv = Preferences::AddBoolVarCache(&mPackagedAppsEnabled,
 | |
|         "network.http.enable-packaged-apps", false);
 | |
|     if (NS_FAILED(rv)) {
 | |
|         mPackagedAppsEnabled = false;
 | |
|     }
 | |
| 
 | |
|     nsHttpChannelAuthProvider::InitializePrefs();
 | |
| 
 | |
|     mMisc.AssignLiteral("rv:" MOZILLA_UAVERSION);
 | |
| 
 | |
|     mCompatFirefox.AssignLiteral("Firefox/" MOZILLA_UAVERSION);
 | |
| 
 | |
|     nsCOMPtr<nsIXULAppInfo> appInfo =
 | |
|         do_GetService("@mozilla.org/xre/app-info;1");
 | |
| 
 | |
|     mAppName.AssignLiteral(MOZ_APP_UA_NAME);
 | |
|     if (mAppName.Length() == 0 && appInfo) {
 | |
|         // Try to get the UA name from appInfo, falling back to the name
 | |
|         appInfo->GetUAName(mAppName);
 | |
|         if (mAppName.Length() == 0) {
 | |
|           appInfo->GetName(mAppName);
 | |
|         }
 | |
|         appInfo->GetVersion(mAppVersion);
 | |
|         mAppName.StripChars(" ()<>@,;:\\\"/[]?={}");
 | |
|     } else {
 | |
|         mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION);
 | |
|     }
 | |
| 
 | |
|     mSessionStartTime = NowInSeconds();
 | |
|     mHandlerActive = true;
 | |
| 
 | |
|     rv = mAuthCache.Init();
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     rv = mPrivateAuthCache.Init();
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     rv = InitConnectionMgr();
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     mRequestContextService =
 | |
|         do_GetService("@mozilla.org/network/request-context-service;1");
 | |
| 
 | |
| #if defined(ANDROID) || defined(MOZ_MULET)
 | |
|     mProductSub.AssignLiteral(MOZILLA_UAVERSION);
 | |
| #else
 | |
|     mProductSub.AssignLiteral("20100101");
 | |
| #endif
 | |
| 
 | |
| #if DEBUG
 | |
|     // dump user agent prefs
 | |
|     LOG(("> legacy-app-name = %s\n", mLegacyAppName.get()));
 | |
|     LOG(("> legacy-app-version = %s\n", mLegacyAppVersion.get()));
 | |
|     LOG(("> platform = %s\n", mPlatform.get()));
 | |
|     LOG(("> oscpu = %s\n", mOscpu.get()));
 | |
|     LOG(("> misc = %s\n", mMisc.get()));
 | |
|     LOG(("> product = %s\n", mProduct.get()));
 | |
|     LOG(("> product-sub = %s\n", mProductSub.get()));
 | |
|     LOG(("> app-name = %s\n", mAppName.get()));
 | |
|     LOG(("> app-version = %s\n", mAppVersion.get()));
 | |
|     LOG(("> compat-firefox = %s\n", mCompatFirefox.get()));
 | |
|     LOG(("> user-agent = %s\n", UserAgent().get()));
 | |
| #endif
 | |
| 
 | |
|     // Startup the http category
 | |
|     // Bring alive the objects in the http-protocol-startup category
 | |
|     NS_CreateServicesFromCategory(NS_HTTP_STARTUP_CATEGORY,
 | |
|                                   static_cast<nsISupports*>(static_cast<void*>(this)),
 | |
|                                   NS_HTTP_STARTUP_TOPIC);
 | |
| 
 | |
|     nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
 | |
|     if (obsService) {
 | |
|         // register the handler object as a weak callback as we don't need to worry
 | |
|         // about shutdown ordering.
 | |
|         obsService->AddObserver(this, "profile-change-net-teardown", true);
 | |
|         obsService->AddObserver(this, "profile-change-net-restore", true);
 | |
|         obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
 | |
|         obsService->AddObserver(this, "net:clear-active-logins", true);
 | |
|         obsService->AddObserver(this, "net:prune-dead-connections", true);
 | |
|         // Sent by the TorButton add-on in the Tor Browser
 | |
|         obsService->AddObserver(this, "net:prune-all-connections", true);
 | |
|         obsService->AddObserver(this, "net:failed-to-process-uri-content", true);
 | |
|         obsService->AddObserver(this, "last-pb-context-exited", true);
 | |
|         obsService->AddObserver(this, "webapps-clear-data", true);
 | |
|         obsService->AddObserver(this, "browser:purge-session-history", true);
 | |
|         obsService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true);
 | |
|         obsService->AddObserver(this, "application-background", true);
 | |
|     }
 | |
| 
 | |
|     MakeNewRequestTokenBucket();
 | |
|     mWifiTickler = new Tickler();
 | |
|     if (NS_FAILED(mWifiTickler->Init()))
 | |
|         mWifiTickler = nullptr;
 | |
| 
 | |
|     nsCOMPtr<nsIParentalControlsService> pc = do_CreateInstance("@mozilla.org/parental-controls-service;1");
 | |
|     if (pc) {
 | |
|         pc->GetParentalControlsEnabled(&mParentalControlEnabled);
 | |
|     }
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| void
 | |
| nsHttpHandler::MakeNewRequestTokenBucket()
 | |
| {
 | |
|     LOG(("nsHttpHandler::MakeNewRequestTokenBucket this=%p child=%d\n",
 | |
|          this, IsNeckoChild()));
 | |
|     if (!mConnMgr || IsNeckoChild()) {
 | |
|         return;
 | |
|     }
 | |
|     RefPtr<EventTokenBucket> tokenBucket =
 | |
|         new EventTokenBucket(RequestTokenBucketHz(), RequestTokenBucketBurst());
 | |
|     mConnMgr->UpdateRequestTokenBucket(tokenBucket);
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::InitConnectionMgr()
 | |
| {
 | |
|     // Init ConnectionManager only on parent!
 | |
|     if (IsNeckoChild()) {
 | |
|         return NS_OK;
 | |
|     }
 | |
| 
 | |
|     nsresult rv;
 | |
| 
 | |
|     if (!mConnMgr) {
 | |
|         mConnMgr = new nsHttpConnectionMgr();
 | |
|     }
 | |
| 
 | |
|     rv = mConnMgr->Init(mMaxConnections,
 | |
|                         mMaxPersistentConnectionsPerServer,
 | |
|                         mMaxPersistentConnectionsPerProxy,
 | |
|                         mMaxRequestDelay,
 | |
|                         mMaxPipelinedRequests,
 | |
|                         mMaxOptimisticPipelinedRequests);
 | |
|     return rv;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::AddStandardRequestHeaders(nsHttpRequestHead *request, bool isSecure)
 | |
| {
 | |
|     nsresult rv;
 | |
| 
 | |
|     // Add the "User-Agent" header
 | |
|     rv = request->SetHeader(nsHttp::User_Agent, UserAgent(),
 | |
|                             false, nsHttpHeaderArray::eVarietyRequestDefault);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     // MIME based content negotiation lives!
 | |
|     // Add the "Accept" header.  Note, this is set as an override because the
 | |
|     // service worker expects to see it.  The other "default" headers are
 | |
|     // hidden from service worker interception.
 | |
|     rv = request->SetHeader(nsHttp::Accept, mAccept,
 | |
|                             false, nsHttpHeaderArray::eVarietyRequestOverride);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     // Add the "Accept-Language" header.  This header is also exposed to the
 | |
|     // service worker.
 | |
|     if (!mAcceptLanguages.IsEmpty()) {
 | |
|         // Add the "Accept-Language" header
 | |
|         rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages,
 | |
|                                 false,
 | |
|                                 nsHttpHeaderArray::eVarietyRequestOverride);
 | |
|         if (NS_FAILED(rv)) return rv;
 | |
|     }
 | |
| 
 | |
|     // Add the "Accept-Encoding" header
 | |
|     if (isSecure) {
 | |
|         rv = request->SetHeader(nsHttp::Accept_Encoding, mHttpsAcceptEncodings,
 | |
|                                 false,
 | |
|                                 nsHttpHeaderArray::eVarietyRequestDefault);
 | |
|     } else {
 | |
|         rv = request->SetHeader(nsHttp::Accept_Encoding, mHttpAcceptEncodings,
 | |
|                                 false,
 | |
|                                 nsHttpHeaderArray::eVarietyRequestDefault);
 | |
|     }
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
| 
 | |
|     // Add the "Do-Not-Track" header
 | |
|     if (mDoNotTrackEnabled) {
 | |
|       rv = request->SetHeader(nsHttp::DoNotTrack, NS_LITERAL_CSTRING("1"),
 | |
|                               false,
 | |
|                               nsHttpHeaderArray::eVarietyRequestDefault);
 | |
|       if (NS_FAILED(rv)) return rv;
 | |
|     }
 | |
| 
 | |
|     // add the "Send Hint" header
 | |
|     if (mSafeHintEnabled || mParentalControlEnabled) {
 | |
|       rv = request->SetHeader(nsHttp::Prefer, NS_LITERAL_CSTRING("safe"),
 | |
|                               false,
 | |
|                               nsHttpHeaderArray::eVarietyRequestDefault);
 | |
|       if (NS_FAILED(rv)) return rv;
 | |
|     }
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::AddConnectionHeader(nsHttpRequestHead *request,
 | |
|                                    uint32_t caps)
 | |
| {
 | |
|     // RFC2616 section 19.6.2 states that the "Connection: keep-alive"
 | |
|     // and "Keep-alive" request headers should not be sent by HTTP/1.1
 | |
|     // user-agents.  But this is not a problem in practice, and the
 | |
|     // alternative proxy-connection is worse. see 570283
 | |
| 
 | |
|     NS_NAMED_LITERAL_CSTRING(close, "close");
 | |
|     NS_NAMED_LITERAL_CSTRING(keepAlive, "keep-alive");
 | |
| 
 | |
|     const nsACString *connectionType = &close;
 | |
|     if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
 | |
|         connectionType = &keepAlive;
 | |
|     }
 | |
| 
 | |
|     return request->SetHeader(nsHttp::Connection, *connectionType);
 | |
| }
 | |
| 
 | |
| bool
 | |
| nsHttpHandler::IsAcceptableEncoding(const char *enc, bool isSecure)
 | |
| {
 | |
|     if (!enc)
 | |
|         return false;
 | |
| 
 | |
|     // we used to accept x-foo anytime foo was acceptable, but that's just
 | |
|     // continuing bad behavior.. so limit it to known x-* patterns
 | |
|     bool rv;
 | |
|     if (isSecure) {
 | |
|         rv = nsHttp::FindToken(mHttpsAcceptEncodings.get(), enc, HTTP_LWS ",") != nullptr;
 | |
|     } else {
 | |
|         rv = nsHttp::FindToken(mHttpAcceptEncodings.get(), enc, HTTP_LWS ",") != nullptr;
 | |
|     }
 | |
|     // gzip and deflate are inherently acceptable in modern HTTP - always
 | |
|     // process them if a stream converter can also be found.
 | |
|     if (!rv &&
 | |
|         (!PL_strcasecmp(enc, "gzip") || !PL_strcasecmp(enc, "deflate") ||
 | |
|          !PL_strcasecmp(enc, "x-gzip") || !PL_strcasecmp(enc, "x-deflate"))) {
 | |
|         rv = true;
 | |
|     }
 | |
|     LOG(("nsHttpHandler::IsAceptableEncoding %s https=%d %d\n",
 | |
|          enc, isSecure, rv));
 | |
|     return rv;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
 | |
| {
 | |
|     if (!mStreamConvSvc) {
 | |
|         nsresult rv;
 | |
|         nsCOMPtr<nsIStreamConverterService> service =
 | |
|             do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
 | |
|         if (NS_FAILED(rv))
 | |
|             return rv;
 | |
|         mStreamConvSvc = new nsMainThreadPtrHolder<nsIStreamConverterService>(service);
 | |
|     }
 | |
|     *result = mStreamConvSvc;
 | |
|     NS_ADDREF(*result);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| nsISiteSecurityService*
 | |
| nsHttpHandler::GetSSService()
 | |
| {
 | |
|     if (!mSSService) {
 | |
|         nsCOMPtr<nsISiteSecurityService> service = do_GetService(NS_SSSERVICE_CONTRACTID);
 | |
|         mSSService = new nsMainThreadPtrHolder<nsISiteSecurityService>(service);
 | |
|     }
 | |
|     return mSSService;
 | |
| }
 | |
| 
 | |
| nsICookieService *
 | |
| nsHttpHandler::GetCookieService()
 | |
| {
 | |
|     if (!mCookieService) {
 | |
|         nsCOMPtr<nsICookieService> service = do_GetService(NS_COOKIESERVICE_CONTRACTID);
 | |
|         mCookieService = new nsMainThreadPtrHolder<nsICookieService>(service);
 | |
|     }
 | |
|     return mCookieService;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::GetIOService(nsIIOService** result)
 | |
| {
 | |
|     NS_ENSURE_ARG_POINTER(result);
 | |
| 
 | |
|     NS_ADDREF(*result = mIOService);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| uint32_t
 | |
| nsHttpHandler::Get32BitsOfPseudoRandom()
 | |
| {
 | |
|     // only confirm rand seeding on socket thread
 | |
|     MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
 | |
| 
 | |
|     // rand() provides different amounts of PRNG on different platforms.
 | |
|     // 15 or 31 bits are common amounts.
 | |
| 
 | |
|     PR_STATIC_ASSERT(RAND_MAX >= 0xfff);
 | |
| 
 | |
| #if RAND_MAX < 0xffffU
 | |
|     return ((uint16_t) rand() << 20) |
 | |
|             (((uint16_t) rand() & 0xfff) << 8) |
 | |
|             ((uint16_t) rand() & 0xff);
 | |
| #elif RAND_MAX < 0xffffffffU
 | |
|     return ((uint16_t) rand() << 16) | ((uint16_t) rand() & 0xffff);
 | |
| #else
 | |
|     return (uint32_t) rand();
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void
 | |
| nsHttpHandler::NotifyObservers(nsIHttpChannel *chan, const char *event)
 | |
| {
 | |
|     LOG(("nsHttpHandler::NotifyObservers [chan=%x event=\"%s\"]\n", chan, event));
 | |
|     nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
 | |
|     if (obsService)
 | |
|         obsService->NotifyObservers(chan, event, nullptr);
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
 | |
|                                  uint32_t flags)
 | |
| {
 | |
|     // TODO E10S This helper has to be initialized on the other process
 | |
|     RefPtr<nsAsyncRedirectVerifyHelper> redirectCallbackHelper =
 | |
|         new nsAsyncRedirectVerifyHelper();
 | |
| 
 | |
|     return redirectCallbackHelper->Init(oldChan, newChan, flags);
 | |
| }
 | |
| 
 | |
| /* static */ nsresult
 | |
| nsHttpHandler::GenerateHostPort(const nsCString& host, int32_t port,
 | |
|                                 nsACString& hostLine)
 | |
| {
 | |
|     return NS_GenerateHostPort(host, port, hostLine);
 | |
| }
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // nsHttpHandler <private>
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| const nsAFlatCString &
 | |
| nsHttpHandler::UserAgent()
 | |
| {
 | |
|     if (mUserAgentOverride) {
 | |
|         LOG(("using general.useragent.override : %s\n", mUserAgentOverride.get()));
 | |
|         return mUserAgentOverride;
 | |
|     }
 | |
| 
 | |
|     if (mUserAgentIsDirty) {
 | |
|         BuildUserAgent();
 | |
|         mUserAgentIsDirty = false;
 | |
|     }
 | |
| 
 | |
|     return mUserAgent;
 | |
| }
 | |
| 
 | |
| void
 | |
| nsHttpHandler::BuildUserAgent()
 | |
| {
 | |
|     LOG(("nsHttpHandler::BuildUserAgent\n"));
 | |
| 
 | |
|     MOZ_ASSERT(!mLegacyAppName.IsEmpty() &&
 | |
|                !mLegacyAppVersion.IsEmpty(),
 | |
|                "HTTP cannot send practical requests without this much");
 | |
| 
 | |
|     // preallocate to worst-case size, which should always be better
 | |
|     // than if we didn't preallocate at all.
 | |
|     mUserAgent.SetCapacity(mLegacyAppName.Length() +
 | |
|                            mLegacyAppVersion.Length() +
 | |
| #ifndef UA_SPARE_PLATFORM
 | |
|                            mPlatform.Length() +
 | |
| #endif
 | |
|                            mOscpu.Length() +
 | |
|                            mMisc.Length() +
 | |
|                            mProduct.Length() +
 | |
|                            mProductSub.Length() +
 | |
|                            mAppName.Length() +
 | |
|                            mAppVersion.Length() +
 | |
|                            mCompatFirefox.Length() +
 | |
|                            mCompatDevice.Length() +
 | |
|                            mDeviceModelId.Length() +
 | |
|                            13);
 | |
| 
 | |
|     // Application portion
 | |
|     mUserAgent.Assign(mLegacyAppName);
 | |
|     mUserAgent += '/';
 | |
|     mUserAgent += mLegacyAppVersion;
 | |
|     mUserAgent += ' ';
 | |
| 
 | |
|     // Application comment
 | |
|     mUserAgent += '(';
 | |
| #ifndef UA_SPARE_PLATFORM
 | |
|     if (!mPlatform.IsEmpty()) {
 | |
|       mUserAgent += mPlatform;
 | |
|       mUserAgent.AppendLiteral("; ");
 | |
|     }
 | |
| #endif
 | |
|     if (!mCompatDevice.IsEmpty()) {
 | |
|         mUserAgent += mCompatDevice;
 | |
|         mUserAgent.AppendLiteral("; ");
 | |
|     }
 | |
|     else if (!mOscpu.IsEmpty()) {
 | |
|       mUserAgent += mOscpu;
 | |
|       mUserAgent.AppendLiteral("; ");
 | |
|     }
 | |
|     if (!mDeviceModelId.IsEmpty()) {
 | |
|         mUserAgent += mDeviceModelId;
 | |
|         mUserAgent.AppendLiteral("; ");
 | |
|     }
 | |
|     mUserAgent += mMisc;
 | |
|     mUserAgent += ')';
 | |
| 
 | |
|     // Product portion
 | |
|     mUserAgent += ' ';
 | |
|     mUserAgent += mProduct;
 | |
|     mUserAgent += '/';
 | |
|     mUserAgent += mProductSub;
 | |
| 
 | |
|     bool isFirefox = mAppName.EqualsLiteral("Firefox");
 | |
|     if (isFirefox || mCompatFirefoxEnabled) {
 | |
|         // "Firefox/x.y" (compatibility) app token
 | |
|         mUserAgent += ' ';
 | |
|         mUserAgent += mCompatFirefox;
 | |
|     }
 | |
|     if (!isFirefox) {
 | |
|         // App portion
 | |
|         mUserAgent += ' ';
 | |
|         mUserAgent += mAppName;
 | |
|         mUserAgent += '/';
 | |
|         mUserAgent += mAppVersion;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #ifdef XP_WIN
 | |
| #define WNT_BASE "Windows NT %ld.%ld"
 | |
| #define W64_PREFIX "; Win64"
 | |
| #endif
 | |
| 
 | |
| void
 | |
| nsHttpHandler::InitUserAgentComponents()
 | |
| {
 | |
| #ifndef MOZ_UA_OS_AGNOSTIC
 | |
|     // Gather platform.
 | |
|     mPlatform.AssignLiteral(
 | |
| #if defined(ANDROID)
 | |
|     "Android"
 | |
| #elif defined(XP_WIN)
 | |
|     "Windows"
 | |
| #elif defined(XP_MACOSX)
 | |
|     "Macintosh"
 | |
| #elif defined(XP_UNIX)
 | |
|     // We historically have always had X11 here,
 | |
|     // and there seems little a webpage can sensibly do
 | |
|     // based on it being something else, so use X11 for
 | |
|     // backwards compatibility in all cases.
 | |
|     "X11"
 | |
| #endif
 | |
|     );
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #ifdef ANDROID
 | |
|     nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
 | |
|     MOZ_ASSERT(infoService, "Could not find a system info service");
 | |
|     nsresult rv;
 | |
|     // Add the Android version number to the Fennec platform identifier.
 | |
| #if defined MOZ_WIDGET_ANDROID
 | |
| #ifndef MOZ_UA_OS_AGNOSTIC // Don't add anything to mPlatform since it's empty.
 | |
|     nsAutoString androidVersion;
 | |
|     rv = infoService->GetPropertyAsAString(
 | |
|         NS_LITERAL_STRING("release_version"), androidVersion);
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|       mPlatform += " ";
 | |
|       // If the 2nd character is a ".", we know the major version is a single
 | |
|       // digit. If we're running on a version below 4 we pretend to be on
 | |
|       // Android KitKat (4.4) to work around scripts sniffing for low versions.
 | |
|       if (androidVersion[1] == 46 && androidVersion[0] < 52) {
 | |
|         mPlatform += "4.4";
 | |
|       } else {
 | |
|         mPlatform += NS_LossyConvertUTF16toASCII(androidVersion);
 | |
|       }
 | |
|     }
 | |
| #endif
 | |
| #endif
 | |
|     // Add the `Mobile` or `Tablet` or `TV` token when running on device.
 | |
|     bool isTablet;
 | |
|     rv = infoService->GetPropertyAsBool(NS_LITERAL_STRING("tablet"), &isTablet);
 | |
|     if (NS_SUCCEEDED(rv) && isTablet) {
 | |
|         mCompatDevice.AssignLiteral("Tablet");
 | |
|     } else {
 | |
|         bool isTV;
 | |
|         rv = infoService->GetPropertyAsBool(NS_LITERAL_STRING("tv"), &isTV);
 | |
|         if (NS_SUCCEEDED(rv) && isTV) {
 | |
|             mCompatDevice.AssignLiteral("TV");
 | |
|         } else {
 | |
|             mCompatDevice.AssignLiteral("Mobile");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (Preferences::GetBool(UA_PREF("use_device"), false)) {
 | |
|         mDeviceModelId = mozilla::net::GetDeviceModelId();
 | |
|     }
 | |
| #endif // ANDROID
 | |
| 
 | |
| #ifdef MOZ_MULET
 | |
|     {
 | |
|         // Add the `Mobile` or `Tablet` or `TV` token when running in the b2g
 | |
|         // desktop simulator via preference.
 | |
|         nsCString deviceType;
 | |
|         nsresult rv = Preferences::GetCString("devtools.useragent.device_type", &deviceType);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mCompatDevice.Assign(deviceType);
 | |
|         } else {
 | |
|             mCompatDevice.AssignLiteral("Mobile");
 | |
|         }
 | |
|     }
 | |
| #endif // MOZ_MULET
 | |
| 
 | |
| #if defined(MOZ_WIDGET_GONK)
 | |
|     // Device model identifier should be a simple token, which can be composed
 | |
|     // of letters, numbers, hyphen ("-") and dot (".").
 | |
|     // Any other characters means the identifier is invalid and ignored.
 | |
|     nsCString deviceId;
 | |
|     rv = Preferences::GetCString("general.useragent.device_id", &deviceId);
 | |
|     if (NS_SUCCEEDED(rv)) {
 | |
|         bool valid = true;
 | |
|         deviceId.Trim(" ", true, true);
 | |
|         for (size_t i = 0; i < deviceId.Length(); i++) {
 | |
|             char c = deviceId.CharAt(i);
 | |
|             if (!(isalnum(c) || c == '-' || c == '.')) {
 | |
|                 valid = false;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         if (valid) {
 | |
|             mDeviceModelId = deviceId;
 | |
|         } else {
 | |
|             LOG(("nsHttpHandler: Ignore invalid device ID: [%s]\n",
 | |
|                   deviceId.get()));
 | |
|         }
 | |
|     }
 | |
| #endif
 | |
| 
 | |
| #ifndef MOZ_UA_OS_AGNOSTIC
 | |
|     // Gather OS/CPU.
 | |
| #if defined(XP_WIN)
 | |
|     OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
 | |
| #pragma warning(push)
 | |
| #pragma warning(disable:4996)
 | |
|     if (GetVersionEx(&info)) {
 | |
| #pragma warning(pop)
 | |
|         const char *format;
 | |
| #if defined _M_IA64
 | |
|         format = WNT_BASE W64_PREFIX "; IA64";
 | |
| #elif defined _M_X64 || defined _M_AMD64
 | |
|         format = WNT_BASE W64_PREFIX "; x64";
 | |
| #else
 | |
|         BOOL isWow64 = FALSE;
 | |
|         if (!IsWow64Process(GetCurrentProcess(), &isWow64)) {
 | |
|             isWow64 = FALSE;
 | |
|         }
 | |
|         format = isWow64
 | |
|           ? WNT_BASE "; WOW64"
 | |
|           : WNT_BASE;
 | |
| #endif
 | |
|         char *buf = PR_smprintf(format,
 | |
|                                 info.dwMajorVersion,
 | |
|                                 info.dwMinorVersion);
 | |
|         if (buf) {
 | |
|             mOscpu = buf;
 | |
|             PR_smprintf_free(buf);
 | |
|         }
 | |
|     }
 | |
| #elif defined (XP_MACOSX)
 | |
| #if defined(__ppc__)
 | |
|     mOscpu.AssignLiteral("PPC Mac OS X");
 | |
| #elif defined(__i386__) || defined(__x86_64__)
 | |
|     mOscpu.AssignLiteral("Intel Mac OS X");
 | |
| #endif
 | |
|     SInt32 majorVersion = nsCocoaFeatures::OSXVersionMajor();
 | |
|     SInt32 minorVersion = nsCocoaFeatures::OSXVersionMinor();
 | |
|     mOscpu += nsPrintfCString(" %d.%d", majorVersion, minorVersion);
 | |
| #elif defined (XP_UNIX)
 | |
|     struct utsname name;
 | |
| 
 | |
|     int ret = uname(&name);
 | |
|     if (ret >= 0) {
 | |
|         nsAutoCString buf;
 | |
|         buf =  (char*)name.sysname;
 | |
| 
 | |
|         if (strcmp(name.machine, "x86_64") == 0 &&
 | |
|             sizeof(void *) == sizeof(int32_t)) {
 | |
|             // We're running 32-bit code on x86_64. Make this browser
 | |
|             // look like it's running on i686 hardware, but append "
 | |
|             // (x86_64)" to the end of the oscpu identifier to be able
 | |
|             // to differentiate this from someone running 64-bit code
 | |
|             // on x86_64..
 | |
| 
 | |
|             buf += " i686 on x86_64";
 | |
|         } else {
 | |
|             buf += ' ';
 | |
| 
 | |
| #ifdef AIX
 | |
|             // AIX uname returns machine specific info in the uname.machine
 | |
|             // field and does not return the cpu type like other platforms.
 | |
|             // We use the AIX version and release numbers instead.
 | |
|             buf += (char*)name.version;
 | |
|             buf += '.';
 | |
|             buf += (char*)name.release;
 | |
| #else
 | |
|             buf += (char*)name.machine;
 | |
| #endif
 | |
|         }
 | |
| 
 | |
|         mOscpu.Assign(buf);
 | |
|     }
 | |
| #endif
 | |
| #endif
 | |
| 
 | |
|     mUserAgentIsDirty = true;
 | |
| }
 | |
| 
 | |
| uint32_t
 | |
| nsHttpHandler::MaxSocketCount()
 | |
| {
 | |
|     PR_CallOnce(&nsSocketTransportService::gMaxCountInitOnce,
 | |
|                 nsSocketTransportService::DiscoverMaxCount);
 | |
|     // Don't use the full max count because sockets can be held in
 | |
|     // the persistent connection pool for a long time and that could
 | |
|     // starve other users.
 | |
| 
 | |
|     uint32_t maxCount = nsSocketTransportService::gMaxCount;
 | |
|     if (maxCount <= 8)
 | |
|         maxCount = 1;
 | |
|     else
 | |
|         maxCount -= 8;
 | |
| 
 | |
|     return maxCount;
 | |
| }
 | |
| 
 | |
| void
 | |
| nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
 | |
| {
 | |
|     nsresult rv = NS_OK;
 | |
|     int32_t val;
 | |
| 
 | |
|     LOG(("nsHttpHandler::PrefsChanged [pref=%s]\n", pref));
 | |
| 
 | |
| #define PREF_CHANGED(p) ((pref == nullptr) || !PL_strcmp(pref, p))
 | |
| #define MULTI_PREF_CHANGED(p) \
 | |
|   ((pref == nullptr) || !PL_strncmp(pref, p, sizeof(p) - 1))
 | |
| 
 | |
|     // If a security pref changed, lets clear our connection pool reuse
 | |
|     if (MULTI_PREF_CHANGED(SECURITY_PREFIX)) {
 | |
|         LOG(("nsHttpHandler::PrefsChanged Security Pref Changed %s\n", pref));
 | |
|         if (mConnMgr) {
 | |
|             mConnMgr->DoShiftReloadConnectionCleanup(nullptr);
 | |
|             mConnMgr->PruneDeadConnections();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // UA components
 | |
|     //
 | |
| 
 | |
|     bool cVar = false;
 | |
| 
 | |
|     if (PREF_CHANGED(UA_PREF("compatMode.firefox"))) {
 | |
|         rv = prefs->GetBoolPref(UA_PREF("compatMode.firefox"), &cVar);
 | |
|         mCompatFirefoxEnabled = (NS_SUCCEEDED(rv) && cVar);
 | |
|         mUserAgentIsDirty = true;
 | |
|     }
 | |
| 
 | |
|     // general.useragent.override
 | |
|     if (PREF_CHANGED(UA_PREF("override"))) {
 | |
|         prefs->GetCharPref(UA_PREF("override"),
 | |
|                             getter_Copies(mUserAgentOverride));
 | |
|         mUserAgentIsDirty = true;
 | |
|     }
 | |
| 
 | |
| #ifdef ANDROID
 | |
|     // general.useragent.use_device
 | |
|     if (PREF_CHANGED(UA_PREF("use_device"))) {
 | |
|         if (Preferences::GetBool(UA_PREF("use_device"), false)) {
 | |
|             mDeviceModelId = mozilla::net::GetDeviceModelId();
 | |
|         } else {
 | |
|             mDeviceModelId = EmptyCString();
 | |
|         }
 | |
|         mUserAgentIsDirty = true;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     //
 | |
|     // HTTP options
 | |
|     //
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("keep-alive.timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("keep-alive.timeout"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mIdleTimeout = PR_SecondsToInterval(clamped(val, 1, 0xffff));
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("request.max-attempts"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("request.max-attempts"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mMaxRequestAttempts = (uint16_t) clamped(val, 1, 0xffff);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("request.max-start-delay"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("request.max-start-delay"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mMaxRequestDelay = (uint16_t) clamped(val, 0, 0xffff);
 | |
|             if (mConnMgr)
 | |
|                 mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_REQUEST_DELAY,
 | |
|                                       mMaxRequestDelay);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("response.timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("response.timeout"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mResponseTimeout = PR_SecondsToInterval(clamped(val, 0, 0xffff));
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("network-changed.timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("network-changed.timeout"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mNetworkChangedTimeout = clamped(val, 1, 600) * 1000;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
| 
 | |
|             mMaxConnections = (uint16_t) clamped((uint32_t)val,
 | |
|                                                  (uint32_t)1, MaxSocketCount());
 | |
| 
 | |
|             if (mConnMgr)
 | |
|                 mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
 | |
|                                       mMaxConnections);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-server"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-server"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mMaxPersistentConnectionsPerServer = (uint8_t) clamped(val, 1, 0xff);
 | |
|             if (mConnMgr)
 | |
|                 mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_HOST,
 | |
|                                       mMaxPersistentConnectionsPerServer);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-proxy"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-proxy"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mMaxPersistentConnectionsPerProxy = (uint8_t) clamped(val, 1, 0xff);
 | |
|             if (mConnMgr)
 | |
|                 mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
 | |
|                                       mMaxPersistentConnectionsPerProxy);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("sendRefererHeader"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mReferrerLevel = (uint8_t) clamped(val, 0, 0xff);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("referer.spoofSource"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("referer.spoofSource"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSpoofReferrerSource = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("referer.trimmingPolicy"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("referer.trimmingPolicy"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mReferrerTrimmingPolicy = (uint8_t) clamped(val, 0, 0xff);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("referer.XOriginPolicy"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("referer.XOriginPolicy"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mReferrerXOriginPolicy = (uint8_t) clamped(val, 0, 0xff);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mRedirectionLimit = (uint8_t) clamped(val, 0, 0xff);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("connection-retry-timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("connection-retry-timeout"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mIdleSynTimeout = (uint16_t) clamped(val, 0, 3000);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("fast-fallback-to-IPv4"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("fast-fallback-to-IPv4"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mFastFallbackToIPv4 = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("version"))) {
 | |
|         nsXPIDLCString httpVersion;
 | |
|         prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));
 | |
|         if (httpVersion) {
 | |
|             if (!PL_strcmp(httpVersion, "1.1"))
 | |
|                 mHttpVersion = NS_HTTP_VERSION_1_1;
 | |
|             else if (!PL_strcmp(httpVersion, "0.9"))
 | |
|                 mHttpVersion = NS_HTTP_VERSION_0_9;
 | |
|             else
 | |
|                 mHttpVersion = NS_HTTP_VERSION_1_0;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("proxy.version"))) {
 | |
|         nsXPIDLCString httpVersion;
 | |
|         prefs->GetCharPref(HTTP_PREF("proxy.version"), getter_Copies(httpVersion));
 | |
|         if (httpVersion) {
 | |
|             if (!PL_strcmp(httpVersion, "1.1"))
 | |
|                 mProxyHttpVersion = NS_HTTP_VERSION_1_1;
 | |
|             else
 | |
|                 mProxyHttpVersion = NS_HTTP_VERSION_1_0;
 | |
|             // it does not make sense to issue a HTTP/0.9 request to a proxy server
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("pipelining"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             if (cVar)
 | |
|                 mCapabilities |=  NS_HTTP_ALLOW_PIPELINING;
 | |
|             else
 | |
|                 mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
 | |
|             mPipeliningEnabled = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining.maxrequests"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("pipelining.maxrequests"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mMaxPipelinedRequests = clamped(val, 1, 0xffff);
 | |
|             if (mConnMgr)
 | |
|                 mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PIPELINED_REQUESTS,
 | |
|                                       mMaxPipelinedRequests);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining.max-optimistic-requests"))) {
 | |
|         rv = prefs->
 | |
|             GetIntPref(HTTP_PREF("pipelining.max-optimistic-requests"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mMaxOptimisticPipelinedRequests = clamped(val, 1, 0xffff);
 | |
|             if (mConnMgr)
 | |
|                 mConnMgr->UpdateParam
 | |
|                     (nsHttpConnectionMgr::MAX_OPTIMISTIC_PIPELINED_REQUESTS,
 | |
|                      mMaxOptimisticPipelinedRequests);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining.aggressive"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("pipelining.aggressive"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mPipelineAggressive = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining.maxsize"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("pipelining.maxsize"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mMaxPipelineObjectSize =
 | |
|                 static_cast<int64_t>(clamped(val, 1000, 100000000));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Determines whether or not to actually reschedule after the
 | |
|     // reschedule-timeout has expired
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining.reschedule-on-timeout"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("pipelining.reschedule-on-timeout"),
 | |
|                                 &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mPipelineRescheduleOnTimeout = cVar;
 | |
|     }
 | |
| 
 | |
|     // The amount of time head of line blocking is allowed (in ms)
 | |
|     // before the blocked transactions are moved to another pipeline
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining.reschedule-timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("pipelining.reschedule-timeout"),
 | |
|                                &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mPipelineRescheduleTimeout =
 | |
|                 PR_MillisecondsToInterval((uint16_t) clamped(val, 500, 0xffff));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // The amount of time a pipelined transaction is allowed to wait before
 | |
|     // being canceled and retried in a non-pipeline connection
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining.read-timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("pipelining.read-timeout"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mPipelineReadTimeout =
 | |
|                 PR_MillisecondsToInterval((uint16_t) clamped(val, 5000,
 | |
|                                                              0xffff));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("pipelining.ssl"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("pipelining.ssl"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mPipeliningOverSSL = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mProxyPipelining = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("qos"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("qos"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mQoSBits = (uint8_t) clamped(val, 0, 0xff);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("sendSecureXSiteReferrer"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("sendSecureXSiteReferrer"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSendSecureXSiteReferrer = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
 | |
|         nsXPIDLCString accept;
 | |
|         rv = prefs->GetCharPref(HTTP_PREF("accept.default"),
 | |
|                                   getter_Copies(accept));
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             SetAccept(accept);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
 | |
|         nsXPIDLCString acceptEncodings;
 | |
|         rv = prefs->GetCharPref(HTTP_PREF("accept-encoding"),
 | |
|                                   getter_Copies(acceptEncodings));
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             SetAcceptEncodings(acceptEncodings, false);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("accept-encoding.secure"))) {
 | |
|         nsXPIDLCString acceptEncodings;
 | |
|         rv = prefs->GetCharPref(HTTP_PREF("accept-encoding.secure"),
 | |
|                                   getter_Copies(acceptEncodings));
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             SetAcceptEncodings(acceptEncodings, true);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("default-socket-type"))) {
 | |
|         nsXPIDLCString sval;
 | |
|         rv = prefs->GetCharPref(HTTP_PREF("default-socket-type"),
 | |
|                                 getter_Copies(sval));
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             if (sval.IsEmpty())
 | |
|                 mDefaultSocketType.Adopt(0);
 | |
|             else {
 | |
|                 // verify that this socket type is actually valid
 | |
|                 nsCOMPtr<nsISocketProviderService> sps(
 | |
|                         do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID));
 | |
|                 if (sps) {
 | |
|                     nsCOMPtr<nsISocketProvider> sp;
 | |
|                     rv = sps->GetSocketProvider(sval, getter_AddRefs(sp));
 | |
|                     if (NS_SUCCEEDED(rv)) {
 | |
|                         // OK, this looks like a valid socket provider.
 | |
|                         mDefaultSocketType.Assign(sval);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("prompt-temp-redirect"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("prompt-temp-redirect"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mPromptTempRedirect = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("assoc-req.enforce"))) {
 | |
|         cVar = false;
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("assoc-req.enforce"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mEnforceAssocReq = cVar;
 | |
|     }
 | |
| 
 | |
|     // enable Persistent caching for HTTPS - bug#205921
 | |
|     if (PREF_CHANGED(BROWSER_PREF("disk_cache_ssl"))) {
 | |
|         cVar = false;
 | |
|         rv = prefs->GetBoolPref(BROWSER_PREF("disk_cache_ssl"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mEnablePersistentHttpsCaching = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("phishy-userpass-length"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("phishy-userpass-length"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mPhishyUserPassLength = (uint8_t) clamped(val, 0, 0xff);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.enabled"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mEnableSpdy = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.enabled.v3-1"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled.v3-1"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSpdyV31 = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.enabled.http2"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled.http2"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mHttp2Enabled = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.enabled.deps"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled.deps"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mUseH2Deps = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.enforce-tls-profile"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("spdy.enforce-tls-profile"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mEnforceHttp2TlsProfile = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.coalesce-hostnames"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("spdy.coalesce-hostnames"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mCoalesceSpdy = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.persistent-settings"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("spdy.persistent-settings"),
 | |
|                                 &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSpdyPersistentSettings = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("spdy.timeout"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSpdyTimeout = PR_SecondsToInterval(clamped(val, 1, 0xffff));
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.chunk-size"))) {
 | |
|         // keep this within http/2 ranges of 1 to 2^14-1
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("spdy.chunk-size"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSpdySendingChunkSize = (uint32_t) clamped(val, 1, 0x3fff);
 | |
|     }
 | |
| 
 | |
|     // The amount of idle seconds on a spdy connection before initiating a
 | |
|     // server ping. 0 will disable.
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.ping-threshold"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("spdy.ping-threshold"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSpdyPingThreshold =
 | |
|                 PR_SecondsToInterval((uint16_t) clamped(val, 0, 0x7fffffff));
 | |
|     }
 | |
| 
 | |
|     // The amount of seconds to wait for a spdy ping response before
 | |
|     // closing the session.
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.ping-timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("spdy.ping-timeout"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSpdyPingTimeout =
 | |
|                 PR_SecondsToInterval((uint16_t) clamped(val, 0, 0x7fffffff));
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.allow-push"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("spdy.allow-push"),
 | |
|                                 &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mAllowPush = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("altsvc.enabled"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("altsvc.enabled"),
 | |
|                                 &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mEnableAltSvc = cVar;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("altsvc.oe"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("altsvc.oe"),
 | |
|                                 &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mEnableAltSvcOE = cVar;
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.push-allowance"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("spdy.push-allowance"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mSpdyPushAllowance =
 | |
|                 static_cast<uint32_t>
 | |
|                 (clamped(val, 1024, static_cast<int32_t>(ASpdySession::kInitialRwin)));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.pull-allowance"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("spdy.pull-allowance"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mSpdyPullAllowance =
 | |
|                 static_cast<uint32_t>(clamped(val, 1024, 0x7fffffff));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.default-concurrent"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("spdy.default-concurrent"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mDefaultSpdyConcurrent =
 | |
|                 static_cast<uint32_t>(std::max<int32_t>(std::min<int32_t>(val, 9999), 1));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // The amount of seconds to wait for a spdy ping response before
 | |
|     // closing the session.
 | |
|     if (PREF_CHANGED(HTTP_PREF("spdy.send-buffer-size"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("spdy.send-buffer-size"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mSpdySendBufferSize = (uint32_t) clamped(val, 1500, 0x7fffffff);
 | |
|     }
 | |
| 
 | |
|     // The maximum amount of time to wait for socket transport to be
 | |
|     // established
 | |
|     if (PREF_CHANGED(HTTP_PREF("connection-timeout"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("connection-timeout"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             // the pref is in seconds, but the variable is in milliseconds
 | |
|             mConnectTimeout = clamped(val, 1, 0xffff) * PR_MSEC_PER_SEC;
 | |
|     }
 | |
| 
 | |
|     // The maximum number of current global half open sockets allowable
 | |
|     // for starting a new speculative connection.
 | |
|     if (PREF_CHANGED(HTTP_PREF("speculative-parallel-limit"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("speculative-parallel-limit"), &val);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mParallelSpeculativeConnectLimit = (uint32_t) clamped(val, 0, 1024);
 | |
|     }
 | |
| 
 | |
|     // Whether or not to block requests for non head js/css items (e.g. media)
 | |
|     // while those elements load.
 | |
|     if (PREF_CHANGED(HTTP_PREF("rendering-critical-requests-prioritization"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("rendering-critical-requests-prioritization"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv))
 | |
|             mCriticalRequestPrioritization = cVar;
 | |
|     }
 | |
| 
 | |
|     // on transition of network.http.diagnostics to true print
 | |
|     // a bunch of information to the console
 | |
|     if (pref && PREF_CHANGED(HTTP_PREF("diagnostics"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("diagnostics"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv) && cVar) {
 | |
|             if (mConnMgr)
 | |
|                 mConnMgr->PrintDiagnostics();
 | |
|         }
 | |
|     }
 | |
|     //
 | |
|     // INTL options
 | |
|     //
 | |
| 
 | |
|     if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) {
 | |
|         nsCOMPtr<nsIPrefLocalizedString> pls;
 | |
|         prefs->GetComplexValue(INTL_ACCEPT_LANGUAGES,
 | |
|                                 NS_GET_IID(nsIPrefLocalizedString),
 | |
|                                 getter_AddRefs(pls));
 | |
|         if (pls) {
 | |
|             nsXPIDLString uval;
 | |
|             pls->ToString(getter_Copies(uval));
 | |
|             if (uval)
 | |
|                 SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval).get());
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Tracking options
 | |
|     //
 | |
| 
 | |
|     if (PREF_CHANGED(DONOTTRACK_HEADER_ENABLED)) {
 | |
|         cVar = false;
 | |
|         rv = prefs->GetBoolPref(DONOTTRACK_HEADER_ENABLED, &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mDoNotTrackEnabled = cVar;
 | |
|         }
 | |
|     }
 | |
|     // Hint option
 | |
|     if (PREF_CHANGED(SAFE_HINT_HEADER_VALUE)) {
 | |
|         cVar = false;
 | |
|         rv = prefs->GetBoolPref(SAFE_HINT_HEADER_VALUE, &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mSafeHintEnabled = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // toggle to true anytime a token bucket related pref is changed.. that
 | |
|     // includes telemetry and allow-experiments because of the abtest profile
 | |
|     bool requestTokenBucketUpdated = false;
 | |
| 
 | |
|     //
 | |
|     // Telemetry
 | |
|     //
 | |
| 
 | |
|     if (PREF_CHANGED(TELEMETRY_ENABLED)) {
 | |
|         cVar = false;
 | |
|         requestTokenBucketUpdated = true;
 | |
|         rv = prefs->GetBoolPref(TELEMETRY_ENABLED, &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mTelemetryEnabled = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256" is the required h2 interop
 | |
|     // suite.
 | |
| 
 | |
|     if (PREF_CHANGED(H2MANDATORY_SUITE)) {
 | |
|         cVar = false;
 | |
|         rv = prefs->GetBoolPref(H2MANDATORY_SUITE, &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mH2MandatorySuiteEnabled = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // network.allow-experiments
 | |
|     //
 | |
|     if (PREF_CHANGED(ALLOW_EXPERIMENTS)) {
 | |
|         cVar = true;
 | |
|         requestTokenBucketUpdated = true;
 | |
|         rv = prefs->GetBoolPref(ALLOW_EXPERIMENTS, &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mAllowExperiments = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // network.http.debug-observations
 | |
|     if (PREF_CHANGED("network.http.debug-observations")) {
 | |
|         cVar = false;
 | |
|         rv = prefs->GetBoolPref("network.http.debug-observations", &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mDebugObservations = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Test HTTP Pipelining (bug796192)
 | |
|     // If experiments are allowed and pipelining is Off,
 | |
|     // turn it On for just 10 minutes
 | |
|     //
 | |
|     if (mAllowExperiments && !mPipeliningEnabled &&
 | |
|         PREF_CHANGED(HTTP_PREF("pipelining.abtest"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("pipelining.abtest"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             // If option is enabled, only test for ~1% of sessions
 | |
|             if (cVar && !(rand() % 128)) {
 | |
|                 mCapabilities |=  NS_HTTP_ALLOW_PIPELINING;
 | |
|                 if (mPipelineTestTimer)
 | |
|                     mPipelineTestTimer->Cancel();
 | |
|                 mPipelineTestTimer =
 | |
|                     do_CreateInstance("@mozilla.org/timer;1", &rv);
 | |
|                 if (NS_SUCCEEDED(rv)) {
 | |
|                     rv = mPipelineTestTimer->InitWithFuncCallback(
 | |
|                         TimerCallback, this, 10*60*1000, // 10 minutes
 | |
|                         nsITimer::TYPE_ONE_SHOT);
 | |
|                 }
 | |
|             } else {
 | |
|                 mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
 | |
|                 if (mPipelineTestTimer) {
 | |
|                     mPipelineTestTimer->Cancel();
 | |
|                     mPipelineTestTimer = nullptr;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("pacing.requests.enabled"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("pacing.requests.enabled"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mRequestTokenBucketEnabled = cVar;
 | |
|             requestTokenBucketUpdated = true;
 | |
|         }
 | |
|     }
 | |
|     if (PREF_CHANGED(HTTP_PREF("pacing.requests.min-parallelism"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.min-parallelism"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mRequestTokenBucketMinParallelism = static_cast<uint16_t>(clamped(val, 1, 1024));
 | |
|             requestTokenBucketUpdated = true;
 | |
|         }
 | |
|     }
 | |
|     if (PREF_CHANGED(HTTP_PREF("pacing.requests.hz"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.hz"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mRequestTokenBucketHz = static_cast<uint32_t>(clamped(val, 1, 10000));
 | |
|             requestTokenBucketUpdated = true;
 | |
|         }
 | |
|     }
 | |
|     if (PREF_CHANGED(HTTP_PREF("pacing.requests.burst"))) {
 | |
|         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.burst"), &val);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mRequestTokenBucketBurst = val ? val : 1;
 | |
|             requestTokenBucketUpdated = true;
 | |
|         }
 | |
|     }
 | |
|     if (requestTokenBucketUpdated) {
 | |
|         MakeNewRequestTokenBucket();
 | |
|     }
 | |
| 
 | |
|     // Keepalive values for initial and idle connections.
 | |
|     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.short_lived_connections"))) {
 | |
|         rv = prefs->GetBoolPref(
 | |
|             HTTP_PREF("tcp_keepalive.short_lived_connections"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv) && cVar != mTCPKeepaliveShortLivedEnabled) {
 | |
|             mTCPKeepaliveShortLivedEnabled = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.short_lived_time"))) {
 | |
|         rv = prefs->GetIntPref(
 | |
|             HTTP_PREF("tcp_keepalive.short_lived_time"), &val);
 | |
|         if (NS_SUCCEEDED(rv) && val > 0)
 | |
|             mTCPKeepaliveShortLivedTimeS = clamped(val, 1, 300); // Max 5 mins.
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.short_lived_idle_time"))) {
 | |
|         rv = prefs->GetIntPref(
 | |
|             HTTP_PREF("tcp_keepalive.short_lived_idle_time"), &val);
 | |
|         if (NS_SUCCEEDED(rv) && val > 0)
 | |
|             mTCPKeepaliveShortLivedIdleTimeS = clamped(val,
 | |
|                                                        1, kMaxTCPKeepIdle);
 | |
|     }
 | |
| 
 | |
|     // Keepalive values for Long-lived Connections.
 | |
|     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.long_lived_connections"))) {
 | |
|         rv = prefs->GetBoolPref(
 | |
|             HTTP_PREF("tcp_keepalive.long_lived_connections"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv) && cVar != mTCPKeepaliveLongLivedEnabled) {
 | |
|             mTCPKeepaliveLongLivedEnabled = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.long_lived_idle_time"))) {
 | |
|         rv = prefs->GetIntPref(
 | |
|             HTTP_PREF("tcp_keepalive.long_lived_idle_time"), &val);
 | |
|         if (NS_SUCCEEDED(rv) && val > 0)
 | |
|             mTCPKeepaliveLongLivedIdleTimeS = clamped(val,
 | |
|                                                       1, kMaxTCPKeepIdle);
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("enforce-framing.http1")) ||
 | |
|         PREF_CHANGED(HTTP_PREF("enforce-framing.soft")) ) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("enforce-framing.http1"), &cVar);
 | |
|         if (NS_SUCCEEDED(rv) && cVar) {
 | |
|             mEnforceH1Framing = FRAMECHECK_STRICT;
 | |
|         } else {
 | |
|             rv = prefs->GetBoolPref(HTTP_PREF("enforce-framing.soft"), &cVar);
 | |
|             if (NS_SUCCEEDED(rv) && cVar) {
 | |
|                 mEnforceH1Framing = FRAMECHECK_BARELY;
 | |
|             } else {
 | |
|                 mEnforceH1Framing = FRAMECHECK_LAX;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // remote content-signature testing option
 | |
|     if (PREF_CHANGED(NEW_TAB_REMOTE_MODE)) {
 | |
|         nsAutoCString channel;
 | |
|         prefs->GetCharPref(NEW_TAB_REMOTE_MODE, getter_Copies(channel));
 | |
|         if (channel.EqualsLiteral("test") ||
 | |
|             channel.EqualsLiteral("test2") ||
 | |
|             channel.EqualsLiteral("dev")) {
 | |
|             mNewTabContentSignaturesDisabled = true;
 | |
|         } else {
 | |
|             mNewTabContentSignaturesDisabled = false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (PREF_CHANGED(HTTP_PREF("keep_empty_response_headers_as_empty_string"))) {
 | |
|         rv = prefs->GetBoolPref(HTTP_PREF("keep_empty_response_headers_as_empty_string"),
 | |
|                                 &cVar);
 | |
|         if (NS_SUCCEEDED(rv)) {
 | |
|             mKeepEmptyResponseHeadersAsEmtpyString = cVar;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Enable HTTP response timeout if TCP Keepalives are disabled.
 | |
|     mResponseTimeoutEnabled = !mTCPKeepaliveShortLivedEnabled &&
 | |
|                               !mTCPKeepaliveLongLivedEnabled;
 | |
| 
 | |
| #undef PREF_CHANGED
 | |
| #undef MULTI_PREF_CHANGED
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Static method called by mPipelineTestTimer when it expires.
 | |
|  */
 | |
| void
 | |
| nsHttpHandler::TimerCallback(nsITimer * aTimer, void * aClosure)
 | |
| {
 | |
|     RefPtr<nsHttpHandler> thisObject = static_cast<nsHttpHandler*>(aClosure);
 | |
|     if (!thisObject->mPipeliningEnabled)
 | |
|         thisObject->mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Currently, only regularizes the case of subtags.
 | |
|  */
 | |
| static void
 | |
| CanonicalizeLanguageTag(char *languageTag)
 | |
| {
 | |
|     char *s = languageTag;
 | |
|     while (*s != '\0') {
 | |
|         *s = nsCRT::ToLower(*s);
 | |
|         s++;
 | |
|     }
 | |
| 
 | |
|     s = languageTag;
 | |
|     bool isFirst = true;
 | |
|     bool seenSingleton = false;
 | |
|     while (*s != '\0') {
 | |
|         char *subTagEnd = strchr(s, '-');
 | |
|         if (subTagEnd == nullptr) {
 | |
|             subTagEnd = strchr(s, '\0');
 | |
|         }
 | |
| 
 | |
|         if (isFirst) {
 | |
|             isFirst = false;
 | |
|         } else if (seenSingleton) {
 | |
|             // Do nothing
 | |
|         } else {
 | |
|             size_t subTagLength = subTagEnd - s;
 | |
|             if (subTagLength == 1) {
 | |
|                 seenSingleton = true;
 | |
|             } else if (subTagLength == 2) {
 | |
|                 *s = nsCRT::ToUpper(*s);
 | |
|                 *(s + 1) = nsCRT::ToUpper(*(s + 1));
 | |
|             } else if (subTagLength == 4) {
 | |
|                 *s = nsCRT::ToUpper(*s);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         s = subTagEnd;
 | |
|         if (*s != '\0') {
 | |
|             s++;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /**
 | |
|  *  Allocates a C string into that contains a ISO 639 language list
 | |
|  *  notated with HTTP "q" values for output with a HTTP Accept-Language
 | |
|  *  header. Previous q values will be stripped because the order of
 | |
|  *  the langs imply the q value. The q values are calculated by dividing
 | |
|  *  1.0 amongst the number of languages present.
 | |
|  *
 | |
|  *  Ex: passing: "en, ja"
 | |
|  *      returns: "en,ja;q=0.5"
 | |
|  *
 | |
|  *      passing: "en, ja, fr_CA"
 | |
|  *      returns: "en,ja;q=0.7,fr_CA;q=0.3"
 | |
|  */
 | |
| static nsresult
 | |
| PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLanguages)
 | |
| {
 | |
|     if (!i_AcceptLanguages)
 | |
|         return NS_OK;
 | |
| 
 | |
|     uint32_t n, count_n, size, wrote;
 | |
|     double q, dec;
 | |
|     char *p, *p2, *token, *q_Accept, *o_Accept;
 | |
|     const char *comma;
 | |
|     int32_t available;
 | |
| 
 | |
|     o_Accept = strdup(i_AcceptLanguages);
 | |
|     if (!o_Accept)
 | |
|         return NS_ERROR_OUT_OF_MEMORY;
 | |
|     for (p = o_Accept, n = size = 0; '\0' != *p; p++) {
 | |
|         if (*p == ',') n++;
 | |
|             size++;
 | |
|     }
 | |
| 
 | |
|     available = size + ++n * 11 + 1;
 | |
|     q_Accept = new char[available];
 | |
|     if (!q_Accept) {
 | |
|         free(o_Accept);
 | |
|         return NS_ERROR_OUT_OF_MEMORY;
 | |
|     }
 | |
|     *q_Accept = '\0';
 | |
|     q = 1.0;
 | |
|     dec = q / (double) n;
 | |
|     count_n = 0;
 | |
|     p2 = q_Accept;
 | |
|     for (token = nsCRT::strtok(o_Accept, ",", &p);
 | |
|          token != (char *) 0;
 | |
|          token = nsCRT::strtok(p, ",", &p))
 | |
|     {
 | |
|         token = net_FindCharNotInSet(token, HTTP_LWS);
 | |
|         char* trim;
 | |
|         trim = net_FindCharInSet(token, ";" HTTP_LWS);
 | |
|         if (trim != (char*)0)  // remove "; q=..." if present
 | |
|             *trim = '\0';
 | |
| 
 | |
|         if (*token != '\0') {
 | |
|             CanonicalizeLanguageTag(token);
 | |
| 
 | |
|             comma = count_n++ != 0 ? "," : ""; // delimiter if not first item
 | |
|             uint32_t u = QVAL_TO_UINT(q);
 | |
| 
 | |
|             // Only display q-value if less than 1.00.
 | |
|             if (u < 100) {
 | |
|                 const char *qval_str;
 | |
| 
 | |
|                 // With a small number of languages, one decimal place is enough to prevent duplicate q-values.
 | |
|                 // Also, trailing zeroes do not add any information, so they can be removed.
 | |
|                 if ((n < 10) || ((u % 10) == 0)) {
 | |
|                     u = (u + 5) / 10;
 | |
|                     qval_str = "%s%s;q=0.%u";
 | |
|                 } else {
 | |
|                     // Values below 10 require zero padding.
 | |
|                     qval_str = "%s%s;q=0.%02u";
 | |
|                 }
 | |
| 
 | |
|                 wrote = snprintf(p2, available, qval_str, comma, token, u);
 | |
|             } else {
 | |
|                 wrote = snprintf(p2, available, "%s%s", comma, token);
 | |
|             }
 | |
| 
 | |
|             q -= dec;
 | |
|             p2 += wrote;
 | |
|             available -= wrote;
 | |
|             MOZ_ASSERT(available > 0, "allocated string not long enough");
 | |
|         }
 | |
|     }
 | |
|     free(o_Accept);
 | |
| 
 | |
|     o_AcceptLanguages.Assign((const char *) q_Accept);
 | |
|     delete [] q_Accept;
 | |
| 
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages)
 | |
| {
 | |
|     nsAutoCString buf;
 | |
|     nsresult rv = PrepareAcceptLanguages(aAcceptLanguages, buf);
 | |
|     if (NS_SUCCEEDED(rv))
 | |
|         mAcceptLanguages.Assign(buf);
 | |
|     return rv;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::SetAccept(const char *aAccept)
 | |
| {
 | |
|     mAccept = aAccept;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings, bool isSecure)
 | |
| {
 | |
|     if (isSecure) {
 | |
|         mHttpsAcceptEncodings = aAcceptEncodings;
 | |
|     } else {
 | |
|         // use legacy list if a secure override is not specified
 | |
|         mHttpAcceptEncodings = aAcceptEncodings;
 | |
|         if (mHttpsAcceptEncodings.IsEmpty()) {
 | |
|             mHttpsAcceptEncodings = aAcceptEncodings;
 | |
|         }
 | |
|     }
 | |
|       
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // nsHttpHandler::nsISupports
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(nsHttpHandler,
 | |
|                   nsIHttpProtocolHandler,
 | |
|                   nsIProxiedProtocolHandler,
 | |
|                   nsIProtocolHandler,
 | |
|                   nsIObserver,
 | |
|                   nsISupportsWeakReference,
 | |
|                   nsISpeculativeConnect)
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // nsHttpHandler::nsIProtocolHandler
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetScheme(nsACString &aScheme)
 | |
| {
 | |
|     aScheme.AssignLiteral("http");
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetDefaultPort(int32_t *result)
 | |
| {
 | |
|     *result = NS_HTTP_DEFAULT_PORT;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetProtocolFlags(uint32_t *result)
 | |
| {
 | |
|     *result = NS_HTTP_PROTOCOL_FLAGS;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::NewURI(const nsACString &aSpec,
 | |
|                       const char *aCharset,
 | |
|                       nsIURI *aBaseURI,
 | |
|                       nsIURI **aURI)
 | |
| {
 | |
|     return mozilla::net::NewURI(aSpec, aCharset, aBaseURI, NS_HTTP_DEFAULT_PORT, aURI);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::NewChannel2(nsIURI* uri,
 | |
|                            nsILoadInfo* aLoadInfo,
 | |
|                            nsIChannel** result)
 | |
| {
 | |
|     LOG(("nsHttpHandler::NewChannel\n"));
 | |
| 
 | |
|     NS_ENSURE_ARG_POINTER(uri);
 | |
|     NS_ENSURE_ARG_POINTER(result);
 | |
| 
 | |
|     bool isHttp = false, isHttps = false;
 | |
| 
 | |
|     // Verify that we have been given a valid scheme
 | |
|     nsresult rv = uri->SchemeIs("http", &isHttp);
 | |
|     if (NS_FAILED(rv)) return rv;
 | |
|     if (!isHttp) {
 | |
|         rv = uri->SchemeIs("https", &isHttps);
 | |
|         if (NS_FAILED(rv)) return rv;
 | |
|         if (!isHttps) {
 | |
|             NS_WARNING("Invalid URI scheme");
 | |
|             return NS_ERROR_UNEXPECTED;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return NewProxiedChannel2(uri, nullptr, 0, nullptr, aLoadInfo, result);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
 | |
| {
 | |
|     return NewChannel2(uri, nullptr, result);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
 | |
| {
 | |
|     // don't override anything.
 | |
|     *_retval = false;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // nsHttpHandler::nsIProxiedProtocolHandler
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::NewProxiedChannel2(nsIURI *uri,
 | |
|                                   nsIProxyInfo* givenProxyInfo,
 | |
|                                   uint32_t proxyResolveFlags,
 | |
|                                   nsIURI *proxyURI,
 | |
|                                   nsILoadInfo* aLoadInfo,
 | |
|                                   nsIChannel** result)
 | |
| {
 | |
|     RefPtr<HttpBaseChannel> httpChannel;
 | |
| 
 | |
|     LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
 | |
|         givenProxyInfo));
 | |
| 
 | |
|     nsCOMPtr<nsProxyInfo> proxyInfo;
 | |
|     if (givenProxyInfo) {
 | |
|         proxyInfo = do_QueryInterface(givenProxyInfo);
 | |
|         NS_ENSURE_ARG(proxyInfo);
 | |
|     }
 | |
| 
 | |
|     bool https;
 | |
|     nsresult rv = uri->SchemeIs("https", &https);
 | |
|     if (NS_FAILED(rv))
 | |
|         return rv;
 | |
| 
 | |
|     if (IsNeckoChild()) {
 | |
|         httpChannel = new HttpChannelChild();
 | |
|     } else {
 | |
|         httpChannel = new nsHttpChannel();
 | |
|     }
 | |
| 
 | |
|     uint32_t caps = mCapabilities;
 | |
| 
 | |
|     if (https) {
 | |
|         // enable pipelining over SSL if requested
 | |
|         if (mPipeliningOverSSL)
 | |
|             caps |= NS_HTTP_ALLOW_PIPELINING;
 | |
|     }
 | |
| 
 | |
|     if (!IsNeckoChild()) {
 | |
|         // HACK: make sure PSM gets initialized on the main thread.
 | |
|         net_EnsurePSMInit();
 | |
|     }
 | |
| 
 | |
|     rv = httpChannel->Init(uri, caps, proxyInfo, proxyResolveFlags, proxyURI);
 | |
|     if (NS_FAILED(rv))
 | |
|         return rv;
 | |
| 
 | |
|     // set the loadInfo on the new channel
 | |
|     rv = httpChannel->SetLoadInfo(aLoadInfo);
 | |
|     if (NS_FAILED(rv)) {
 | |
|         return rv;
 | |
|     }
 | |
| 
 | |
|     httpChannel.forget(result);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::NewProxiedChannel(nsIURI *uri,
 | |
|                                  nsIProxyInfo* givenProxyInfo,
 | |
|                                  uint32_t proxyResolveFlags,
 | |
|                                  nsIURI *proxyURI,
 | |
|                                  nsIChannel **result)
 | |
| {
 | |
|     return NewProxiedChannel2(uri, givenProxyInfo,
 | |
|                               proxyResolveFlags, proxyURI,
 | |
|                               nullptr, result);
 | |
| }
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // nsHttpHandler::nsIHttpProtocolHandler
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetUserAgent(nsACString &value)
 | |
| {
 | |
|     value = UserAgent();
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetAppName(nsACString &value)
 | |
| {
 | |
|     value = mLegacyAppName;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetAppVersion(nsACString &value)
 | |
| {
 | |
|     value = mLegacyAppVersion;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetPlatform(nsACString &value)
 | |
| {
 | |
|     value = mPlatform;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetOscpu(nsACString &value)
 | |
| {
 | |
|     value = mOscpu;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::GetMisc(nsACString &value)
 | |
| {
 | |
|     value = mMisc;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // nsHttpHandler::nsIObserver
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::Observe(nsISupports *subject,
 | |
|                        const char *topic,
 | |
|                        const char16_t *data)
 | |
| {
 | |
|     MOZ_ASSERT(NS_IsMainThread());
 | |
|     LOG(("nsHttpHandler::Observe [topic=\"%s\"]\n", topic));
 | |
| 
 | |
|     if (!strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
 | |
|         nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
 | |
|         if (prefBranch)
 | |
|             PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
 | |
|     } else if (!strcmp(topic, "profile-change-net-teardown") ||
 | |
|                !strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) ) {
 | |
| 
 | |
|         mHandlerActive = false;
 | |
| 
 | |
|         // clear cache of all authentication credentials.
 | |
|         mAuthCache.ClearAll();
 | |
|         mPrivateAuthCache.ClearAll();
 | |
|         if (mWifiTickler)
 | |
|             mWifiTickler->Cancel();
 | |
| 
 | |
|         // Inform nsIOService that network is tearing down.
 | |
|         gIOService->SetHttpHandlerAlreadyShutingDown();
 | |
| 
 | |
|         ShutdownConnectionManager();
 | |
| 
 | |
|         // need to reset the session start time since cache validation may
 | |
|         // depend on this value.
 | |
|         mSessionStartTime = NowInSeconds();
 | |
| 
 | |
|         if (!mDoNotTrackEnabled) {
 | |
|             Telemetry::Accumulate(Telemetry::DNT_USAGE, 2);
 | |
|         } else {
 | |
|             Telemetry::Accumulate(Telemetry::DNT_USAGE, 1);
 | |
|         }
 | |
|     } else if (!strcmp(topic, "profile-change-net-restore")) {
 | |
|         // initialize connection manager
 | |
|         InitConnectionMgr();
 | |
|     } else if (!strcmp(topic, "net:clear-active-logins")) {
 | |
|         mAuthCache.ClearAll();
 | |
|         mPrivateAuthCache.ClearAll();
 | |
|     } else if (!strcmp(topic, "net:prune-dead-connections")) {
 | |
|         if (mConnMgr) {
 | |
|             mConnMgr->PruneDeadConnections();
 | |
|         }
 | |
|     } else if (!strcmp(topic, "net:prune-all-connections")) {
 | |
|         if (mConnMgr) {
 | |
|             mConnMgr->DoShiftReloadConnectionCleanup(nullptr);
 | |
|             mConnMgr->PruneDeadConnections();
 | |
|         }
 | |
|     } else if (!strcmp(topic, "net:failed-to-process-uri-content")) {
 | |
|         nsCOMPtr<nsIURI> uri = do_QueryInterface(subject);
 | |
|         if (uri && mConnMgr) {
 | |
|             mConnMgr->ReportFailedToProcess(uri);
 | |
|         }
 | |
|     } else if (!strcmp(topic, "last-pb-context-exited")) {
 | |
|         mPrivateAuthCache.ClearAll();
 | |
|         if (mConnMgr) {
 | |
|             mConnMgr->ClearAltServiceMappings();
 | |
|         }
 | |
|     } else if (!strcmp(topic, "webapps-clear-data")) {
 | |
|         if (mConnMgr) {
 | |
|             mConnMgr->ClearAltServiceMappings();
 | |
|         }
 | |
|     } else if (!strcmp(topic, "browser:purge-session-history")) {
 | |
|         if (mConnMgr) {
 | |
|             if (gSocketTransportService) {
 | |
|                 nsCOMPtr<nsIRunnable> event =
 | |
|                     NewRunnableMethod(mConnMgr,
 | |
|                                       &nsHttpConnectionMgr::ClearConnectionHistory);
 | |
|                 gSocketTransportService->Dispatch(event, NS_DISPATCH_NORMAL);
 | |
|             }
 | |
|             mConnMgr->ClearAltServiceMappings();
 | |
|         }
 | |
|     } else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
 | |
|         nsAutoCString converted = NS_ConvertUTF16toUTF8(data);
 | |
|         if (!strcmp(converted.get(), NS_NETWORK_LINK_DATA_CHANGED)) {
 | |
|             if (mConnMgr) {
 | |
|                 mConnMgr->PruneDeadConnections();
 | |
|                 mConnMgr->VerifyTraffic();
 | |
|             }
 | |
|         }
 | |
|     } else if (!strcmp(topic, "application-background")) {
 | |
|         // going to the background on android means we should close
 | |
|         // down idle connections for power conservation
 | |
|         if (mConnMgr) {
 | |
|             mConnMgr->DoShiftReloadConnectionCleanup(nullptr);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| // nsISpeculativeConnect
 | |
| 
 | |
| nsresult
 | |
| nsHttpHandler::SpeculativeConnectInternal(nsIURI *aURI,
 | |
|                                           nsIInterfaceRequestor *aCallbacks,
 | |
|                                           bool anonymous)
 | |
| {
 | |
|     if (IsNeckoChild()) {
 | |
|         ipc::URIParams params;
 | |
|         SerializeURI(aURI, params);
 | |
|         gNeckoChild->SendSpeculativeConnect(params, anonymous);
 | |
|         return NS_OK;
 | |
|     }
 | |
| 
 | |
|     if (!mHandlerActive)
 | |
|         return NS_OK;
 | |
| 
 | |
|     MOZ_ASSERT(NS_IsMainThread());
 | |
|     nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
 | |
|     if (mDebugObservations && obsService) {
 | |
|         // this is basically used for test coverage of an otherwise 'hintable' feature
 | |
|         nsAutoCString spec;
 | |
|         aURI->GetSpec(spec);
 | |
|         spec.Append(anonymous ? NS_LITERAL_CSTRING("[A]") : NS_LITERAL_CSTRING("[.]"));
 | |
|         obsService->NotifyObservers(nullptr,
 | |
|                                     "speculative-connect-request",
 | |
|                                     NS_ConvertUTF8toUTF16(spec).get());
 | |
|         if (!IsNeckoChild() && gNeckoParent) {
 | |
|             Unused << gNeckoParent->SendSpeculativeConnectRequest(spec);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     nsISiteSecurityService* sss = gHttpHandler->GetSSService();
 | |
|     bool isStsHost = false;
 | |
|     if (!sss)
 | |
|         return NS_OK;
 | |
| 
 | |
|     nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(aCallbacks);
 | |
|     uint32_t flags = 0;
 | |
|     if (loadContext && loadContext->UsePrivateBrowsing())
 | |
|         flags |= nsISocketProvider::NO_PERMANENT_STORAGE;
 | |
|     nsCOMPtr<nsIURI> clone;
 | |
|     if (NS_SUCCEEDED(sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS,
 | |
|                                       aURI, flags, &isStsHost)) && isStsHost) {
 | |
|         if (NS_SUCCEEDED(NS_GetSecureUpgradedURI(aURI,
 | |
|                                                  getter_AddRefs(clone)))) {
 | |
|             aURI = clone.get();
 | |
|             // (NOTE: We better make sure |clone| stays alive until the end
 | |
|             // of the function now, since our aURI arg now points to it!)
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     nsAutoCString scheme;
 | |
|     nsresult rv = aURI->GetScheme(scheme);
 | |
|     if (NS_FAILED(rv))
 | |
|         return rv;
 | |
| 
 | |
|     // If this is HTTPS, make sure PSM is initialized as the channel
 | |
|     // creation path may have been bypassed
 | |
|     if (scheme.EqualsLiteral("https")) {
 | |
|         if (!IsNeckoChild()) {
 | |
|             // make sure PSM gets initialized on the main thread.
 | |
|             net_EnsurePSMInit();
 | |
|         }
 | |
|     }
 | |
|     // Ensure that this is HTTP or HTTPS, otherwise we don't do preconnect here
 | |
|     else if (!scheme.EqualsLiteral("http"))
 | |
|         return NS_ERROR_UNEXPECTED;
 | |
| 
 | |
|     // Construct connection info object
 | |
|     bool usingSSL = false;
 | |
|     rv = aURI->SchemeIs("https", &usingSSL);
 | |
|     if (NS_FAILED(rv))
 | |
|         return rv;
 | |
| 
 | |
|     nsAutoCString host;
 | |
|     rv = aURI->GetAsciiHost(host);
 | |
|     if (NS_FAILED(rv))
 | |
|         return rv;
 | |
| 
 | |
|     int32_t port = -1;
 | |
|     rv = aURI->GetPort(&port);
 | |
|     if (NS_FAILED(rv))
 | |
|         return rv;
 | |
| 
 | |
|     nsAutoCString username;
 | |
|     aURI->GetUsername(username);
 | |
| 
 | |
|     nsHttpConnectionInfo *ci =
 | |
|         new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr, usingSSL);
 | |
|     ci->SetAnonymous(anonymous);
 | |
| 
 | |
|     return SpeculativeConnect(ci, aCallbacks);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::SpeculativeConnect(nsIURI *aURI,
 | |
|                                   nsIInterfaceRequestor *aCallbacks)
 | |
| {
 | |
|     return SpeculativeConnectInternal(aURI, aCallbacks, false);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpHandler::SpeculativeAnonymousConnect(nsIURI *aURI,
 | |
|                                            nsIInterfaceRequestor *aCallbacks)
 | |
| {
 | |
|     return SpeculativeConnectInternal(aURI, aCallbacks, true);
 | |
| }
 | |
| 
 | |
| void
 | |
| nsHttpHandler::TickleWifi(nsIInterfaceRequestor *cb)
 | |
| {
 | |
|     if (!cb || !mWifiTickler)
 | |
|         return;
 | |
| 
 | |
|     // If B2G requires a similar mechanism nsINetworkManager, currently only avail
 | |
|     // on B2G, contains the necessary information on wifi and gateway
 | |
| 
 | |
|     nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(cb);
 | |
|     nsCOMPtr<nsPIDOMWindowOuter> piWindow = do_QueryInterface(domWindow);
 | |
|     if (!piWindow)
 | |
|         return;
 | |
| 
 | |
|     nsCOMPtr<nsIDOMNavigator> domNavigator = piWindow->GetNavigator();
 | |
|     nsCOMPtr<nsIMozNavigatorNetwork> networkNavigator =
 | |
|         do_QueryInterface(domNavigator);
 | |
|     if (!networkNavigator)
 | |
|         return;
 | |
| 
 | |
|     nsCOMPtr<nsINetworkProperties> networkProperties;
 | |
|     networkNavigator->GetProperties(getter_AddRefs(networkProperties));
 | |
|     if (!networkProperties)
 | |
|         return;
 | |
| 
 | |
|     uint32_t gwAddress;
 | |
|     bool isWifi;
 | |
|     nsresult rv;
 | |
| 
 | |
|     rv = networkProperties->GetDhcpGateway(&gwAddress);
 | |
|     if (NS_SUCCEEDED(rv))
 | |
|         rv = networkProperties->GetIsWifi(&isWifi);
 | |
|     if (NS_FAILED(rv))
 | |
|         return;
 | |
| 
 | |
|     if (!gwAddress || !isWifi)
 | |
|         return;
 | |
| 
 | |
|     mWifiTickler->SetIPV4Address(gwAddress);
 | |
|     mWifiTickler->Tickle();
 | |
| }
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| // nsHttpsHandler implementation
 | |
| //-----------------------------------------------------------------------------
 | |
| 
 | |
| NS_IMPL_ISUPPORTS(nsHttpsHandler,
 | |
|                   nsIHttpProtocolHandler,
 | |
|                   nsIProxiedProtocolHandler,
 | |
|                   nsIProtocolHandler,
 | |
|                   nsISupportsWeakReference,
 | |
|                   nsISpeculativeConnect)
 | |
| 
 | |
| nsresult
 | |
| nsHttpsHandler::Init()
 | |
| {
 | |
|     nsCOMPtr<nsIProtocolHandler> httpHandler(
 | |
|             do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http"));
 | |
|     MOZ_ASSERT(httpHandler.get() != nullptr);
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpsHandler::GetScheme(nsACString &aScheme)
 | |
| {
 | |
|     aScheme.AssignLiteral("https");
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpsHandler::GetDefaultPort(int32_t *aPort)
 | |
| {
 | |
|     *aPort = NS_HTTPS_DEFAULT_PORT;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpsHandler::GetProtocolFlags(uint32_t *aProtocolFlags)
 | |
| {
 | |
|     *aProtocolFlags = NS_HTTP_PROTOCOL_FLAGS | URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpsHandler::NewURI(const nsACString &aSpec,
 | |
|                        const char *aOriginCharset,
 | |
|                        nsIURI *aBaseURI,
 | |
|                        nsIURI **_retval)
 | |
| {
 | |
|     return mozilla::net::NewURI(aSpec, aOriginCharset, aBaseURI, NS_HTTPS_DEFAULT_PORT, _retval);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpsHandler::NewChannel2(nsIURI* aURI,
 | |
|                             nsILoadInfo* aLoadInfo,
 | |
|                             nsIChannel** _retval)
 | |
| {
 | |
|     MOZ_ASSERT(gHttpHandler);
 | |
|     if (!gHttpHandler)
 | |
|       return NS_ERROR_UNEXPECTED;
 | |
|     return gHttpHandler->NewChannel2(aURI, aLoadInfo, _retval);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpsHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
 | |
| {
 | |
|     return NewChannel2(aURI, nullptr, _retval);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsHttpsHandler::AllowPort(int32_t aPort, const char *aScheme, bool *_retval)
 | |
| {
 | |
|     // don't override anything.
 | |
|     *_retval = false;
 | |
|     return NS_OK;
 | |
| }
 | |
| 
 | |
| void
 | |
| nsHttpHandler::ShutdownConnectionManager()
 | |
| {
 | |
|     // ensure connection manager is shutdown
 | |
|     if (mConnMgr) {
 | |
|         mConnMgr->Shutdown();
 | |
|     }
 | |
| }
 | |
| 
 | |
| } // namespace net
 | |
| } // namespace mozilla
 | 
