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 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications.
20 * Portions created by the Initial Developer are Copyright (C) 2001
21 * the Initial Developer. All Rights Reserved.
24 * Darin Fisher <darin@netscape.com> (original author)
25 * Gagan Saksena <gagan@netscape.com>
26 * Pierre Phaneuf <pp@ludusdesign.com>
27 * Christopher Blizzard <blizzard@mozilla.org>
28 * Adrian Havill <havill@redhat.com>
29 * Gervase Markham <gerv@gerv.net>
30 * Bradley Baetz <bbaetz@netscape.com>
31 * Benjamin Smedberg <bsmedberg@covad.net>
32 * Josh Aas <josh@mozilla.com>
34 * Alternatively, the contents of this file may be used under the terms of
35 * either the GNU General Public License Version 2 or later (the "GPL"), or
36 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
37 * in which case the provisions of the GPL or the LGPL are applicable instead
38 * of those above. If you wish to allow use of your version of this file only
39 * under the terms of either the GPL or the LGPL, and not to allow others to
40 * use your version of this file under the terms of the MPL, indicate your
41 * decision by deleting the provisions above and replace them with the notice
42 * and other provisions required by the GPL or the LGPL. If you do not delete
43 * the provisions above, a recipient may use your version of this file under
44 * the terms of any one of the MPL, the GPL or the LGPL.
46 * ***** END LICENSE BLOCK ***** */
49 #include "nsHttpHandler.h"
50 #include "nsHttpChannel.h"
51 #include "nsHttpConnection.h"
52 #include "nsHttpResponseHead.h"
53 #include "nsHttpTransaction.h"
54 #include "nsHttpAuthCache.h"
55 #include "nsStandardURL.h"
56 #include "nsIHttpChannel.h"
58 #include "nsIStandardURL.h"
59 #include "nsICacheService.h"
60 #include "nsICategoryManager.h"
61 #include "nsCategoryManagerUtils.h"
62 #include "nsICacheService.h"
63 #include "nsIPrefService.h"
64 #include "nsIPrefBranch2.h"
65 #include "nsIPrefLocalizedString.h"
66 #include "nsISocketProviderService.h"
67 #include "nsISocketProvider.h"
68 #include "nsPrintfCString.h"
71 #include "nsAutoLock.h"
73 #include "nsReadableUtils.h"
74 #include "nsQuickSort.h"
75 #include "nsNetUtil.h"
76 #include "nsIOService.h"
78 #include "nsIXULAppInfo.h"
80 #if defined(XP_UNIX) || defined(XP_BEOS)
81 #include <sys/utsname.h>
88 #if defined(XP_MACOSX)
89 #include <Carbon/Carbon.h>
98 // defined by the socket transport service while active
99 extern PRThread
*gSocketThread
;
102 static NS_DEFINE_CID(kIOServiceCID
, NS_IOSERVICE_CID
);
103 static NS_DEFINE_CID(kStreamConverterServiceCID
, NS_STREAMCONVERTERSERVICE_CID
);
104 static NS_DEFINE_CID(kCookieServiceCID
, NS_COOKIESERVICE_CID
);
105 static NS_DEFINE_CID(kCacheServiceCID
, NS_CACHESERVICE_CID
);
106 static NS_DEFINE_CID(kSocketProviderServiceCID
, NS_SOCKETPROVIDERSERVICE_CID
);
108 #define UA_PREF_PREFIX "general.useragent."
109 #define UA_APPNAME "Mozilla"
110 #define UA_APPVERSION "5.0"
111 #define UA_APPSECURITY_FALLBACK "N"
113 #define HTTP_PREF_PREFIX "network.http."
114 #define INTL_ACCEPT_LANGUAGES "intl.accept_languages"
115 #define INTL_ACCEPT_CHARSET "intl.charset.default"
116 #define NETWORK_ENABLEIDN "network.enableIDN"
117 #define BROWSER_PREF_PREFIX "browser.cache."
119 #define UA_PREF(_pref) UA_PREF_PREFIX _pref
120 #define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
121 #define BROWSER_PREF(_pref) BROWSER_PREF_PREFIX _pref
123 //-----------------------------------------------------------------------------
126 NewURI(const nsACString
&aSpec
,
127 const char *aCharset
,
129 PRInt32 aDefaultPort
,
132 nsStandardURL
*url
= new nsStandardURL();
134 return NS_ERROR_OUT_OF_MEMORY
;
137 nsresult rv
= url
->Init(nsIStandardURL::URLTYPE_AUTHORITY
,
138 aDefaultPort
, aSpec
, aCharset
, aBaseURI
);
144 *aURI
= url
; // no QI needed
148 //-----------------------------------------------------------------------------
149 // nsHttpHandler <public>
150 //-----------------------------------------------------------------------------
152 nsHttpHandler
*gHttpHandler
= nsnull
;
154 nsHttpHandler::nsHttpHandler()
156 , mHttpVersion(NS_HTTP_VERSION_1_1
)
157 , mProxyHttpVersion(NS_HTTP_VERSION_1_1
)
158 , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE
)
159 , mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE
)
160 , mReferrerLevel(0xff) // by default we always send a referrer
162 , mMaxRequestAttempts(10)
163 , mMaxRequestDelay(10)
164 , mMaxConnections(24)
165 , mMaxConnectionsPerServer(8)
166 , mMaxPersistentConnectionsPerServer(2)
167 , mMaxPersistentConnectionsPerProxy(4)
168 , mMaxPipelinedRequests(2)
169 , mRedirectionLimit(10)
170 , mPhishyUserPassLength(1)
171 , mPipeliningOverSSL(PR_FALSE
)
172 , mLastUniqueID(NowInSeconds())
173 , mSessionStartTime(0)
175 , mUserAgentIsDirty(PR_TRUE
)
177 , mSendSecureXSiteReferrer(PR_TRUE
)
178 , mEnablePersistentHttpsCaching(PR_FALSE
)
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 // We do not deal with the timer cancellation in the destructor since
193 // it is taken care of in xpcom shutdown event in the Observe method.
195 LOG(("Deleting nsHttpHandler [this=%x]\n", this));
197 // make sure the connection manager is shutdown
199 mConnMgr
->Shutdown();
200 NS_RELEASE(mConnMgr
);
203 nsHttp::DestroyAtomTable();
205 gHttpHandler
= nsnull
;
209 nsHttpHandler::Init()
213 LOG(("nsHttpHandler::Init\n"));
215 rv
= nsHttp::CreateAtomTable();
219 mIOService
= do_GetService(kIOServiceCID
, &rv
);
221 NS_WARNING("unable to continue without io service");
225 InitUserAgentComponents();
227 // monitor some preference changes
228 nsCOMPtr
<nsIPrefBranch2
> prefBranch
= do_GetService(NS_PREFSERVICE_CONTRACTID
);
230 prefBranch
->AddObserver(HTTP_PREF_PREFIX
, this, PR_TRUE
);
231 prefBranch
->AddObserver(UA_PREF_PREFIX
, this, PR_TRUE
);
232 prefBranch
->AddObserver(INTL_ACCEPT_LANGUAGES
, this, PR_TRUE
);
233 prefBranch
->AddObserver(INTL_ACCEPT_CHARSET
, this, PR_TRUE
);
234 prefBranch
->AddObserver(NETWORK_ENABLEIDN
, this, PR_TRUE
);
235 prefBranch
->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, PR_TRUE
);
237 PrefsChanged(prefBranch
, nsnull
);
240 mMisc
.AssignLiteral("rv:" MOZILLA_VERSION
);
243 // dump user agent prefs
244 LOG(("> app-name = %s\n", mAppName
.get()));
245 LOG(("> app-version = %s\n", mAppVersion
.get()));
246 LOG(("> platform = %s\n", mPlatform
.get()));
247 LOG(("> oscpu = %s\n", mOscpu
.get()));
248 LOG(("> security = %s\n", mSecurity
.get()));
249 LOG(("> language = %s\n", mLanguage
.get()));
250 LOG(("> misc = %s\n", mMisc
.get()));
251 LOG(("> vendor = %s\n", mVendor
.get()));
252 LOG(("> vendor-sub = %s\n", mVendorSub
.get()));
253 LOG(("> vendor-comment = %s\n", mVendorComment
.get()));
254 LOG(("> extra = %s\n", mExtraUA
.get()));
255 LOG(("> product = %s\n", mProduct
.get()));
256 LOG(("> product-sub = %s\n", mProductSub
.get()));
257 LOG(("> product-comment = %s\n", mProductComment
.get()));
258 LOG(("> user-agent = %s\n", UserAgent().get()));
261 mSessionStartTime
= NowInSeconds();
263 rv
= mAuthCache
.Init();
264 if (NS_FAILED(rv
)) return rv
;
266 rv
= InitConnectionMgr();
267 if (NS_FAILED(rv
)) return rv
;
269 nsCOMPtr
<nsIXULAppInfo
> appInfo
=
270 do_GetService("@mozilla.org/xre/app-info;1");
272 appInfo
->GetPlatformBuildID(mProductSub
);
273 if (mProductSub
.Length() > 8)
274 mProductSub
.SetLength(8);
276 // Startup the http category
277 // Bring alive the objects in the http-protocol-startup category
278 NS_CreateServicesFromCategory(NS_HTTP_STARTUP_CATEGORY
,
279 static_cast<nsISupports
*>(static_cast<void*>(this)),
280 NS_HTTP_STARTUP_TOPIC
);
282 mObserverService
= do_GetService("@mozilla.org/observer-service;1");
283 if (mObserverService
) {
284 mObserverService
->AddObserver(this, "profile-change-net-teardown", PR_TRUE
);
285 mObserverService
->AddObserver(this, "profile-change-net-restore", PR_TRUE
);
286 mObserverService
->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID
, PR_TRUE
);
289 StartPruneDeadConnectionsTimer();
294 nsHttpHandler::InitConnectionMgr()
299 mConnMgr
= new nsHttpConnectionMgr();
301 return NS_ERROR_OUT_OF_MEMORY
;
305 rv
= mConnMgr
->Init(mMaxConnections
,
306 mMaxConnectionsPerServer
,
307 mMaxConnectionsPerServer
,
308 mMaxPersistentConnectionsPerServer
,
309 mMaxPersistentConnectionsPerProxy
,
311 mMaxPipelinedRequests
);
316 nsHttpHandler::StartPruneDeadConnectionsTimer()
318 LOG(("nsHttpHandler::StartPruneDeadConnectionsTimer\n"));
320 mTimer
= do_CreateInstance("@mozilla.org/timer;1");
321 NS_ASSERTION(mTimer
, "no timer");
322 // failure to create a timer is not a fatal error, but idle connections
323 // will not be cleaned up until we try to use them.
325 mTimer
->Init(this, 15*1000, // every 15 seconds
326 nsITimer::TYPE_REPEATING_SLACK
);
330 nsHttpHandler::StopPruneDeadConnectionsTimer()
332 LOG(("nsHttpHandler::StopPruneDeadConnectionsTimer\n"));
341 nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray
*request
,
347 // Add the "User-Agent" header
348 rv
= request
->SetHeader(nsHttp::User_Agent
, UserAgent());
349 if (NS_FAILED(rv
)) return rv
;
351 // MIME based content negotiation lives!
352 // Add the "Accept" header
353 rv
= request
->SetHeader(nsHttp::Accept
, mAccept
);
354 if (NS_FAILED(rv
)) return rv
;
356 // Add the "Accept-Language" header
357 if (!mAcceptLanguages
.IsEmpty()) {
358 // Add the "Accept-Language" header
359 rv
= request
->SetHeader(nsHttp::Accept_Language
, mAcceptLanguages
);
360 if (NS_FAILED(rv
)) return rv
;
363 // Add the "Accept-Encoding" header
364 rv
= request
->SetHeader(nsHttp::Accept_Encoding
, mAcceptEncodings
);
365 if (NS_FAILED(rv
)) return rv
;
367 // Add the "Accept-Charset" header
368 rv
= request
->SetHeader(nsHttp::Accept_Charset
, mAcceptCharsets
);
369 if (NS_FAILED(rv
)) return rv
;
371 // RFC2616 section 19.6.2 states that the "Connection: keep-alive"
372 // and "Keep-alive" request headers should not be sent by HTTP/1.1
373 // user-agents. Otherwise, problems with proxy servers (especially
374 // transparent proxies) can result.
376 // However, we need to send something so that we can use keepalive
377 // with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when
378 // we're talking to an http proxy, and "Connection:" otherwise
380 NS_NAMED_LITERAL_CSTRING(close
, "close");
381 NS_NAMED_LITERAL_CSTRING(keepAlive
, "keep-alive");
383 const nsACString
*connectionType
= &close
;
384 if (caps
& NS_HTTP_ALLOW_KEEPALIVE
) {
385 rv
= request
->SetHeader(nsHttp::Keep_Alive
, nsPrintfCString("%u", mIdleTimeout
));
386 if (NS_FAILED(rv
)) return rv
;
387 connectionType
= &keepAlive
;
388 } else if (useProxy
) {
390 request
->SetHeader(nsHttp::Connection
, close
);
393 const nsHttpAtom
&header
= useProxy
? nsHttp::Proxy_Connection
394 : nsHttp::Connection
;
395 return request
->SetHeader(header
, *connectionType
);
399 nsHttpHandler::IsAcceptableEncoding(const char *enc
)
404 // HTTP 1.1 allows servers to send x-gzip and x-compress instead
405 // of gzip and compress, for example. So, we'll always strip off
406 // an "x-" prefix before matching the encoding to one we claim
408 if (!PL_strncasecmp(enc
, "x-", 2))
411 return nsHttp::FindToken(mAcceptEncodings
.get(), enc
, HTTP_LWS
",") != nsnull
;
415 nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy
,
416 nsICacheSession
**result
)
420 // Skip cache if disabled in preferences
422 return NS_ERROR_NOT_AVAILABLE
;
424 // We want to get the pointer to the cache service each time we're called,
425 // because it's possible for some add-ons (such as Google Gears) to swap
426 // in new cache services on the fly, and we want to pick them up as
428 nsCOMPtr
<nsICacheService
> serv
= do_GetService(NS_CACHESERVICE_CONTRACTID
,
430 if (NS_FAILED(rv
)) return rv
;
432 const char *sessionName
= "HTTP";
433 switch (storagePolicy
) {
434 case nsICache::STORE_IN_MEMORY
:
435 sessionName
= "HTTP-memory-only";
437 case nsICache::STORE_OFFLINE
:
438 sessionName
= "HTTP-offline";
444 nsCOMPtr
<nsICacheSession
> cacheSession
;
445 rv
= serv
->CreateSession(sessionName
,
447 nsICache::STREAM_BASED
,
448 getter_AddRefs(cacheSession
));
449 if (NS_FAILED(rv
)) return rv
;
451 rv
= cacheSession
->SetDoomEntriesIfExpired(PR_FALSE
);
452 if (NS_FAILED(rv
)) return rv
;
454 NS_ADDREF(*result
= cacheSession
);
460 nsHttpHandler::GetStreamConverterService(nsIStreamConverterService
**result
)
462 if (!mStreamConvSvc
) {
464 mStreamConvSvc
= do_GetService(kStreamConverterServiceCID
, &rv
);
465 if (NS_FAILED(rv
)) return rv
;
467 *result
= mStreamConvSvc
;
473 nsHttpHandler::GetCookieService()
476 mCookieService
= do_GetService(kCookieServiceCID
);
477 return mCookieService
;
481 nsHttpHandler::GetIOService(nsIIOService
** result
)
483 NS_ADDREF(*result
= mIOService
);
489 nsHttpHandler::NotifyObservers(nsIHttpChannel
*chan
, const char *event
)
491 LOG(("nsHttpHandler::NotifyObservers [chan=%x event=\"%s\"]\n", chan
, event
));
492 if (mObserverService
)
493 mObserverService
->NotifyObservers(chan
, event
, nsnull
);
497 nsHttpHandler::OnChannelRedirect(nsIChannel
* oldChan
, nsIChannel
* newChan
,
500 // First, the global observer
501 NS_ASSERTION(gIOService
, "Must have an IO service at this point");
502 nsresult rv
= gIOService
->OnChannelRedirect(oldChan
, newChan
, flags
);
506 // Now, the per-channel observers
507 nsCOMPtr
<nsIChannelEventSink
> sink
;
508 NS_QueryNotificationCallbacks(oldChan
, sink
);
510 rv
= sink
->OnChannelRedirect(oldChan
, newChan
, flags
);
515 //-----------------------------------------------------------------------------
516 // nsHttpHandler <private>
517 //-----------------------------------------------------------------------------
519 const nsAFlatCString
&
520 nsHttpHandler::UserAgent()
522 if (mUserAgentOverride
) {
523 LOG(("using general.useragent.override : %s\n", mUserAgentOverride
.get()));
524 return mUserAgentOverride
;
527 if (mUserAgentIsDirty
) {
529 mUserAgentIsDirty
= PR_FALSE
;
536 nsHttpHandler::BuildUserAgent()
538 LOG(("nsHttpHandler::BuildUserAgent\n"));
540 NS_ASSERTION(!mAppName
.IsEmpty() &&
541 !mAppVersion
.IsEmpty() &&
542 !mPlatform
.IsEmpty() &&
543 !mSecurity
.IsEmpty() &&
545 "HTTP cannot send practical requests without this much");
547 // preallocate to worst-case size, which should always be better
548 // than if we didn't preallocate at all.
549 mUserAgent
.SetCapacity(mAppName
.Length() +
550 mAppVersion
.Length() +
557 mProductSub
.Length() +
558 mProductComment
.Length() +
560 mVendorSub
.Length() +
561 mVendorComment
.Length() +
565 // Application portion
566 mUserAgent
.Assign(mAppName
);
568 mUserAgent
+= mAppVersion
;
571 // Application comment
573 mUserAgent
+= mPlatform
;
574 mUserAgent
.AppendLiteral("; ");
575 mUserAgent
+= mSecurity
;
576 mUserAgent
.AppendLiteral("; ");
577 mUserAgent
+= mOscpu
;
578 if (!mLanguage
.IsEmpty()) {
579 mUserAgent
.AppendLiteral("; ");
580 mUserAgent
+= mLanguage
;
582 if (!mMisc
.IsEmpty()) {
583 mUserAgent
.AppendLiteral("; ");
589 if (!mProduct
.IsEmpty()) {
591 mUserAgent
+= mProduct
;
592 if (!mProductSub
.IsEmpty()) {
594 mUserAgent
+= mProductSub
;
596 if (!mProductComment
.IsEmpty()) {
597 mUserAgent
.AppendLiteral(" (");
598 mUserAgent
+= mProductComment
;
604 if (!mVendor
.IsEmpty()) {
606 mUserAgent
+= mVendor
;
607 if (!mVendorSub
.IsEmpty()) {
609 mUserAgent
+= mVendorSub
;
611 if (!mVendorComment
.IsEmpty()) {
612 mUserAgent
.AppendLiteral(" (");
613 mUserAgent
+= mVendorComment
;
618 if (!mExtraUA
.IsEmpty())
619 mUserAgent
+= mExtraUA
;
623 nsHttpHandler::InitUserAgentComponents()
627 mPlatform
.AssignLiteral(
628 #if defined(MOZ_WIDGET_PHOTON)
630 #elif defined(XP_OS2)
632 #elif defined(XP_WIN)
634 #elif defined(XP_MACOSX)
636 #elif defined(XP_BEOS)
638 #elif !defined(MOZ_X11)
648 DosQuerySysInfo(QSV_VERSION_MINOR
, QSV_VERSION_MINOR
,
649 &os2ver
, sizeof(os2ver
));
651 mOscpu
.AssignLiteral("2.11");
652 else if (os2ver
== 30)
653 mOscpu
.AssignLiteral("Warp 3");
654 else if (os2ver
== 40)
655 mOscpu
.AssignLiteral("Warp 4");
656 else if (os2ver
== 45)
657 mOscpu
.AssignLiteral("Warp 4.5");
660 OSVERSIONINFO info
= { sizeof(OSVERSIONINFO
) };
661 if (GetVersionEx(&info
)) {
662 char *buf
= PR_smprintf("Windows CE %ld.%ld",
664 info
.dwMinorVersion
);
667 PR_smprintf_free(buf
);
670 #elif defined(XP_WIN)
671 OSVERSIONINFO info
= { sizeof(OSVERSIONINFO
) };
672 if (GetVersionEx(&info
)) {
673 if (info
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
674 if (info
.dwMajorVersion
== 3)
675 mOscpu
.AssignLiteral("WinNT3.51");
676 else if (info
.dwMajorVersion
== 4)
677 mOscpu
.AssignLiteral("WinNT4.0");
679 char *buf
= PR_smprintf("Windows NT %ld.%ld",
681 info
.dwMinorVersion
);
684 PR_smprintf_free(buf
);
688 char *buf
= PR_smprintf("Windows %ld.%ld",
690 info
.dwMinorVersion
);
693 PR_smprintf_free(buf
);
697 #elif defined (XP_MACOSX)
699 mOscpu
.AssignLiteral("PPC Mac OS X");
700 #elif defined(__i386__)
701 mOscpu
.AssignLiteral("Intel Mac OS X");
703 long majorVersion
, minorVersion
;
704 if ((::Gestalt(gestaltSystemVersionMajor
, &majorVersion
) == noErr
) &&
705 (::Gestalt(gestaltSystemVersionMinor
, &minorVersion
) == noErr
)) {
706 mOscpu
+= nsPrintfCString(" %ld.%ld", majorVersion
, minorVersion
);
708 #elif defined (XP_UNIX) || defined (XP_BEOS)
711 int ret
= uname(&name
);
714 buf
= (char*)name
.sysname
;
716 if (strcmp(name
.machine
, "x86_64") == 0 &&
717 sizeof(void *) == sizeof(PRInt32
)) {
718 // We're running 32-bit code on x86_64. Make this browser
719 // look like it's running on i686 hardware, but append "
720 // (x86_64)" to the end of the oscpu identifier to be able
721 // to differentiate this from someone running 64-bit code
724 buf
+= " i686 (x86_64)";
729 // AIX uname returns machine specific info in the uname.machine
730 // field and does not return the cpu type like other platforms.
731 // We use the AIX version and release numbers instead.
732 buf
+= (char*)name
.version
;
734 buf
+= (char*)name
.release
;
736 buf
+= (char*)name
.machine
;
744 mUserAgentIsDirty
= PR_TRUE
;
747 static int StringCompare(const void* s1
, const void* s2
, void*)
749 return nsCRT::strcmp(*static_cast<const char *const *>(s1
),
750 *static_cast<const char *const *>(s2
));
754 nsHttpHandler::PrefsChanged(nsIPrefBranch
*prefs
, const char *pref
)
759 LOG(("nsHttpHandler::PrefsChanged [pref=%s]\n", pref
));
761 #define PREF_CHANGED(p) ((pref == nsnull) || !PL_strcmp(pref, p))
762 #define MULTI_PREF_CHANGED(p) \
763 ((pref == nsnull) || !PL_strncmp(pref, p, sizeof(p) - 1))
769 // Gather application values.
770 if (PREF_CHANGED(UA_PREF("appName"))) {
771 prefs
->GetCharPref(UA_PREF("appName"),
772 getter_Copies(mAppName
));
773 if (mAppName
.IsEmpty())
774 mAppName
.AssignLiteral(UA_APPNAME
);
775 mUserAgentIsDirty
= PR_TRUE
;
777 if (PREF_CHANGED(UA_PREF("appVersion"))) {
778 prefs
->GetCharPref(UA_PREF("appVersion"),
779 getter_Copies(mAppVersion
));
780 if (mAppVersion
.IsEmpty())
781 mAppVersion
.AssignLiteral(UA_APPVERSION
);
782 mUserAgentIsDirty
= PR_TRUE
;
785 // Gather vendor values.
786 if (PREF_CHANGED(UA_PREF("vendor"))) {
787 prefs
->GetCharPref(UA_PREF("vendor"),
788 getter_Copies(mVendor
));
789 mUserAgentIsDirty
= PR_TRUE
;
791 if (PREF_CHANGED(UA_PREF("vendorSub"))) {
792 prefs
->GetCharPref(UA_PREF("vendorSub"),
793 getter_Copies(mVendorSub
));
794 mUserAgentIsDirty
= PR_TRUE
;
796 if (PREF_CHANGED(UA_PREF("vendorComment"))) {
797 prefs
->GetCharPref(UA_PREF("vendorComment"),
798 getter_Copies(mVendorComment
));
799 mUserAgentIsDirty
= PR_TRUE
;
802 if (MULTI_PREF_CHANGED(UA_PREF("extra."))) {
805 // Unfortunately, we can't do this using the pref branch.
806 nsCOMPtr
<nsIPrefService
> service
=
807 do_GetService(NS_PREFSERVICE_CONTRACTID
);
808 nsCOMPtr
<nsIPrefBranch
> branch
;
809 service
->GetBranch(UA_PREF("extra."), getter_AddRefs(branch
));
813 rv
= branch
->GetChildList("", &extraCount
, &extraItems
);
814 if (NS_SUCCEEDED(rv
) && extraItems
) {
815 NS_QuickSort(extraItems
, extraCount
, sizeof(extraItems
[0]),
816 StringCompare
, nsnull
);
817 for (char **item
= extraItems
,
818 **item_end
= extraItems
+ extraCount
;
819 item
< item_end
; ++item
) {
820 nsXPIDLCString valStr
;
821 branch
->GetCharPref(*item
, getter_Copies(valStr
));
822 if (!valStr
.IsEmpty())
823 mExtraUA
+= NS_LITERAL_CSTRING(" ") + valStr
;
825 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(extraCount
, extraItems
);
829 mUserAgentIsDirty
= PR_TRUE
;
832 // Gather product values.
833 if (PREF_CHANGED(UA_PREF("productComment"))) {
834 prefs
->GetCharPref(UA_PREF("productComment"),
835 getter_Copies(mProductComment
));
836 mUserAgentIsDirty
= PR_TRUE
;
839 // Get Security level supported
840 if (PREF_CHANGED(UA_PREF("security"))) {
841 prefs
->GetCharPref(UA_PREF("security"), getter_Copies(mSecurity
));
843 mSecurity
.AssignLiteral(UA_APPSECURITY_FALLBACK
);
844 mUserAgentIsDirty
= PR_TRUE
;
848 if (PREF_CHANGED(UA_PREF("locale"))) {
849 nsCOMPtr
<nsIPrefLocalizedString
> pls
;
850 prefs
->GetComplexValue(UA_PREF("locale"),
851 NS_GET_IID(nsIPrefLocalizedString
),
852 getter_AddRefs(pls
));
855 pls
->ToString(getter_Copies(uval
));
857 CopyUTF16toUTF8(uval
, mLanguage
);
861 rv
= prefs
->GetCharPref(UA_PREF("locale"), getter_Copies(cval
));
863 mLanguage
.Assign(cval
);
866 mUserAgentIsDirty
= PR_TRUE
;
869 // general.useragent.override
870 if (PREF_CHANGED(UA_PREF("override"))) {
871 prefs
->GetCharPref(UA_PREF("override"),
872 getter_Copies(mUserAgentOverride
));
873 mUserAgentIsDirty
= PR_TRUE
;
880 if (PREF_CHANGED(HTTP_PREF("keep-alive.timeout"))) {
881 rv
= prefs
->GetIntPref(HTTP_PREF("keep-alive.timeout"), &val
);
882 if (NS_SUCCEEDED(rv
))
883 mIdleTimeout
= (PRUint16
) CLAMP(val
, 1, 0xffff);
886 if (PREF_CHANGED(HTTP_PREF("request.max-attempts"))) {
887 rv
= prefs
->GetIntPref(HTTP_PREF("request.max-attempts"), &val
);
888 if (NS_SUCCEEDED(rv
))
889 mMaxRequestAttempts
= (PRUint16
) CLAMP(val
, 1, 0xffff);
892 if (PREF_CHANGED(HTTP_PREF("request.max-start-delay"))) {
893 rv
= prefs
->GetIntPref(HTTP_PREF("request.max-start-delay"), &val
);
894 if (NS_SUCCEEDED(rv
)) {
895 mMaxRequestDelay
= (PRUint16
) CLAMP(val
, 0, 0xffff);
897 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_REQUEST_DELAY
,
902 if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
903 rv
= prefs
->GetIntPref(HTTP_PREF("max-connections"), &val
);
904 if (NS_SUCCEEDED(rv
)) {
905 mMaxConnections
= (PRUint16
) CLAMP(val
, 1, 0xffff);
907 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS
,
912 if (PREF_CHANGED(HTTP_PREF("max-connections-per-server"))) {
913 rv
= prefs
->GetIntPref(HTTP_PREF("max-connections-per-server"), &val
);
914 if (NS_SUCCEEDED(rv
)) {
915 mMaxConnectionsPerServer
= (PRUint8
) CLAMP(val
, 1, 0xff);
917 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS_PER_HOST
,
918 mMaxConnectionsPerServer
);
919 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS_PER_PROXY
,
920 mMaxConnectionsPerServer
);
925 if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-server"))) {
926 rv
= prefs
->GetIntPref(HTTP_PREF("max-persistent-connections-per-server"), &val
);
927 if (NS_SUCCEEDED(rv
)) {
928 mMaxPersistentConnectionsPerServer
= (PRUint8
) CLAMP(val
, 1, 0xff);
930 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_HOST
,
931 mMaxPersistentConnectionsPerServer
);
935 if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-proxy"))) {
936 rv
= prefs
->GetIntPref(HTTP_PREF("max-persistent-connections-per-proxy"), &val
);
937 if (NS_SUCCEEDED(rv
)) {
938 mMaxPersistentConnectionsPerProxy
= (PRUint8
) CLAMP(val
, 1, 0xff);
940 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_PROXY
,
941 mMaxPersistentConnectionsPerProxy
);
945 if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
946 rv
= prefs
->GetIntPref(HTTP_PREF("sendRefererHeader"), &val
);
947 if (NS_SUCCEEDED(rv
))
948 mReferrerLevel
= (PRUint8
) CLAMP(val
, 0, 0xff);
951 if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
952 rv
= prefs
->GetIntPref(HTTP_PREF("redirection-limit"), &val
);
953 if (NS_SUCCEEDED(rv
))
954 mRedirectionLimit
= (PRUint8
) CLAMP(val
, 0, 0xff);
957 if (PREF_CHANGED(HTTP_PREF("version"))) {
958 nsXPIDLCString httpVersion
;
959 prefs
->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion
));
961 if (!PL_strcmp(httpVersion
, "1.1"))
962 mHttpVersion
= NS_HTTP_VERSION_1_1
;
963 else if (!PL_strcmp(httpVersion
, "0.9"))
964 mHttpVersion
= NS_HTTP_VERSION_0_9
;
966 mHttpVersion
= NS_HTTP_VERSION_1_0
;
970 if (PREF_CHANGED(HTTP_PREF("proxy.version"))) {
971 nsXPIDLCString httpVersion
;
972 prefs
->GetCharPref(HTTP_PREF("proxy.version"), getter_Copies(httpVersion
));
974 if (!PL_strcmp(httpVersion
, "1.1"))
975 mProxyHttpVersion
= NS_HTTP_VERSION_1_1
;
977 mProxyHttpVersion
= NS_HTTP_VERSION_1_0
;
978 // it does not make sense to issue a HTTP/0.9 request to a proxy server
982 PRBool cVar
= PR_FALSE
;
984 if (PREF_CHANGED(HTTP_PREF("keep-alive"))) {
985 rv
= prefs
->GetBoolPref(HTTP_PREF("keep-alive"), &cVar
);
986 if (NS_SUCCEEDED(rv
)) {
988 mCapabilities
|= NS_HTTP_ALLOW_KEEPALIVE
;
990 mCapabilities
&= ~NS_HTTP_ALLOW_KEEPALIVE
;
994 if (PREF_CHANGED(HTTP_PREF("proxy.keep-alive"))) {
995 rv
= prefs
->GetBoolPref(HTTP_PREF("proxy.keep-alive"), &cVar
);
996 if (NS_SUCCEEDED(rv
)) {
998 mProxyCapabilities
|= NS_HTTP_ALLOW_KEEPALIVE
;
1000 mProxyCapabilities
&= ~NS_HTTP_ALLOW_KEEPALIVE
;
1004 if (PREF_CHANGED(HTTP_PREF("pipelining"))) {
1005 rv
= prefs
->GetBoolPref(HTTP_PREF("pipelining"), &cVar
);
1006 if (NS_SUCCEEDED(rv
)) {
1008 mCapabilities
|= NS_HTTP_ALLOW_PIPELINING
;
1010 mCapabilities
&= ~NS_HTTP_ALLOW_PIPELINING
;
1014 if (PREF_CHANGED(HTTP_PREF("pipelining.maxrequests"))) {
1015 rv
= prefs
->GetIntPref(HTTP_PREF("pipelining.maxrequests"), &val
);
1016 if (NS_SUCCEEDED(rv
)) {
1017 mMaxPipelinedRequests
= CLAMP(val
, 1, NS_HTTP_MAX_PIPELINED_REQUESTS
);
1019 mConnMgr
->UpdateParam(nsHttpConnectionMgr::MAX_PIPELINED_REQUESTS
,
1020 mMaxPipelinedRequests
);
1024 if (PREF_CHANGED(HTTP_PREF("pipelining.ssl"))) {
1025 rv
= prefs
->GetBoolPref(HTTP_PREF("pipelining.ssl"), &cVar
);
1026 if (NS_SUCCEEDED(rv
))
1027 mPipeliningOverSSL
= cVar
;
1030 if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
1031 rv
= prefs
->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar
);
1032 if (NS_SUCCEEDED(rv
)) {
1034 mProxyCapabilities
|= NS_HTTP_ALLOW_PIPELINING
;
1036 mProxyCapabilities
&= ~NS_HTTP_ALLOW_PIPELINING
;
1040 if (PREF_CHANGED(HTTP_PREF("sendSecureXSiteReferrer"))) {
1041 rv
= prefs
->GetBoolPref(HTTP_PREF("sendSecureXSiteReferrer"), &cVar
);
1042 if (NS_SUCCEEDED(rv
))
1043 mSendSecureXSiteReferrer
= cVar
;
1046 if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
1047 nsXPIDLCString accept
;
1048 rv
= prefs
->GetCharPref(HTTP_PREF("accept.default"),
1049 getter_Copies(accept
));
1050 if (NS_SUCCEEDED(rv
))
1054 if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
1055 nsXPIDLCString acceptEncodings
;
1056 rv
= prefs
->GetCharPref(HTTP_PREF("accept-encoding"),
1057 getter_Copies(acceptEncodings
));
1058 if (NS_SUCCEEDED(rv
))
1059 SetAcceptEncodings(acceptEncodings
);
1062 if (PREF_CHANGED(HTTP_PREF("use-cache"))) {
1063 rv
= prefs
->GetBoolPref(HTTP_PREF("use-cache"), &cVar
);
1064 if (NS_SUCCEEDED(rv
)) {
1069 if (PREF_CHANGED(HTTP_PREF("default-socket-type"))) {
1070 nsXPIDLCString sval
;
1071 rv
= prefs
->GetCharPref(HTTP_PREF("default-socket-type"),
1072 getter_Copies(sval
));
1073 if (NS_SUCCEEDED(rv
)) {
1075 mDefaultSocketType
.Adopt(0);
1077 // verify that this socket type is actually valid
1078 nsCOMPtr
<nsISocketProviderService
> sps(
1079 do_GetService(kSocketProviderServiceCID
));
1081 nsCOMPtr
<nsISocketProvider
> sp
;
1082 rv
= sps
->GetSocketProvider(sval
, getter_AddRefs(sp
));
1083 if (NS_SUCCEEDED(rv
)) {
1084 // OK, this looks like a valid socket provider.
1085 mDefaultSocketType
.Assign(sval
);
1092 // enable Persistent caching for HTTPS - bug#205921
1093 if (PREF_CHANGED(BROWSER_PREF("disk_cache_ssl"))) {
1095 rv
= prefs
->GetBoolPref(BROWSER_PREF("disk_cache_ssl"), &cVar
);
1096 if (NS_SUCCEEDED(rv
))
1097 mEnablePersistentHttpsCaching
= cVar
;
1100 if (PREF_CHANGED(HTTP_PREF("phishy-userpass-length"))) {
1101 rv
= prefs
->GetIntPref(HTTP_PREF("phishy-userpass-length"), &val
);
1102 if (NS_SUCCEEDED(rv
))
1103 mPhishyUserPassLength
= (PRUint8
) CLAMP(val
, 0, 0xff);
1110 if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES
)) {
1111 nsCOMPtr
<nsIPrefLocalizedString
> pls
;
1112 prefs
->GetComplexValue(INTL_ACCEPT_LANGUAGES
,
1113 NS_GET_IID(nsIPrefLocalizedString
),
1114 getter_AddRefs(pls
));
1117 pls
->ToString(getter_Copies(uval
));
1119 SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval
).get());
1123 if (PREF_CHANGED(INTL_ACCEPT_CHARSET
)) {
1124 nsCOMPtr
<nsIPrefLocalizedString
> pls
;
1125 prefs
->GetComplexValue(INTL_ACCEPT_CHARSET
,
1126 NS_GET_IID(nsIPrefLocalizedString
),
1127 getter_AddRefs(pls
));
1130 pls
->ToString(getter_Copies(uval
));
1132 SetAcceptCharsets(NS_ConvertUTF16toUTF8(uval
).get());
1140 if (PREF_CHANGED(NETWORK_ENABLEIDN
)) {
1141 PRBool enableIDN
= PR_FALSE
;
1142 prefs
->GetBoolPref(NETWORK_ENABLEIDN
, &enableIDN
);
1143 // No locking is required here since this method runs in the main
1144 // UI thread, and so do all the methods in nsHttpChannel.cpp
1145 // (mIDNConverter is used by nsHttpChannel)
1146 if (enableIDN
&& !mIDNConverter
) {
1147 mIDNConverter
= do_GetService(NS_IDNSERVICE_CONTRACTID
);
1148 NS_ASSERTION(mIDNConverter
, "idnSDK not installed");
1150 else if (!enableIDN
&& mIDNConverter
)
1151 mIDNConverter
= nsnull
;
1155 #undef MULTI_PREF_CHANGED
1159 * Allocates a C string into that contains a ISO 639 language list
1160 * notated with HTTP "q" values for output with a HTTP Accept-Language
1161 * header. Previous q values will be stripped because the order of
1162 * the langs imply the q value. The q values are calculated by dividing
1163 * 1.0 amongst the number of languages present.
1165 * Ex: passing: "en, ja"
1166 * returns: "en,ja;q=0.5"
1168 * passing: "en, ja, fr_CA"
1169 * returns: "en,ja;q=0.7,fr_CA;q=0.3"
1172 PrepareAcceptLanguages(const char *i_AcceptLanguages
, nsACString
&o_AcceptLanguages
)
1174 if (!i_AcceptLanguages
)
1177 PRUint32 n
, size
, wrote
;
1179 char *p
, *p2
, *token
, *q_Accept
, *o_Accept
;
1183 o_Accept
= nsCRT::strdup(i_AcceptLanguages
);
1185 return NS_ERROR_OUT_OF_MEMORY
;
1186 for (p
= o_Accept
, n
= size
= 0; '\0' != *p
; p
++) {
1191 available
= size
+ ++n
* 11 + 1;
1192 q_Accept
= new char[available
];
1194 nsCRT::free(o_Accept
);
1195 return NS_ERROR_OUT_OF_MEMORY
;
1199 dec
= q
/ (double) n
;
1202 for (token
= nsCRT::strtok(o_Accept
, ",", &p
);
1203 token
!= (char *) 0;
1204 token
= nsCRT::strtok(p
, ",", &p
))
1206 token
= net_FindCharNotInSet(token
, HTTP_LWS
);
1208 trim
= net_FindCharInSet(token
, ";" HTTP_LWS
);
1209 if (trim
!= (char*)0) // remove "; q=..." if present
1212 if (*token
!= '\0') {
1213 comma
= n
++ != 0 ? "," : ""; // delimiter if not first item
1214 PRUint32 u
= QVAL_TO_UINT(q
);
1216 wrote
= PR_snprintf(p2
, available
, "%s%s;q=0.%u", comma
, token
, u
);
1218 wrote
= PR_snprintf(p2
, available
, "%s%s", comma
, token
);
1222 NS_ASSERTION(available
> 0, "allocated string not long enough");
1225 nsCRT::free(o_Accept
);
1227 o_AcceptLanguages
.Assign((const char *) q_Accept
);
1234 nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages
)
1237 nsresult rv
= PrepareAcceptLanguages(aAcceptLanguages
, buf
);
1238 if (NS_SUCCEEDED(rv
))
1239 mAcceptLanguages
.Assign(buf
);
1244 * Allocates a C string into that contains a character set/encoding list
1245 * notated with HTTP "q" values for output with a HTTP Accept-Charset
1246 * header. If the UTF-8 character set is not present, it will be added.
1247 * If a wildcard catch-all is not present, it will be added. If more than
1248 * one charset is set (as of 2001-02-07, only one is used), they will be
1249 * comma delimited and with q values set for each charset in decending order.
1251 * Ex: passing: "euc-jp"
1252 * returns: "euc-jp,utf-8;q=0.6,*;q=0.6"
1255 * returns: "UTF-8, *"
1258 PrepareAcceptCharsets(const char *i_AcceptCharset
, nsACString
&o_AcceptCharset
)
1260 PRUint32 n
, size
, wrote
, u
;
1263 char *p
, *p2
, *token
, *q_Accept
, *o_Accept
;
1264 const char *acceptable
, *comma
;
1265 PRBool add_utf
= PR_FALSE
;
1266 PRBool add_asterisk
= PR_FALSE
;
1268 if (!i_AcceptCharset
)
1271 acceptable
= i_AcceptCharset
;
1272 o_Accept
= nsCRT::strdup(acceptable
);
1273 if (nsnull
== o_Accept
)
1274 return NS_ERROR_OUT_OF_MEMORY
;
1275 for (p
= o_Accept
, n
= size
= 0; '\0' != *p
; p
++) {
1280 // only add "utf-8" and "*" to the list if they aren't
1281 // already specified.
1283 if (PL_strcasestr(acceptable
, "utf-8") == NULL
) {
1287 if (PL_strstr(acceptable
, "*") == NULL
) {
1289 add_asterisk
= PR_TRUE
;
1292 available
= size
+ ++n
* 11 + 1;
1293 q_Accept
= new char[available
];
1294 if ((char *) 0 == q_Accept
)
1295 return NS_ERROR_OUT_OF_MEMORY
;
1298 dec
= q
/ (double) n
;
1301 for (token
= nsCRT::strtok(o_Accept
, ",", &p
);
1302 token
!= (char *) 0;
1303 token
= nsCRT::strtok(p
, ",", &p
)) {
1304 token
= net_FindCharNotInSet(token
, HTTP_LWS
);
1306 trim
= net_FindCharInSet(token
, ";" HTTP_LWS
);
1307 if (trim
!= (char*)0) // remove "; q=..." if present
1310 if (*token
!= '\0') {
1311 comma
= n
++ != 0 ? "," : ""; // delimiter if not first item
1312 u
= QVAL_TO_UINT(q
);
1314 wrote
= PR_snprintf(p2
, available
, "%s%s;q=0.%u", comma
, token
, u
);
1316 wrote
= PR_snprintf(p2
, available
, "%s%s", comma
, token
);
1320 NS_ASSERTION(available
> 0, "allocated string not long enough");
1324 comma
= n
++ != 0 ? "," : ""; // delimiter if not first item
1325 u
= QVAL_TO_UINT(q
);
1327 wrote
= PR_snprintf(p2
, available
, "%sutf-8;q=0.%u", comma
, u
);
1329 wrote
= PR_snprintf(p2
, available
, "%sutf-8", comma
);
1333 NS_ASSERTION(available
> 0, "allocated string not long enough");
1336 comma
= n
++ != 0 ? "," : ""; // delimiter if not first item
1338 // keep q of "*" equal to the lowest q value
1339 // in the event of a tie between the q of "*" and a non-wildcard
1340 // the non-wildcard always receives preference.
1343 u
= QVAL_TO_UINT(q
);
1345 wrote
= PR_snprintf(p2
, available
, "%s*;q=0.%u", comma
, u
);
1347 wrote
= PR_snprintf(p2
, available
, "%s*", comma
);
1350 NS_ASSERTION(available
> 0, "allocated string not long enough");
1352 nsCRT::free(o_Accept
);
1354 // change alloc from C++ new/delete to nsCRT::strdup's way
1355 o_AcceptCharset
.Assign(q_Accept
);
1356 #if defined DEBUG_havill
1357 printf("Accept-Charset: %s\n", q_Accept
);
1364 nsHttpHandler::SetAcceptCharsets(const char *aAcceptCharsets
)
1367 nsresult rv
= PrepareAcceptCharsets(aAcceptCharsets
, buf
);
1368 if (NS_SUCCEEDED(rv
))
1369 mAcceptCharsets
.Assign(buf
);
1374 nsHttpHandler::SetAccept(const char *aAccept
)
1381 nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings
)
1383 mAcceptEncodings
= aAcceptEncodings
;
1387 //-----------------------------------------------------------------------------
1388 // nsHttpHandler::nsISupports
1389 //-----------------------------------------------------------------------------
1391 NS_IMPL_THREADSAFE_ISUPPORTS5(nsHttpHandler
,
1392 nsIHttpProtocolHandler
,
1393 nsIProxiedProtocolHandler
,
1396 nsISupportsWeakReference
)
1398 //-----------------------------------------------------------------------------
1399 // nsHttpHandler::nsIProtocolHandler
1400 //-----------------------------------------------------------------------------
1403 nsHttpHandler::GetScheme(nsACString
&aScheme
)
1405 aScheme
.AssignLiteral("http");
1410 nsHttpHandler::GetDefaultPort(PRInt32
*result
)
1412 *result
= NS_HTTP_DEFAULT_PORT
;
1417 nsHttpHandler::GetProtocolFlags(PRUint32
*result
)
1419 *result
= URI_STD
| ALLOWS_PROXY
| ALLOWS_PROXY_HTTP
|
1420 URI_LOADABLE_BY_ANYONE
;
1425 nsHttpHandler::NewURI(const nsACString
&aSpec
,
1426 const char *aCharset
,
1430 LOG(("nsHttpHandler::NewURI\n"));
1431 return ::NewURI(aSpec
, aCharset
, aBaseURI
, NS_HTTP_DEFAULT_PORT
, aURI
);
1435 nsHttpHandler::NewChannel(nsIURI
*uri
, nsIChannel
**result
)
1437 LOG(("nsHttpHandler::NewChannel\n"));
1439 NS_ENSURE_ARG_POINTER(uri
);
1440 NS_ENSURE_ARG_POINTER(result
);
1442 PRBool isHttp
= PR_FALSE
, isHttps
= PR_FALSE
;
1444 // Verify that we have been given a valid scheme
1445 nsresult rv
= uri
->SchemeIs("http", &isHttp
);
1446 if (NS_FAILED(rv
)) return rv
;
1448 rv
= uri
->SchemeIs("https", &isHttps
);
1449 if (NS_FAILED(rv
)) return rv
;
1451 NS_WARNING("Invalid URI scheme");
1452 return NS_ERROR_UNEXPECTED
;
1456 return NewProxiedChannel(uri
, nsnull
, result
);
1460 nsHttpHandler::AllowPort(PRInt32 port
, const char *scheme
, PRBool
*_retval
)
1462 // don't override anything.
1463 *_retval
= PR_FALSE
;
1467 //-----------------------------------------------------------------------------
1468 // nsHttpHandler::nsIProxiedProtocolHandler
1469 //-----------------------------------------------------------------------------
1472 nsHttpHandler::NewProxiedChannel(nsIURI
*uri
,
1473 nsIProxyInfo
* givenProxyInfo
,
1474 nsIChannel
**result
)
1476 nsHttpChannel
*httpChannel
= nsnull
;
1478 LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
1481 nsCOMPtr
<nsProxyInfo
> proxyInfo
;
1482 if (givenProxyInfo
) {
1483 proxyInfo
= do_QueryInterface(givenProxyInfo
);
1484 NS_ENSURE_ARG(proxyInfo
);
1488 nsresult rv
= uri
->SchemeIs("https", &https
);
1492 NS_NEWXPCOM(httpChannel
, nsHttpChannel
);
1494 return NS_ERROR_OUT_OF_MEMORY
;
1495 NS_ADDREF(httpChannel
);
1497 // select proxy caps if using a non-transparent proxy. SSL tunneling
1498 // should not use proxy settings.
1500 if (proxyInfo
&& !nsCRT::strcmp(proxyInfo
->Type(), "http") && !https
)
1501 caps
= mProxyCapabilities
;
1503 caps
= mCapabilities
;
1506 // enable pipelining over SSL if requested
1507 if (mPipeliningOverSSL
)
1508 caps
|= NS_HTTP_ALLOW_PIPELINING
;
1510 // HACK: make sure PSM gets initialized on the main thread.
1511 nsCOMPtr
<nsISocketProviderService
> spserv
=
1512 do_GetService(kSocketProviderServiceCID
);
1514 nsCOMPtr
<nsISocketProvider
> provider
;
1515 spserv
->GetSocketProvider("ssl", getter_AddRefs(provider
));
1519 rv
= httpChannel
->Init(uri
, caps
, proxyInfo
);
1521 if (NS_FAILED(rv
)) {
1522 NS_RELEASE(httpChannel
);
1526 *result
= httpChannel
;
1530 //-----------------------------------------------------------------------------
1531 // nsHttpHandler::nsIHttpProtocolHandler
1532 //-----------------------------------------------------------------------------
1535 nsHttpHandler::GetUserAgent(nsACString
&value
)
1537 value
= UserAgent();
1542 nsHttpHandler::GetAppName(nsACString
&value
)
1549 nsHttpHandler::GetAppVersion(nsACString
&value
)
1551 value
= mAppVersion
;
1556 nsHttpHandler::GetVendor(nsACString
&value
)
1562 nsHttpHandler::SetVendor(const nsACString
&value
)
1565 mUserAgentIsDirty
= PR_TRUE
;
1570 nsHttpHandler::GetVendorSub(nsACString
&value
)
1576 nsHttpHandler::SetVendorSub(const nsACString
&value
)
1579 mUserAgentIsDirty
= PR_TRUE
;
1584 nsHttpHandler::GetVendorComment(nsACString
&value
)
1586 value
= mVendorComment
;
1590 nsHttpHandler::SetVendorComment(const nsACString
&value
)
1592 mVendorComment
= value
;
1593 mUserAgentIsDirty
= PR_TRUE
;
1598 nsHttpHandler::GetProduct(nsACString
&value
)
1604 nsHttpHandler::SetProduct(const nsACString
&value
)
1607 mUserAgentIsDirty
= PR_TRUE
;
1612 nsHttpHandler::GetProductSub(nsACString
&value
)
1614 value
= mProductSub
;
1618 nsHttpHandler::SetProductSub(const nsACString
&value
)
1620 mProductSub
= value
;
1621 mUserAgentIsDirty
= PR_TRUE
;
1626 nsHttpHandler::GetProductComment(nsACString
&value
)
1628 value
= mProductComment
;
1632 nsHttpHandler::SetProductComment(const nsACString
&value
)
1634 mProductComment
= value
;
1635 mUserAgentIsDirty
= PR_TRUE
;
1640 nsHttpHandler::GetPlatform(nsACString
&value
)
1647 nsHttpHandler::GetOscpu(nsACString
&value
)
1654 nsHttpHandler::GetLanguage(nsACString
&value
)
1660 nsHttpHandler::SetLanguage(const nsACString
&value
)
1663 mUserAgentIsDirty
= PR_TRUE
;
1668 nsHttpHandler::GetMisc(nsACString
&value
)
1674 nsHttpHandler::SetMisc(const nsACString
&value
)
1677 mUserAgentIsDirty
= PR_TRUE
;
1681 //-----------------------------------------------------------------------------
1682 // nsHttpHandler::nsIObserver
1683 //-----------------------------------------------------------------------------
1686 nsHttpHandler::Observe(nsISupports
*subject
,
1688 const PRUnichar
*data
)
1690 LOG(("nsHttpHandler::Observe [topic=\"%s\"]\n", topic
));
1692 if (strcmp(topic
, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
) == 0) {
1693 nsCOMPtr
<nsIPrefBranch
> prefBranch
= do_QueryInterface(subject
);
1695 PrefsChanged(prefBranch
, NS_ConvertUTF16toUTF8(data
).get());
1697 else if (strcmp(topic
, "profile-change-net-teardown") == 0 ||
1698 strcmp(topic
, NS_XPCOM_SHUTDOWN_OBSERVER_ID
) == 0) {
1700 // kill off the "prune dead connections" timer
1701 StopPruneDeadConnectionsTimer();
1703 // clear cache of all authentication credentials.
1704 mAuthCache
.ClearAll();
1706 // ensure connection manager is shutdown
1708 mConnMgr
->Shutdown();
1710 // need to reset the session start time since cache validation may
1711 // depend on this value.
1712 mSessionStartTime
= NowInSeconds();
1714 else if (strcmp(topic
, "profile-change-net-restore") == 0) {
1715 // initialize connection manager
1716 InitConnectionMgr();
1718 // restart the "prune dead connections" timer
1719 StartPruneDeadConnectionsTimer();
1721 else if (strcmp(topic
, "timer-callback") == 0) {
1722 // prune dead connections
1724 nsCOMPtr
<nsITimer
> timer
= do_QueryInterface(subject
);
1725 NS_ASSERTION(timer
== mTimer
, "unexpected timer-callback");
1728 mConnMgr
->PruneDeadConnections();
1734 //-----------------------------------------------------------------------------
1735 // nsHttpsHandler implementation
1736 //-----------------------------------------------------------------------------
1738 NS_IMPL_THREADSAFE_ISUPPORTS4(nsHttpsHandler
,
1739 nsIHttpProtocolHandler
,
1740 nsIProxiedProtocolHandler
,
1742 nsISupportsWeakReference
)
1745 nsHttpsHandler::Init()
1747 nsCOMPtr
<nsIProtocolHandler
> httpHandler(
1748 do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http"));
1749 NS_ASSERTION(httpHandler
.get() != nsnull
, "no http handler?");
1754 nsHttpsHandler::GetScheme(nsACString
&aScheme
)
1756 aScheme
.AssignLiteral("https");
1761 nsHttpsHandler::GetDefaultPort(PRInt32
*aPort
)
1763 *aPort
= NS_HTTPS_DEFAULT_PORT
;
1768 nsHttpsHandler::GetProtocolFlags(PRUint32
*aProtocolFlags
)
1770 return gHttpHandler
->GetProtocolFlags(aProtocolFlags
);
1774 nsHttpsHandler::NewURI(const nsACString
&aSpec
,
1775 const char *aOriginCharset
,
1779 return ::NewURI(aSpec
, aOriginCharset
, aBaseURI
, NS_HTTPS_DEFAULT_PORT
, _retval
);
1783 nsHttpsHandler::NewChannel(nsIURI
*aURI
, nsIChannel
**_retval
)
1785 return gHttpHandler
->NewChannel(aURI
, _retval
);
1789 nsHttpsHandler::AllowPort(PRInt32 aPort
, const char *aScheme
, PRBool
*_retval
)
1791 // don't override anything.
1792 *_retval
= PR_FALSE
;