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