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/. */
8 #include "nsHttpHandler.h"
9 #include "nsHttpChannel.h"
10 #include "nsHttpConnection.h"
11 #include "nsHttpResponseHead.h"
12 #include "nsHttpTransaction.h"
13 #include "nsHttpAuthCache.h"
14 #include "nsStandardURL.h"
15 #include "nsIHttpChannel.h"
17 #include "nsIStandardURL.h"
18 #include "nsICacheService.h"
19 #include "nsICategoryManager.h"
20 #include "nsCategoryManagerUtils.h"
21 #include "nsICacheService.h"
22 #include "nsIPrefService.h"
23 #include "nsIPrefBranch.h"
24 #include "nsIPrefLocalizedString.h"
25 #include "nsISocketProviderService.h"
26 #include "nsISocketProvider.h"
27 #include "nsPrintfCString.h"
31 #include "nsReadableUtils.h"
32 #include "nsQuickSort.h"
33 #include "nsNetUtil.h"
34 #include "nsIOService.h"
35 #include "nsAsyncRedirectVerifyHelper.h"
36 #include "nsSocketTransportService2.h"
37 #include "nsAlgorithm.h"
38 #include "ASpdySession.h"
40 #include "nsIXULAppInfo.h"
42 #include "mozilla/net/NeckoChild.h"
45 #include <sys/utsname.h>
52 #if defined(XP_MACOSX)
53 #include <CoreServices/CoreServices.h>
61 //-----------------------------------------------------------------------------
62 using namespace mozilla
;
63 using namespace mozilla::net
;
64 #include "mozilla/net/HttpChannelChild.h"
66 #include "mozilla/FunctionTimer.h"
69 // defined by the socket transport service while active
70 extern PRThread
*gSocketThread
;
73 static NS_DEFINE_CID(kIOServiceCID
, NS_IOSERVICE_CID
);
74 static NS_DEFINE_CID(kStreamConverterServiceCID
, NS_STREAMCONVERTERSERVICE_CID
);
75 static NS_DEFINE_CID(kCookieServiceCID
, NS_COOKIESERVICE_CID
);
76 static NS_DEFINE_CID(kCacheServiceCID
, NS_CACHESERVICE_CID
);
77 static NS_DEFINE_CID(kSocketProviderServiceCID
, NS_SOCKETPROVIDERSERVICE_CID
);
79 #define UA_PREF_PREFIX "general.useragent."
81 #define UA_SPARE_PLATFORM
84 #define HTTP_PREF_PREFIX "network.http."
85 #define INTL_ACCEPT_LANGUAGES "intl.accept_languages"
86 #define NETWORK_ENABLEIDN "network.enableIDN"
87 #define BROWSER_PREF_PREFIX "browser.cache."
88 #define DONOTTRACK_HEADER_ENABLED "privacy.donottrackheader.enabled"
89 #define TELEMETRY_ENABLED "toolkit.telemetry.enabled"
90 #define ALLOW_EXPERIMENTS "network.allow-experiments"
92 #define UA_PREF(_pref) UA_PREF_PREFIX _pref
93 #define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
94 #define BROWSER_PREF(_pref) BROWSER_PREF_PREFIX _pref
96 #define NS_HTTP_PROTOCOL_FLAGS (URI_STD | ALLOWS_PROXY | ALLOWS_PROXY_HTTP | URI_LOADABLE_BY_ANYONE)
98 //-----------------------------------------------------------------------------
101 NewURI(const nsACString
&aSpec
,
102 const char *aCharset
,
104 PRInt32 aDefaultPort
,
107 nsStandardURL
*url
= new nsStandardURL();
109 return NS_ERROR_OUT_OF_MEMORY
;
112 nsresult rv
= url
->Init(nsIStandardURL::URLTYPE_AUTHORITY
,
113 aDefaultPort
, aSpec
, aCharset
, aBaseURI
);
119 *aURI
= url
; // no QI needed
123 //-----------------------------------------------------------------------------
124 // nsHttpHandler <public>
125 //-----------------------------------------------------------------------------
127 nsHttpHandler
*gHttpHandler
= nsnull
;
129 nsHttpHandler::nsHttpHandler()
131 , mHttpVersion(NS_HTTP_VERSION_1_1
)
132 , mProxyHttpVersion(NS_HTTP_VERSION_1_1
)
133 , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE
)
134 , mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE
)
135 , mReferrerLevel(0xff) // by default we always send a referrer
136 , mFastFallbackToIPv4(false)
137 , mIdleTimeout(PR_SecondsToInterval(10))
138 , mSpdyTimeout(PR_SecondsToInterval(180))
139 , mMaxRequestAttempts(10)
140 , mMaxRequestDelay(10)
141 , mIdleSynTimeout(250)
142 , mMaxConnections(24)
143 , mMaxConnectionsPerServer(8)
144 , mMaxPersistentConnectionsPerServer(2)
145 , mMaxPersistentConnectionsPerProxy(4)
146 , mMaxPipelinedRequests(32)
147 , mMaxOptimisticPipelinedRequests(4)
148 , mPipelineAggressive(false)
149 , mMaxPipelineObjectSize(300000)
150 , mPipelineRescheduleOnTimeout(true)
151 , mPipelineRescheduleTimeout(PR_MillisecondsToInterval(1500))
152 , mPipelineReadTimeout(PR_MillisecondsToInterval(30000))
153 , mRedirectionLimit(10)
154 , mPhishyUserPassLength(1)
156 , mPipeliningOverSSL(false)
157 , mEnforceAssocReq(false)
158 , mLastUniqueID(NowInSeconds())
159 , mSessionStartTime(0)
160 , mLegacyAppName("Mozilla")
161 , mLegacyAppVersion("5.0")
163 , mUserAgentIsDirty(true)
165 , mPromptTempRedirect(true)
166 , mSendSecureXSiteReferrer(true)
167 , mEnablePersistentHttpsCaching(false)
168 , mDoNotTrackEnabled(false)
169 , mTelemetryEnabled(false)
170 , mAllowExperiments(true)
174 , mCoalesceSpdy(true)
175 , mUseAlternateProtocol(false)
176 , mSpdySendingChunkSize(ASpdySession::kSendingChunkSize
)
177 , mSpdyPingThreshold(PR_SecondsToInterval(44))
178 , mSpdyPingTimeout(PR_SecondsToInterval(8))
180 #if defined(PR_LOGGING)
181 gHttpLog
= PR_NewLogModule("nsHttp");
184 LOG(("Creating nsHttpHandler [this=%x].\n", this));
186 NS_ASSERTION(!gHttpHandler
, "HTTP handler already created!");
190 nsHttpHandler::~nsHttpHandler()
192 LOG(("Deleting nsHttpHandler [this=%x]\n", this));
194 // make sure the connection manager is shutdown
196 mConnMgr
->Shutdown();
197 NS_RELEASE(mConnMgr
);
200 // Note: don't call NeckoChild::DestroyNeckoChild() here, as it's too late
201 // and it'll segfault. NeckoChild will get cleaned up by process exit.
203 nsHttp::DestroyAtomTable();
205 gHttpHandler
= nsnull
;
209 nsHttpHandler::Init()
215 LOG(("nsHttpHandler::Init\n"));
217 rv
= nsHttp::CreateAtomTable();
221 mIOService
= do_GetService(NS_IOSERVICE_CONTRACTID
, &rv
);
223 NS_WARNING("unable to continue without io service");
228 NeckoChild::InitNeckoChild();
230 InitUserAgentComponents();
232 // monitor some preference changes
233 nsCOMPtr
<nsIPrefBranch
> prefBranch
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
235 prefBranch
->AddObserver(HTTP_PREF_PREFIX
, this, true);
236 prefBranch
->AddObserver(UA_PREF_PREFIX
, this, true);
237 prefBranch
->AddObserver(INTL_ACCEPT_LANGUAGES
, this, true);
238 prefBranch
->AddObserver(NETWORK_ENABLEIDN
, this, true);
239 prefBranch
->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true);
240 prefBranch
->AddObserver(DONOTTRACK_HEADER_ENABLED
, this, true);
241 prefBranch
->AddObserver(TELEMETRY_ENABLED
, this, true);
243 PrefsChanged(prefBranch
, nsnull
);
246 mMisc
.AssignLiteral("rv:" MOZILLA_UAVERSION
);
248 nsCOMPtr
<nsIXULAppInfo
> appInfo
=
249 do_GetService("@mozilla.org/xre/app-info;1");
251 mAppName
.AssignLiteral(MOZ_APP_UA_NAME
);
252 if (mAppName
.Length() == 0 && appInfo
) {
253 // Try to get the UA name from appInfo, falling back to the name
254 appInfo
->GetUAName(mAppName
);
255 if (mAppName
.Length() == 0) {
256 appInfo
->GetName(mAppName
);
258 appInfo
->GetVersion(mAppVersion
);
259 mAppName
.StripChars(" ()<>@,;:\\\"/[]?={}");
261 mAppVersion
.AssignLiteral(MOZ_APP_UA_VERSION
);
265 // dump user agent prefs
266 LOG(("> legacy-app-name = %s\n", mLegacyAppName
.get()));
267 LOG(("> legacy-app-version = %s\n", mLegacyAppVersion
.get()));
268 LOG(("> platform = %s\n", mPlatform
.get()));
269 LOG(("> oscpu = %s\n", mOscpu
.get()));
270 LOG(("> misc = %s\n", mMisc
.get()));
271 LOG(("> product = %s\n", mProduct
.get()));
272 LOG(("> product-sub = %s\n", mProductSub
.get()));
273 LOG(("> app-name = %s\n", mAppName
.get()));
274 LOG(("> app-version = %s\n", mAppVersion
.get()));
275 LOG(("> compat-firefox = %s\n", mCompatFirefox
.get()));
276 LOG(("> user-agent = %s\n", UserAgent().get()));
279 mSessionStartTime
= NowInSeconds();
281 rv
= mAuthCache
.Init();
282 if (NS_FAILED(rv
)) return rv
;
284 rv
= InitConnectionMgr();
285 if (NS_FAILED(rv
)) return rv
;
287 mProductSub
.AssignLiteral(MOZILLA_UAVERSION
);
289 // Startup the http category
290 // Bring alive the objects in the http-protocol-startup category
291 NS_CreateServicesFromCategory(NS_HTTP_STARTUP_CATEGORY
,
292 static_cast<nsISupports
*>(static_cast<void*>(this)),
293 NS_HTTP_STARTUP_TOPIC
);
295 mObserverService
= mozilla::services::GetObserverService();
296 if (mObserverService
) {
297 mObserverService
->AddObserver(this, "profile-change-net-teardown", true);
298 mObserverService
->AddObserver(this, "profile-change-net-restore", true);
299 mObserverService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, true);
300 mObserverService
->AddObserver(this, "net:clear-active-logins", true);
301 mObserverService
->AddObserver(this, "net:prune-dead-connections", true);
302 mObserverService
->AddObserver(this, "net:failed-to-process-uri-content", true);
309 nsHttpHandler::InitConnectionMgr()
316 mConnMgr
= new nsHttpConnectionMgr();
318 return NS_ERROR_OUT_OF_MEMORY
;
322 rv
= mConnMgr
->Init(mMaxConnections
,
323 mMaxConnectionsPerServer
,
324 mMaxConnectionsPerServer
,
325 mMaxPersistentConnectionsPerServer
,
326 mMaxPersistentConnectionsPerProxy
,
328 mMaxPipelinedRequests
,
329 mMaxOptimisticPipelinedRequests
);
334 nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray
*request
,
340 // Add the "User-Agent" header
341 rv
= request
->SetHeader(nsHttp::User_Agent
, UserAgent());
342 if (NS_FAILED(rv
)) return rv
;
344 // MIME based content negotiation lives!
345 // Add the "Accept" header
346 rv
= request
->SetHeader(nsHttp::Accept
, mAccept
);
347 if (NS_FAILED(rv
)) return rv
;
349 // Add the "Accept-Language" header
350 if (!mAcceptLanguages
.IsEmpty()) {
351 // Add the "Accept-Language" header
352 rv
= request
->SetHeader(nsHttp::Accept_Language
, mAcceptLanguages
);
353 if (NS_FAILED(rv
)) return rv
;
356 // Add the "Accept-Encoding" header
357 rv
= request
->SetHeader(nsHttp::Accept_Encoding
, mAcceptEncodings
);
358 if (NS_FAILED(rv
)) return rv
;
360 // RFC2616 section 19.6.2 states that the "Connection: keep-alive"
361 // and "Keep-alive" request headers should not be sent by HTTP/1.1
362 // user-agents. Otherwise, problems with proxy servers (especially
363 // transparent proxies) can result.
365 // However, we need to send something so that we can use keepalive
366 // with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when
367 // we're talking to an http proxy, and "Connection:" otherwise.
368 // We no longer send the Keep-Alive request header.
370 NS_NAMED_LITERAL_CSTRING(close
, "close");
371 NS_NAMED_LITERAL_CSTRING(keepAlive
, "keep-alive");
373 const nsACString
*connectionType
= &close
;
374 if (caps
& NS_HTTP_ALLOW_KEEPALIVE
) {
375 connectionType
= &keepAlive
;
376 } else if (useProxy
) {
378 request
->SetHeader(nsHttp::Connection
, close
);
381 // Add the "Do-Not-Track" header
382 if (mDoNotTrackEnabled
) {
383 rv
= request
->SetHeader(nsHttp::DoNotTrack
,
384 NS_LITERAL_CSTRING("1"));
385 if (NS_FAILED(rv
)) return rv
;
388 const nsHttpAtom
&header
= useProxy
? nsHttp::Proxy_Connection
389 : nsHttp::Connection
;
390 return request
->SetHeader(header
, *connectionType
);
394 nsHttpHandler::IsAcceptableEncoding(const char *enc
)
399 // HTTP 1.1 allows servers to send x-gzip and x-compress instead
400 // of gzip and compress, for example. So, we'll always strip off
401 // an "x-" prefix before matching the encoding to one we claim
403 if (!PL_strncasecmp(enc
, "x-", 2))
406 return nsHttp::FindToken(mAcceptEncodings
.get(), enc
, HTTP_LWS
",") != nsnull
;
410 nsHttpHandler::GetStreamConverterService(nsIStreamConverterService
**result
)
412 if (!mStreamConvSvc
) {
414 mStreamConvSvc
= do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID
, &rv
);
415 if (NS_FAILED(rv
)) return rv
;
417 *result
= mStreamConvSvc
;
422 nsIStrictTransportSecurityService
*
423 nsHttpHandler::GetSTSService()
426 mSTSService
= do_GetService(NS_STSSERVICE_CONTRACTID
);
431 nsHttpHandler::GetCookieService()
434 mCookieService
= do_GetService(NS_COOKIESERVICE_CONTRACTID
);
435 return mCookieService
;
439 nsHttpHandler::GetIOService(nsIIOService
** result
)
441 NS_ADDREF(*result
= mIOService
);
446 nsHttpHandler::Get32BitsOfPseudoRandom()
448 // only confirm rand seeding on socket thread
449 NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread
, "wrong thread");
451 // rand() provides different amounts of PRNG on different platforms.
452 // 15 or 31 bits are common amounts.
454 PR_STATIC_ASSERT(RAND_MAX
>= 0xfff);
456 #if RAND_MAX < 0xffffU
457 return ((PRUint16
) rand() << 20) |
458 (((PRUint16
) rand() & 0xfff) << 8) |
459 ((PRUint16
) rand() & 0xff);
460 #elif RAND_MAX < 0xffffffffU
461 return ((PRUint16
) rand() << 16) | ((PRUint16
) rand() & 0xffff);
463 return (PRUint32
) rand();
468 nsHttpHandler::NotifyObservers(nsIHttpChannel
*chan
, const char *event
)
470 LOG(("nsHttpHandler::NotifyObservers [chan=%x event=\"%s\"]\n", chan
, event
));
471 if (mObserverService
)
472 mObserverService
->NotifyObservers(chan
, event
, nsnull
);
476 nsHttpHandler::AsyncOnChannelRedirect(nsIChannel
* oldChan
, nsIChannel
* newChan
,
479 // TODO E10S This helper has to be initialized on the other process
480 nsRefPtr
<nsAsyncRedirectVerifyHelper
> redirectCallbackHelper
=
481 new nsAsyncRedirectVerifyHelper();
483 return redirectCallbackHelper
->Init(oldChan
, newChan
, flags
);
486 /* static */ nsresult
487 nsHttpHandler::GenerateHostPort(const nsCString
& host
, PRInt32 port
,
490 return NS_GenerateHostPort(host
, port
, hostLine
);
493 //-----------------------------------------------------------------------------
494 // nsHttpHandler <private>
495 //-----------------------------------------------------------------------------
497 const nsAFlatCString
&
498 nsHttpHandler::UserAgent()
500 if (mUserAgentOverride
) {
501 LOG(("using general.useragent.override : %s\n", mUserAgentOverride
.get()));
502 return mUserAgentOverride
;
505 if (mUserAgentIsDirty
) {
507 mUserAgentIsDirty
= false;
514 nsHttpHandler::BuildUserAgent()
516 LOG(("nsHttpHandler::BuildUserAgent\n"));
518 NS_ASSERTION(!mLegacyAppName
.IsEmpty() &&
519 !mLegacyAppVersion
.IsEmpty() &&
520 !mPlatform
.IsEmpty() &&
522 "HTTP cannot send practical requests without this much");
524 // preallocate to worst-case size, which should always be better
525 // than if we didn't preallocate at all.
526 mUserAgent
.SetCapacity(mLegacyAppName
.Length() +
527 mLegacyAppVersion
.Length() +
528 #ifndef UA_SPARE_PLATFORM
534 mProductSub
.Length() +
536 mAppVersion
.Length() +
537 mCompatFirefox
.Length() +
538 mCompatDevice
.Length() +
541 // Application portion
542 mUserAgent
.Assign(mLegacyAppName
);
544 mUserAgent
+= mLegacyAppVersion
;
547 // Application comment
549 #ifndef UA_SPARE_PLATFORM
550 mUserAgent
+= mPlatform
;
551 mUserAgent
.AppendLiteral("; ");
553 #if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO)
554 if (!mCompatDevice
.IsEmpty()) {
555 mUserAgent
+= mCompatDevice
;
556 mUserAgent
.AppendLiteral("; ");
559 mUserAgent
+= mOscpu
;
560 mUserAgent
.AppendLiteral("; ");
567 mUserAgent
+= mProduct
;
569 mUserAgent
+= mProductSub
;
571 // "Firefox/x.y.z" compatibility token
572 if (!mCompatFirefox
.IsEmpty()) {
574 mUserAgent
+= mCompatFirefox
;
579 mUserAgent
+= mAppName
;
581 mUserAgent
+= mAppVersion
;
585 #define WNT_BASE "Windows NT %ld.%ld"
586 #define W64_PREFIX "; Win64"
590 nsHttpHandler::InitUserAgentComponents()
593 mPlatform
.AssignLiteral(
596 #elif defined(XP_OS2)
598 #elif defined(XP_WIN)
600 #elif defined(XP_MACOSX)
602 #elif defined(MOZ_PLATFORM_MAEMO)
604 #elif defined(MOZ_X11)
611 #if defined(ANDROID) || defined(MOZ_PLATFORM_MAEMO)
612 nsCOMPtr
<nsIPropertyBag2
> infoService
= do_GetService("@mozilla.org/system-info;1");
613 NS_ASSERTION(infoService
, "Could not find a system info service");
615 bool isTablet
= false;
616 infoService
->GetPropertyAsBool(NS_LITERAL_STRING("tablet"), &isTablet
);
618 mCompatDevice
.AssignLiteral("Tablet");
620 mCompatDevice
.AssignLiteral("Mobile");
626 DosQuerySysInfo(QSV_VERSION_MINOR
, QSV_VERSION_MINOR
,
627 &os2ver
, sizeof(os2ver
));
629 mOscpu
.AssignLiteral("2.11");
630 else if (os2ver
== 30)
631 mOscpu
.AssignLiteral("Warp 3");
632 else if (os2ver
== 40)
633 mOscpu
.AssignLiteral("Warp 4");
634 else if (os2ver
== 45)
635 mOscpu
.AssignLiteral("Warp 4.5");
637 #elif defined(XP_WIN)
638 OSVERSIONINFO info
= { sizeof(OSVERSIONINFO
) };
639 if (GetVersionEx(&info
)) {
642 format
= WNT_BASE W64_PREFIX
"; IA64";
643 #elif defined _M_X64 || defined _M_AMD64
644 format
= WNT_BASE W64_PREFIX
"; x64";
646 BOOL isWow64
= FALSE
;
647 if (!IsWow64Process(GetCurrentProcess(), &isWow64
)) {
654 char *buf
= PR_smprintf(format
,
656 info
.dwMinorVersion
);
659 PR_smprintf_free(buf
);
662 #elif defined (XP_MACOSX)
664 mOscpu
.AssignLiteral("PPC Mac OS X");
665 #elif defined(__i386__) || defined(__x86_64__)
666 mOscpu
.AssignLiteral("Intel Mac OS X");
668 SInt32 majorVersion
, minorVersion
;
669 if ((::Gestalt(gestaltSystemVersionMajor
, &majorVersion
) == noErr
) &&
670 (::Gestalt(gestaltSystemVersionMinor
, &minorVersion
) == noErr
)) {
671 mOscpu
+= nsPrintfCString(" %d.%d", majorVersion
, minorVersion
);
673 #elif defined (XP_UNIX)
676 int ret
= uname(&name
);
679 buf
= (char*)name
.sysname
;
681 if (strcmp(name
.machine
, "x86_64") == 0 &&
682 sizeof(void *) == sizeof(PRInt32
)) {
683 // We're running 32-bit code on x86_64. Make this browser
684 // look like it's running on i686 hardware, but append "
685 // (x86_64)" to the end of the oscpu identifier to be able
686 // to differentiate this from someone running 64-bit code
689 buf
+= " i686 on x86_64";
694 // AIX uname returns machine specific info in the uname.machine
695 // field and does not return the cpu type like other platforms.
696 // We use the AIX version and release numbers instead.
697 buf
+= (char*)name
.version
;
699 buf
+= (char*)name
.release
;
701 buf
+= (char*)name
.machine
;
709 mUserAgentIsDirty
= true;
713 nsHttpHandler::MaxSocketCount()
715 PR_CallOnce(&nsSocketTransportService::gMaxCountInitOnce
,
716 nsSocketTransportService::DiscoverMaxCount
);
717 // Don't use the full max count because sockets can be held in
718 // the persistent connection pool for a long time and that could
719 // starve other users.
721 PRUint32 maxCount
= nsSocketTransportService::gMaxCount
;
731 nsHttpHandler::PrefsChanged(nsIPrefBranch
*prefs
, const char *pref
)
736 LOG(("nsHttpHandler::PrefsChanged [pref=%s]\n", pref
));
738 #define PREF_CHANGED(p) ((pref == nsnull) || !PL_strcmp(pref, p))
739 #define MULTI_PREF_CHANGED(p) \
740 ((pref == nsnull) || !PL_strncmp(pref, p, sizeof(p) - 1))
748 if (PREF_CHANGED(UA_PREF("compatMode.firefox"))) {
749 rv
= prefs
->GetBoolPref(UA_PREF("compatMode.firefox"), &cVar
);
750 if (NS_SUCCEEDED(rv
) && cVar
) {
751 mCompatFirefox
.AssignLiteral("Firefox/" MOZ_UA_FIREFOX_VERSION
);
753 mCompatFirefox
.Truncate();
755 mUserAgentIsDirty
= true;
758 // general.useragent.override
759 if (PREF_CHANGED(UA_PREF("override"))) {
760 prefs
->GetCharPref(UA_PREF("override"),
761 getter_Copies(mUserAgentOverride
));
762 mUserAgentIsDirty
= true;
769 if (PREF_CHANGED(HTTP_PREF("keep-alive.timeout"))) {
770 rv
= prefs
->GetIntPref(HTTP_PREF("keep-alive.timeout"), &val
);
771 if (NS_SUCCEEDED(rv
))
772 mIdleTimeout
= PR_SecondsToInterval(clamped(val
, 1, 0xffff));
775 if (PREF_CHANGED(HTTP_PREF("request.max-attempts"))) {
776 rv
= prefs
->GetIntPref(HTTP_PREF("request.max-attempts"), &val
);
777 if (NS_SUCCEEDED(rv
))
778 mMaxRequestAttempts
= (PRUint16
) clamped(val
, 1, 0xffff);
781 if (PREF_CHANGED(HTTP_PREF("request.max-start-delay"))) {
782 rv
= prefs
->GetIntPref(HTTP_PREF("request.max-start-delay"), &val
);
783 if (NS_SUCCEEDED(rv
)) {
784 mMaxRequestDelay
= (PRUint16
) clamped(val
, 0, 0xffff);
786 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_REQUEST_DELAY
,
791 if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
792 rv
= prefs
->GetIntPref(HTTP_PREF("max-connections"), &val
);
793 if (NS_SUCCEEDED(rv
)) {
795 mMaxConnections
= (PRUint16
) clamped((PRUint32
)val
,
796 (PRUint32
)1, MaxSocketCount());
799 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS
,
804 if (PREF_CHANGED(HTTP_PREF("max-connections-per-server"))) {
805 rv
= prefs
->GetIntPref(HTTP_PREF("max-connections-per-server"), &val
);
806 if (NS_SUCCEEDED(rv
)) {
807 mMaxConnectionsPerServer
= (PRUint8
) clamped(val
, 1, 0xff);
809 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS_PER_HOST
,
810 mMaxConnectionsPerServer
);
811 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS_PER_PROXY
,
812 mMaxConnectionsPerServer
);
817 if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-server"))) {
818 rv
= prefs
->GetIntPref(HTTP_PREF("max-persistent-connections-per-server"), &val
);
819 if (NS_SUCCEEDED(rv
)) {
820 mMaxPersistentConnectionsPerServer
= (PRUint8
) clamped(val
, 1, 0xff);
822 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_HOST
,
823 mMaxPersistentConnectionsPerServer
);
827 if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-proxy"))) {
828 rv
= prefs
->GetIntPref(HTTP_PREF("max-persistent-connections-per-proxy"), &val
);
829 if (NS_SUCCEEDED(rv
)) {
830 mMaxPersistentConnectionsPerProxy
= (PRUint8
) clamped(val
, 1, 0xff);
832 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_PROXY
,
833 mMaxPersistentConnectionsPerProxy
);
837 if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
838 rv
= prefs
->GetIntPref(HTTP_PREF("sendRefererHeader"), &val
);
839 if (NS_SUCCEEDED(rv
))
840 mReferrerLevel
= (PRUint8
) clamped(val
, 0, 0xff);
843 if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
844 rv
= prefs
->GetIntPref(HTTP_PREF("redirection-limit"), &val
);
845 if (NS_SUCCEEDED(rv
))
846 mRedirectionLimit
= (PRUint8
) clamped(val
, 0, 0xff);
849 if (PREF_CHANGED(HTTP_PREF("connection-retry-timeout"))) {
850 rv
= prefs
->GetIntPref(HTTP_PREF("connection-retry-timeout"), &val
);
851 if (NS_SUCCEEDED(rv
))
852 mIdleSynTimeout
= (PRUint16
) clamped(val
, 0, 3000);
855 if (PREF_CHANGED(HTTP_PREF("fast-fallback-to-IPv4"))) {
856 rv
= prefs
->GetBoolPref(HTTP_PREF("fast-fallback-to-IPv4"), &cVar
);
857 if (NS_SUCCEEDED(rv
))
858 mFastFallbackToIPv4
= cVar
;
861 if (PREF_CHANGED(HTTP_PREF("version"))) {
862 nsXPIDLCString httpVersion
;
863 prefs
->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion
));
865 if (!PL_strcmp(httpVersion
, "1.1"))
866 mHttpVersion
= NS_HTTP_VERSION_1_1
;
867 else if (!PL_strcmp(httpVersion
, "0.9"))
868 mHttpVersion
= NS_HTTP_VERSION_0_9
;
870 mHttpVersion
= NS_HTTP_VERSION_1_0
;
874 if (PREF_CHANGED(HTTP_PREF("proxy.version"))) {
875 nsXPIDLCString httpVersion
;
876 prefs
->GetCharPref(HTTP_PREF("proxy.version"), getter_Copies(httpVersion
));
878 if (!PL_strcmp(httpVersion
, "1.1"))
879 mProxyHttpVersion
= NS_HTTP_VERSION_1_1
;
881 mProxyHttpVersion
= NS_HTTP_VERSION_1_0
;
882 // it does not make sense to issue a HTTP/0.9 request to a proxy server
886 if (PREF_CHANGED(HTTP_PREF("keep-alive"))) {
887 rv
= prefs
->GetBoolPref(HTTP_PREF("keep-alive"), &cVar
);
888 if (NS_SUCCEEDED(rv
)) {
890 mCapabilities
|= NS_HTTP_ALLOW_KEEPALIVE
;
892 mCapabilities
&= ~NS_HTTP_ALLOW_KEEPALIVE
;
896 if (PREF_CHANGED(HTTP_PREF("proxy.keep-alive"))) {
897 rv
= prefs
->GetBoolPref(HTTP_PREF("proxy.keep-alive"), &cVar
);
898 if (NS_SUCCEEDED(rv
)) {
900 mProxyCapabilities
|= NS_HTTP_ALLOW_KEEPALIVE
;
902 mProxyCapabilities
&= ~NS_HTTP_ALLOW_KEEPALIVE
;
906 if (PREF_CHANGED(HTTP_PREF("pipelining"))) {
907 rv
= prefs
->GetBoolPref(HTTP_PREF("pipelining"), &cVar
);
908 if (NS_SUCCEEDED(rv
)) {
910 mCapabilities
|= NS_HTTP_ALLOW_PIPELINING
;
912 mCapabilities
&= ~NS_HTTP_ALLOW_PIPELINING
;
916 if (PREF_CHANGED(HTTP_PREF("pipelining.maxrequests"))) {
917 rv
= prefs
->GetIntPref(HTTP_PREF("pipelining.maxrequests"), &val
);
918 if (NS_SUCCEEDED(rv
)) {
919 mMaxPipelinedRequests
= clamped(val
, 1, 0xffff);
921 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_PIPELINED_REQUESTS
,
922 mMaxPipelinedRequests
);
926 if (PREF_CHANGED(HTTP_PREF("pipelining.max-optimistic-requests"))) {
928 GetIntPref(HTTP_PREF("pipelining.max-optimistic-requests"), &val
);
929 if (NS_SUCCEEDED(rv
)) {
930 mMaxOptimisticPipelinedRequests
= clamped(val
, 1, 0xffff);
932 mConnMgr
->UpdateParam
933 (nsHttpConnectionMgr::MAX_OPTIMISTIC_PIPELINED_REQUESTS
,
934 mMaxOptimisticPipelinedRequests
);
938 if (PREF_CHANGED(HTTP_PREF("pipelining.aggressive"))) {
939 rv
= prefs
->GetBoolPref(HTTP_PREF("pipelining.aggressive"), &cVar
);
940 if (NS_SUCCEEDED(rv
))
941 mPipelineAggressive
= cVar
;
944 if (PREF_CHANGED(HTTP_PREF("pipelining.maxsize"))) {
945 rv
= prefs
->GetIntPref(HTTP_PREF("pipelining.maxsize"), &val
);
946 if (NS_SUCCEEDED(rv
)) {
947 mMaxPipelineObjectSize
=
948 static_cast<PRInt64
>(clamped(val
, 1000, 100000000));
952 // Determines whether or not to actually reschedule after the
953 // reschedule-timeout has expired
954 if (PREF_CHANGED(HTTP_PREF("pipelining.reschedule-on-timeout"))) {
955 rv
= prefs
->GetBoolPref(HTTP_PREF("pipelining.reschedule-on-timeout"),
957 if (NS_SUCCEEDED(rv
))
958 mPipelineRescheduleOnTimeout
= cVar
;
961 // The amount of time head of line blocking is allowed (in ms)
962 // before the blocked transactions are moved to another pipeline
963 if (PREF_CHANGED(HTTP_PREF("pipelining.reschedule-timeout"))) {
964 rv
= prefs
->GetIntPref(HTTP_PREF("pipelining.reschedule-timeout"),
966 if (NS_SUCCEEDED(rv
)) {
967 mPipelineRescheduleTimeout
=
968 PR_MillisecondsToInterval((PRUint16
) clamped(val
, 500, 0xffff));
972 // The amount of time a pipelined transaction is allowed to wait before
973 // being canceled and retried in a non-pipeline connection
974 if (PREF_CHANGED(HTTP_PREF("pipelining.read-timeout"))) {
975 rv
= prefs
->GetIntPref(HTTP_PREF("pipelining.read-timeout"), &val
);
976 if (NS_SUCCEEDED(rv
)) {
977 mPipelineReadTimeout
=
978 PR_MillisecondsToInterval((PRUint16
) clamped(val
, 5000,
983 if (PREF_CHANGED(HTTP_PREF("pipelining.ssl"))) {
984 rv
= prefs
->GetBoolPref(HTTP_PREF("pipelining.ssl"), &cVar
);
985 if (NS_SUCCEEDED(rv
))
986 mPipeliningOverSSL
= cVar
;
989 if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
990 rv
= prefs
->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar
);
991 if (NS_SUCCEEDED(rv
)) {
993 mProxyCapabilities
|= NS_HTTP_ALLOW_PIPELINING
;
995 mProxyCapabilities
&= ~NS_HTTP_ALLOW_PIPELINING
;
999 if (PREF_CHANGED(HTTP_PREF("qos"))) {
1000 rv
= prefs
->GetIntPref(HTTP_PREF("qos"), &val
);
1001 if (NS_SUCCEEDED(rv
))
1002 mQoSBits
= (PRUint8
) clamped(val
, 0, 0xff);
1005 if (PREF_CHANGED(HTTP_PREF("sendSecureXSiteReferrer"))) {
1006 rv
= prefs
->GetBoolPref(HTTP_PREF("sendSecureXSiteReferrer"), &cVar
);
1007 if (NS_SUCCEEDED(rv
))
1008 mSendSecureXSiteReferrer
= cVar
;
1011 if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
1012 nsXPIDLCString accept
;
1013 rv
= prefs
->GetCharPref(HTTP_PREF("accept.default"),
1014 getter_Copies(accept
));
1015 if (NS_SUCCEEDED(rv
))
1019 if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
1020 nsXPIDLCString acceptEncodings
;
1021 rv
= prefs
->GetCharPref(HTTP_PREF("accept-encoding"),
1022 getter_Copies(acceptEncodings
));
1023 if (NS_SUCCEEDED(rv
))
1024 SetAcceptEncodings(acceptEncodings
);
1027 if (PREF_CHANGED(HTTP_PREF("use-cache"))) {
1028 rv
= prefs
->GetBoolPref(HTTP_PREF("use-cache"), &cVar
);
1029 if (NS_SUCCEEDED(rv
)) {
1034 if (PREF_CHANGED(HTTP_PREF("default-socket-type"))) {
1035 nsXPIDLCString sval
;
1036 rv
= prefs
->GetCharPref(HTTP_PREF("default-socket-type"),
1037 getter_Copies(sval
));
1038 if (NS_SUCCEEDED(rv
)) {
1040 mDefaultSocketType
.Adopt(0);
1042 // verify that this socket type is actually valid
1043 nsCOMPtr
<nsISocketProviderService
> sps(
1044 do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID
));
1046 nsCOMPtr
<nsISocketProvider
> sp
;
1047 rv
= sps
->GetSocketProvider(sval
, getter_AddRefs(sp
));
1048 if (NS_SUCCEEDED(rv
)) {
1049 // OK, this looks like a valid socket provider.
1050 mDefaultSocketType
.Assign(sval
);
1057 if (PREF_CHANGED(HTTP_PREF("prompt-temp-redirect"))) {
1058 rv
= prefs
->GetBoolPref(HTTP_PREF("prompt-temp-redirect"), &cVar
);
1059 if (NS_SUCCEEDED(rv
)) {
1060 mPromptTempRedirect
= cVar
;
1064 if (PREF_CHANGED(HTTP_PREF("assoc-req.enforce"))) {
1066 rv
= prefs
->GetBoolPref(HTTP_PREF("assoc-req.enforce"), &cVar
);
1067 if (NS_SUCCEEDED(rv
))
1068 mEnforceAssocReq
= cVar
;
1071 // enable Persistent caching for HTTPS - bug#205921
1072 if (PREF_CHANGED(BROWSER_PREF("disk_cache_ssl"))) {
1074 rv
= prefs
->GetBoolPref(BROWSER_PREF("disk_cache_ssl"), &cVar
);
1075 if (NS_SUCCEEDED(rv
))
1076 mEnablePersistentHttpsCaching
= cVar
;
1079 if (PREF_CHANGED(HTTP_PREF("phishy-userpass-length"))) {
1080 rv
= prefs
->GetIntPref(HTTP_PREF("phishy-userpass-length"), &val
);
1081 if (NS_SUCCEEDED(rv
))
1082 mPhishyUserPassLength
= (PRUint8
) clamped(val
, 0, 0xff);
1085 if (PREF_CHANGED(HTTP_PREF("spdy.enabled"))) {
1086 rv
= prefs
->GetBoolPref(HTTP_PREF("spdy.enabled"), &cVar
);
1087 if (NS_SUCCEEDED(rv
))
1091 if (PREF_CHANGED(HTTP_PREF("spdy.enabled.v2"))) {
1092 rv
= prefs
->GetBoolPref(HTTP_PREF("spdy.enabled.v2"), &cVar
);
1093 if (NS_SUCCEEDED(rv
))
1097 if (PREF_CHANGED(HTTP_PREF("spdy.enabled.v3"))) {
1098 rv
= prefs
->GetBoolPref(HTTP_PREF("spdy.enabled.v3"), &cVar
);
1099 if (NS_SUCCEEDED(rv
))
1103 if (PREF_CHANGED(HTTP_PREF("spdy.coalesce-hostnames"))) {
1104 rv
= prefs
->GetBoolPref(HTTP_PREF("spdy.coalesce-hostnames"), &cVar
);
1105 if (NS_SUCCEEDED(rv
))
1106 mCoalesceSpdy
= cVar
;
1109 if (PREF_CHANGED(HTTP_PREF("spdy.use-alternate-protocol"))) {
1110 rv
= prefs
->GetBoolPref(HTTP_PREF("spdy.use-alternate-protocol"),
1112 if (NS_SUCCEEDED(rv
))
1113 mUseAlternateProtocol
= cVar
;
1116 if (PREF_CHANGED(HTTP_PREF("spdy.timeout"))) {
1117 rv
= prefs
->GetIntPref(HTTP_PREF("spdy.timeout"), &val
);
1118 if (NS_SUCCEEDED(rv
))
1119 mSpdyTimeout
= PR_SecondsToInterval(clamped(val
, 1, 0xffff));
1122 if (PREF_CHANGED(HTTP_PREF("spdy.chunk-size"))) {
1123 rv
= prefs
->GetIntPref(HTTP_PREF("spdy.chunk-size"), &val
);
1124 if (NS_SUCCEEDED(rv
))
1125 mSpdySendingChunkSize
= (PRUint32
) clamped(val
, 1, 0x7fffffff);
1128 // The amount of idle seconds on a spdy connection before initiating a
1129 // server ping. 0 will disable.
1130 if (PREF_CHANGED(HTTP_PREF("spdy.ping-threshold"))) {
1131 rv
= prefs
->GetIntPref(HTTP_PREF("spdy.ping-threshold"), &val
);
1132 if (NS_SUCCEEDED(rv
))
1133 mSpdyPingThreshold
=
1134 PR_SecondsToInterval((PRUint16
) clamped(val
, 0, 0x7fffffff));
1137 // The amount of seconds to wait for a spdy ping response before
1138 // closing the session.
1139 if (PREF_CHANGED(HTTP_PREF("spdy.ping-timeout"))) {
1140 rv
= prefs
->GetIntPref(HTTP_PREF("spdy.ping-timeout"), &val
);
1141 if (NS_SUCCEEDED(rv
))
1143 PR_SecondsToInterval((PRUint16
) clamped(val
, 0, 0x7fffffff));
1150 if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES
)) {
1151 nsCOMPtr
<nsIPrefLocalizedString
> pls
;
1152 prefs
->GetComplexValue(INTL_ACCEPT_LANGUAGES
,
1153 NS_GET_IID(nsIPrefLocalizedString
),
1154 getter_AddRefs(pls
));
1157 pls
->ToString(getter_Copies(uval
));
1159 SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval
).get());
1167 if (PREF_CHANGED(NETWORK_ENABLEIDN
)) {
1168 bool enableIDN
= false;
1169 prefs
->GetBoolPref(NETWORK_ENABLEIDN
, &enableIDN
);
1170 // No locking is required here since this method runs in the main
1171 // UI thread, and so do all the methods in nsHttpChannel.cpp
1172 // (mIDNConverter is used by nsHttpChannel)
1173 if (enableIDN
&& !mIDNConverter
) {
1174 mIDNConverter
= do_GetService(NS_IDNSERVICE_CONTRACTID
);
1175 NS_ASSERTION(mIDNConverter
, "idnSDK not installed");
1177 else if (!enableIDN
&& mIDNConverter
)
1178 mIDNConverter
= nsnull
;
1185 if (PREF_CHANGED(DONOTTRACK_HEADER_ENABLED
)) {
1187 rv
= prefs
->GetBoolPref(DONOTTRACK_HEADER_ENABLED
, &cVar
);
1188 if (NS_SUCCEEDED(rv
)) {
1189 mDoNotTrackEnabled
= cVar
;
1197 if (PREF_CHANGED(TELEMETRY_ENABLED
)) {
1199 rv
= prefs
->GetBoolPref(TELEMETRY_ENABLED
, &cVar
);
1200 if (NS_SUCCEEDED(rv
)) {
1201 mTelemetryEnabled
= cVar
;
1206 // network.allow-experiments
1209 if (PREF_CHANGED(ALLOW_EXPERIMENTS
)) {
1211 rv
= prefs
->GetBoolPref(ALLOW_EXPERIMENTS
, &cVar
);
1212 if (NS_SUCCEEDED(rv
)) {
1213 mAllowExperiments
= cVar
;
1218 #undef MULTI_PREF_CHANGED
1222 * Allocates a C string into that contains a ISO 639 language list
1223 * notated with HTTP "q" values for output with a HTTP Accept-Language
1224 * header. Previous q values will be stripped because the order of
1225 * the langs imply the q value. The q values are calculated by dividing
1226 * 1.0 amongst the number of languages present.
1228 * Ex: passing: "en, ja"
1229 * returns: "en,ja;q=0.5"
1231 * passing: "en, ja, fr_CA"
1232 * returns: "en,ja;q=0.7,fr_CA;q=0.3"
1235 PrepareAcceptLanguages(const char *i_AcceptLanguages
, nsACString
&o_AcceptLanguages
)
1237 if (!i_AcceptLanguages
)
1240 PRUint32 n
, size
, wrote
;
1242 char *p
, *p2
, *token
, *q_Accept
, *o_Accept
;
1246 o_Accept
= nsCRT::strdup(i_AcceptLanguages
);
1248 return NS_ERROR_OUT_OF_MEMORY
;
1249 for (p
= o_Accept
, n
= size
= 0; '\0' != *p
; p
++) {
1254 available
= size
+ ++n
* 11 + 1;
1255 q_Accept
= new char[available
];
1257 nsCRT::free(o_Accept
);
1258 return NS_ERROR_OUT_OF_MEMORY
;
1262 dec
= q
/ (double) n
;
1265 for (token
= nsCRT::strtok(o_Accept
, ",", &p
);
1266 token
!= (char *) 0;
1267 token
= nsCRT::strtok(p
, ",", &p
))
1269 token
= net_FindCharNotInSet(token
, HTTP_LWS
);
1271 trim
= net_FindCharInSet(token
, ";" HTTP_LWS
);
1272 if (trim
!= (char*)0) // remove "; q=..." if present
1275 if (*token
!= '\0') {
1276 comma
= n
++ != 0 ? "," : ""; // delimiter if not first item
1277 PRUint32 u
= QVAL_TO_UINT(q
);
1279 wrote
= PR_snprintf(p2
, available
, "%s%s;q=0.%u", comma
, token
, u
);
1281 wrote
= PR_snprintf(p2
, available
, "%s%s", comma
, token
);
1285 NS_ASSERTION(available
> 0, "allocated string not long enough");
1288 nsCRT::free(o_Accept
);
1290 o_AcceptLanguages
.Assign((const char *) q_Accept
);
1297 nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages
)
1300 nsresult rv
= PrepareAcceptLanguages(aAcceptLanguages
, buf
);
1301 if (NS_SUCCEEDED(rv
))
1302 mAcceptLanguages
.Assign(buf
);
1307 nsHttpHandler::SetAccept(const char *aAccept
)
1314 nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings
)
1316 mAcceptEncodings
= aAcceptEncodings
;
1320 //-----------------------------------------------------------------------------
1321 // nsHttpHandler::nsISupports
1322 //-----------------------------------------------------------------------------
1324 NS_IMPL_THREADSAFE_ISUPPORTS6(nsHttpHandler
,
1325 nsIHttpProtocolHandler
,
1326 nsIProxiedProtocolHandler
,
1329 nsISupportsWeakReference
,
1330 nsISpeculativeConnect
)
1332 //-----------------------------------------------------------------------------
1333 // nsHttpHandler::nsIProtocolHandler
1334 //-----------------------------------------------------------------------------
1337 nsHttpHandler::GetScheme(nsACString
&aScheme
)
1339 aScheme
.AssignLiteral("http");
1344 nsHttpHandler::GetDefaultPort(PRInt32
*result
)
1346 *result
= NS_HTTP_DEFAULT_PORT
;
1351 nsHttpHandler::GetProtocolFlags(PRUint32
*result
)
1353 *result
= NS_HTTP_PROTOCOL_FLAGS
;
1358 nsHttpHandler::NewURI(const nsACString
&aSpec
,
1359 const char *aCharset
,
1363 LOG(("nsHttpHandler::NewURI\n"));
1364 return ::NewURI(aSpec
, aCharset
, aBaseURI
, NS_HTTP_DEFAULT_PORT
, aURI
);
1368 nsHttpHandler::NewChannel(nsIURI
*uri
, nsIChannel
**result
)
1370 LOG(("nsHttpHandler::NewChannel\n"));
1372 NS_ENSURE_ARG_POINTER(uri
);
1373 NS_ENSURE_ARG_POINTER(result
);
1375 bool isHttp
= false, isHttps
= false;
1377 // Verify that we have been given a valid scheme
1378 nsresult rv
= uri
->SchemeIs("http", &isHttp
);
1379 if (NS_FAILED(rv
)) return rv
;
1381 rv
= uri
->SchemeIs("https", &isHttps
);
1382 if (NS_FAILED(rv
)) return rv
;
1384 NS_WARNING("Invalid URI scheme");
1385 return NS_ERROR_UNEXPECTED
;
1389 return NewProxiedChannel(uri
, nsnull
, result
);
1393 nsHttpHandler::AllowPort(PRInt32 port
, const char *scheme
, bool *_retval
)
1395 // don't override anything.
1400 //-----------------------------------------------------------------------------
1401 // nsHttpHandler::nsIProxiedProtocolHandler
1402 //-----------------------------------------------------------------------------
1405 nsHttpHandler::NewProxiedChannel(nsIURI
*uri
,
1406 nsIProxyInfo
* givenProxyInfo
,
1407 nsIChannel
**result
)
1409 nsRefPtr
<HttpBaseChannel
> httpChannel
;
1411 LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
1414 nsCOMPtr
<nsProxyInfo
> proxyInfo
;
1415 if (givenProxyInfo
) {
1416 proxyInfo
= do_QueryInterface(givenProxyInfo
);
1417 NS_ENSURE_ARG(proxyInfo
);
1421 nsresult rv
= uri
->SchemeIs("https", &https
);
1425 if (IsNeckoChild()) {
1426 httpChannel
= new HttpChannelChild();
1428 httpChannel
= new nsHttpChannel();
1431 // select proxy caps if using a non-transparent proxy. SSL tunneling
1432 // should not use proxy settings.
1434 if (proxyInfo
&& !nsCRT::strcmp(proxyInfo
->Type(), "http") && !https
)
1435 caps
= mProxyCapabilities
;
1437 caps
= mCapabilities
;
1440 // enable pipelining over SSL if requested
1441 if (mPipeliningOverSSL
)
1442 caps
|= NS_HTTP_ALLOW_PIPELINING
;
1444 if (!IsNeckoChild()) {
1445 // HACK: make sure PSM gets initialized on the main thread.
1446 net_EnsurePSMInit();
1450 rv
= httpChannel
->Init(uri
, caps
, proxyInfo
);
1454 httpChannel
.forget(result
);
1458 //-----------------------------------------------------------------------------
1459 // nsHttpHandler::nsIHttpProtocolHandler
1460 //-----------------------------------------------------------------------------
1463 nsHttpHandler::GetUserAgent(nsACString
&value
)
1465 value
= UserAgent();
1470 nsHttpHandler::GetAppName(nsACString
&value
)
1472 value
= mLegacyAppName
;
1477 nsHttpHandler::GetAppVersion(nsACString
&value
)
1479 value
= mLegacyAppVersion
;
1484 nsHttpHandler::GetProduct(nsACString
&value
)
1491 nsHttpHandler::GetProductSub(nsACString
&value
)
1493 value
= mProductSub
;
1498 nsHttpHandler::GetPlatform(nsACString
&value
)
1505 nsHttpHandler::GetOscpu(nsACString
&value
)
1512 nsHttpHandler::GetMisc(nsACString
&value
)
1518 //-----------------------------------------------------------------------------
1519 // nsHttpHandler::nsIObserver
1520 //-----------------------------------------------------------------------------
1523 nsHttpHandler::Observe(nsISupports
*subject
,
1525 const PRUnichar
*data
)
1527 LOG(("nsHttpHandler::Observe [topic=\"%s\"]\n", topic
));
1529 if (strcmp(topic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
) == 0) {
1530 nsCOMPtr
<nsIPrefBranch
> prefBranch
= do_QueryInterface(subject
);
1532 PrefsChanged(prefBranch
, NS_ConvertUTF16toUTF8(data
).get());
1534 else if (strcmp(topic
, "profile-change-net-teardown") == 0 ||
1535 strcmp(topic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
) == 0) {
1537 // clear cache of all authentication credentials.
1538 mAuthCache
.ClearAll();
1540 // ensure connection manager is shutdown
1542 mConnMgr
->Shutdown();
1544 // need to reset the session start time since cache validation may
1545 // depend on this value.
1546 mSessionStartTime
= NowInSeconds();
1548 else if (strcmp(topic
, "profile-change-net-restore") == 0) {
1549 // initialize connection manager
1550 InitConnectionMgr();
1552 else if (strcmp(topic
, "net:clear-active-logins") == 0) {
1553 mAuthCache
.ClearAll();
1555 else if (strcmp(topic
, "net:prune-dead-connections") == 0) {
1557 mConnMgr
->PruneDeadConnections();
1560 else if (strcmp(topic
, "net:failed-to-process-uri-content") == 0) {
1561 nsCOMPtr
<nsIURI
> uri
= do_QueryInterface(subject
);
1562 if (uri
&& mConnMgr
)
1563 mConnMgr
->ReportFailedToProcess(uri
);
1569 // nsISpeculativeConnect
1572 nsHttpHandler::SpeculativeConnect(nsIURI
*aURI
,
1573 nsIInterfaceRequestor
*aCallbacks
,
1574 nsIEventTarget
*aTarget
)
1576 nsIStrictTransportSecurityService
* stss
= gHttpHandler
->GetSTSService();
1577 bool isStsHost
= false;
1581 nsCOMPtr
<nsIURI
> clone
;
1582 if (NS_SUCCEEDED(stss
->IsStsURI(aURI
, &isStsHost
)) && isStsHost
) {
1583 if (NS_SUCCEEDED(aURI
->Clone(getter_AddRefs(clone
)))) {
1584 clone
->SetScheme(NS_LITERAL_CSTRING("https"));
1589 nsCAutoString scheme
;
1590 nsresult rv
= aURI
->GetScheme(scheme
);
1594 // If this is HTTPS, make sure PSM is initialized as the channel
1595 // creation path may have been bypassed
1596 if (scheme
.EqualsLiteral("https")) {
1597 if (!IsNeckoChild()) {
1598 // make sure PSM gets initialized on the main thread.
1599 net_EnsurePSMInit();
1602 // Ensure that this is HTTP or HTTPS, otherwise we don't do preconnect here
1603 else if (!scheme
.EqualsLiteral("http"))
1604 return NS_ERROR_UNEXPECTED
;
1606 // Construct connection info object
1607 bool usingSSL
= false;
1608 rv
= aURI
->SchemeIs("https", &usingSSL
);
1613 rv
= aURI
->GetAsciiHost(host
);
1618 rv
= aURI
->GetPort(&port
);
1622 nsHttpConnectionInfo
*ci
=
1623 new nsHttpConnectionInfo(host
, port
, nsnull
, usingSSL
);
1625 return SpeculativeConnect(ci
, aCallbacks
, aTarget
);
1628 //-----------------------------------------------------------------------------
1629 // nsHttpsHandler implementation
1630 //-----------------------------------------------------------------------------
1632 NS_IMPL_THREADSAFE_ISUPPORTS5(nsHttpsHandler
,
1633 nsIHttpProtocolHandler
,
1634 nsIProxiedProtocolHandler
,
1636 nsISupportsWeakReference
,
1637 nsISpeculativeConnect
)
1640 nsHttpsHandler::Init()
1642 nsCOMPtr
<nsIProtocolHandler
> httpHandler(
1643 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http"));
1644 NS_ASSERTION(httpHandler
.get() != nsnull
, "no http handler?");
1649 nsHttpsHandler::GetScheme(nsACString
&aScheme
)
1651 aScheme
.AssignLiteral("https");
1656 nsHttpsHandler::GetDefaultPort(PRInt32
*aPort
)
1658 *aPort
= NS_HTTPS_DEFAULT_PORT
;
1663 nsHttpsHandler::GetProtocolFlags(PRUint32
*aProtocolFlags
)
1665 *aProtocolFlags
= NS_HTTP_PROTOCOL_FLAGS
;
1670 nsHttpsHandler::NewURI(const nsACString
&aSpec
,
1671 const char *aOriginCharset
,
1675 return ::NewURI(aSpec
, aOriginCharset
, aBaseURI
, NS_HTTPS_DEFAULT_PORT
, _retval
);
1679 nsHttpsHandler::NewChannel(nsIURI
*aURI
, nsIChannel
**_retval
)
1681 NS_ABORT_IF_FALSE(gHttpHandler
, "Should have a HTTP handler by now.");
1683 return NS_ERROR_UNEXPECTED
;
1684 return gHttpHandler
->NewChannel(aURI
, _retval
);
1688 nsHttpsHandler::AllowPort(PRInt32 aPort
, const char *aScheme
, bool *_retval
)
1690 // don't override anything.