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