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
5 : *
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/
10 : *
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
14 : * License.
15 : *
16 : * The Original Code is Mozilla.
17 : *
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.
22 : *
23 : * Contributor(s):
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>
33 : * Dão Gottwald <dao@mozilla.com>
34 : *
35 : * Alternatively, the contents of this file may be used under the terms of
36 : * either the GNU General Public License Version 2 or later (the "GPL"), or
37 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
38 : * in which case the provisions of the GPL or the LGPL are applicable instead
39 : * of those above. If you wish to allow use of your version of this file only
40 : * under the terms of either the GPL or the LGPL, and not to allow others to
41 : * use your version of this file under the terms of the MPL, indicate your
42 : * decision by deleting the provisions above and replace them with the notice
43 : * and other provisions required by the GPL or the LGPL. If you do not delete
44 : * the provisions above, a recipient may use your version of this file under
45 : * the terms of any one of the MPL, the GPL or the LGPL.
46 : *
47 : * ***** END LICENSE BLOCK ***** */
48 :
49 : #include "nsHttp.h"
50 : #include "nsHttpHandler.h"
51 : #include "nsHttpChannel.h"
52 : #include "nsHttpConnection.h"
53 : #include "nsHttpResponseHead.h"
54 : #include "nsHttpTransaction.h"
55 : #include "nsHttpAuthCache.h"
56 : #include "nsStandardURL.h"
57 : #include "nsIHttpChannel.h"
58 : #include "nsIURL.h"
59 : #include "nsIStandardURL.h"
60 : #include "nsICacheService.h"
61 : #include "nsICategoryManager.h"
62 : #include "nsCategoryManagerUtils.h"
63 : #include "nsICacheService.h"
64 : #include "nsIPrefService.h"
65 : #include "nsIPrefBranch.h"
66 : #include "nsIPrefLocalizedString.h"
67 : #include "nsISocketProviderService.h"
68 : #include "nsISocketProvider.h"
69 : #include "nsPrintfCString.h"
70 : #include "nsCOMPtr.h"
71 : #include "nsNetCID.h"
72 : #include "prprf.h"
73 : #include "nsReadableUtils.h"
74 : #include "nsQuickSort.h"
75 : #include "nsNetUtil.h"
76 : #include "nsIOService.h"
77 : #include "nsAsyncRedirectVerifyHelper.h"
78 : #include "nsSocketTransportService2.h"
79 : #include "nsAlgorithm.h"
80 : #include "SpdySession.h"
81 :
82 : #include "nsIXULAppInfo.h"
83 :
84 : #include "mozilla/net/NeckoChild.h"
85 :
86 : #if defined(XP_UNIX)
87 : #include <sys/utsname.h>
88 : #endif
89 :
90 : #if defined(XP_WIN)
91 : #include <windows.h>
92 : #endif
93 :
94 : #if defined(XP_MACOSX)
95 : #include <CoreServices/CoreServices.h>
96 : #endif
97 :
98 : #if defined(XP_OS2)
99 : #define INCL_DOSMISC
100 : #include <os2.h>
101 : #endif
102 :
103 : //-----------------------------------------------------------------------------
104 : using namespace mozilla;
105 : using namespace mozilla::net;
106 : #include "mozilla/net/HttpChannelChild.h"
107 :
108 : #include "mozilla/FunctionTimer.h"
109 :
110 : #ifdef DEBUG
111 : // defined by the socket transport service while active
112 : extern PRThread *gSocketThread;
113 : #endif
114 :
115 : static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
116 : static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
117 : static NS_DEFINE_CID(kCookieServiceCID, NS_COOKIESERVICE_CID);
118 : static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
119 : static NS_DEFINE_CID(kSocketProviderServiceCID, NS_SOCKETPROVIDERSERVICE_CID);
120 :
121 : #define UA_PREF_PREFIX "general.useragent."
122 : #ifdef XP_WIN
123 : #define UA_SPARE_PLATFORM
124 : #endif
125 :
126 : #define HTTP_PREF_PREFIX "network.http."
127 : #define INTL_ACCEPT_LANGUAGES "intl.accept_languages"
128 : #define NETWORK_ENABLEIDN "network.enableIDN"
129 : #define BROWSER_PREF_PREFIX "browser.cache."
130 : #define DONOTTRACK_HEADER_ENABLED "privacy.donottrackheader.enabled"
131 : #define TELEMETRY_ENABLED "toolkit.telemetry.enabled"
132 : #define ALLOW_EXPERIMENTS "network.allow-experiments"
133 :
134 : #define UA_PREF(_pref) UA_PREF_PREFIX _pref
135 : #define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
136 : #define BROWSER_PREF(_pref) BROWSER_PREF_PREFIX _pref
137 :
138 : #define NS_HTTP_PROTOCOL_FLAGS (URI_STD | ALLOWS_PROXY | ALLOWS_PROXY_HTTP | URI_LOADABLE_BY_ANYONE)
139 :
140 : //-----------------------------------------------------------------------------
141 :
142 : static nsresult
143 35064 : NewURI(const nsACString &aSpec,
144 : const char *aCharset,
145 : nsIURI *aBaseURI,
146 : PRInt32 aDefaultPort,
147 : nsIURI **aURI)
148 : {
149 35064 : nsStandardURL *url = new nsStandardURL();
150 35064 : if (!url)
151 0 : return NS_ERROR_OUT_OF_MEMORY;
152 35064 : NS_ADDREF(url);
153 :
154 : nsresult rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY,
155 35064 : aDefaultPort, aSpec, aCharset, aBaseURI);
156 35064 : if (NS_FAILED(rv)) {
157 36 : NS_RELEASE(url);
158 36 : return rv;
159 : }
160 :
161 35028 : *aURI = url; // no QI needed
162 35028 : return NS_OK;
163 : }
164 :
165 : //-----------------------------------------------------------------------------
166 : // nsHttpHandler <public>
167 : //-----------------------------------------------------------------------------
168 :
169 : nsHttpHandler *gHttpHandler = nsnull;
170 :
171 679 : nsHttpHandler::nsHttpHandler()
172 : : mConnMgr(nsnull)
173 : , mHttpVersion(NS_HTTP_VERSION_1_1)
174 : , mProxyHttpVersion(NS_HTTP_VERSION_1_1)
175 : , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
176 : , mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
177 : , mReferrerLevel(0xff) // by default we always send a referrer
178 : , mFastFallbackToIPv4(false)
179 679 : , mIdleTimeout(PR_SecondsToInterval(10))
180 679 : , mSpdyTimeout(PR_SecondsToInterval(180))
181 : , mMaxRequestAttempts(10)
182 : , mMaxRequestDelay(10)
183 : , mIdleSynTimeout(250)
184 : , mMaxConnections(24)
185 : , mMaxConnectionsPerServer(8)
186 : , mMaxPersistentConnectionsPerServer(2)
187 : , mMaxPersistentConnectionsPerProxy(4)
188 : , mMaxPipelinedRequests(2)
189 : , mRedirectionLimit(10)
190 : , mPhishyUserPassLength(1)
191 : , mQoSBits(0x00)
192 : , mPipeliningOverSSL(false)
193 : , mInPrivateBrowsingMode(PRIVATE_BROWSING_UNKNOWN)
194 679 : , mLastUniqueID(NowInSeconds())
195 : , mSessionStartTime(0)
196 : , mLegacyAppName("Mozilla")
197 : , mLegacyAppVersion("5.0")
198 : , mProduct("Gecko")
199 : , mUserAgentIsDirty(true)
200 : , mUseCache(true)
201 : , mPromptTempRedirect(true)
202 : , mSendSecureXSiteReferrer(true)
203 : , mEnablePersistentHttpsCaching(false)
204 : , mDoNotTrackEnabled(false)
205 : , mTelemetryEnabled(false)
206 : , mAllowExperiments(true)
207 : , mEnableSpdy(false)
208 : , mCoalesceSpdy(true)
209 : , mUseAlternateProtocol(false)
210 : , mSpdySendingChunkSize(SpdySession::kSendingChunkSize)
211 679 : , mSpdyPingThreshold(PR_SecondsToInterval(44))
212 3395 : , mSpdyPingTimeout(PR_SecondsToInterval(8))
213 : {
214 : #if defined(PR_LOGGING)
215 679 : gHttpLog = PR_NewLogModule("nsHttp");
216 : #endif
217 :
218 679 : LOG(("Creating nsHttpHandler [this=%x].\n", this));
219 :
220 679 : NS_ASSERTION(!gHttpHandler, "HTTP handler already created!");
221 679 : gHttpHandler = this;
222 679 : }
223 :
224 2031 : nsHttpHandler::~nsHttpHandler()
225 : {
226 677 : LOG(("Deleting nsHttpHandler [this=%x]\n", this));
227 :
228 : // make sure the connection manager is shutdown
229 677 : if (mConnMgr) {
230 677 : mConnMgr->Shutdown();
231 677 : NS_RELEASE(mConnMgr);
232 : }
233 :
234 : // Note: don't call NeckoChild::DestroyNeckoChild() here, as it's too late
235 : // and it'll segfault. NeckoChild will get cleaned up by process exit.
236 :
237 677 : nsHttp::DestroyAtomTable();
238 :
239 677 : gHttpHandler = nsnull;
240 2708 : }
241 :
242 : nsresult
243 679 : nsHttpHandler::Init()
244 : {
245 : NS_TIME_FUNCTION;
246 :
247 : nsresult rv;
248 :
249 679 : LOG(("nsHttpHandler::Init\n"));
250 :
251 679 : rv = nsHttp::CreateAtomTable();
252 679 : if (NS_FAILED(rv))
253 0 : return rv;
254 :
255 679 : mIOService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
256 679 : if (NS_FAILED(rv)) {
257 0 : NS_WARNING("unable to continue without io service");
258 0 : return rv;
259 : }
260 :
261 679 : if (IsNeckoChild())
262 0 : NeckoChild::InitNeckoChild();
263 :
264 679 : InitUserAgentComponents();
265 :
266 : // monitor some preference changes
267 1358 : nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
268 679 : if (prefBranch) {
269 679 : prefBranch->AddObserver(HTTP_PREF_PREFIX, this, true);
270 679 : prefBranch->AddObserver(UA_PREF_PREFIX, this, true);
271 679 : prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, true);
272 679 : prefBranch->AddObserver(NETWORK_ENABLEIDN, this, true);
273 679 : prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true);
274 679 : prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true);
275 679 : prefBranch->AddObserver(TELEMETRY_ENABLED, this, true);
276 :
277 679 : PrefsChanged(prefBranch, nsnull);
278 : }
279 :
280 679 : mMisc.AssignLiteral("rv:" MOZILLA_UAVERSION);
281 :
282 : nsCOMPtr<nsIXULAppInfo> appInfo =
283 1358 : do_GetService("@mozilla.org/xre/app-info;1");
284 :
285 679 : mAppName.AssignLiteral(MOZ_APP_UA_NAME);
286 679 : if (mAppName.Length() == 0 && appInfo) {
287 299 : appInfo->GetName(mAppName);
288 299 : appInfo->GetVersion(mAppVersion);
289 299 : mAppName.StripChars(" ()<>@,;:\\\"/[]?={}");
290 : } else {
291 380 : mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION);
292 : }
293 :
294 : #if DEBUG
295 : // dump user agent prefs
296 679 : LOG(("> legacy-app-name = %s\n", mLegacyAppName.get()));
297 679 : LOG(("> legacy-app-version = %s\n", mLegacyAppVersion.get()));
298 679 : LOG(("> platform = %s\n", mPlatform.get()));
299 679 : LOG(("> oscpu = %s\n", mOscpu.get()));
300 679 : LOG(("> misc = %s\n", mMisc.get()));
301 679 : LOG(("> product = %s\n", mProduct.get()));
302 679 : LOG(("> product-sub = %s\n", mProductSub.get()));
303 679 : LOG(("> app-name = %s\n", mAppName.get()));
304 679 : LOG(("> app-version = %s\n", mAppVersion.get()));
305 679 : LOG(("> compat-firefox = %s\n", mCompatFirefox.get()));
306 679 : LOG(("> user-agent = %s\n", UserAgent().get()));
307 : #endif
308 :
309 679 : mSessionStartTime = NowInSeconds();
310 :
311 679 : rv = mAuthCache.Init();
312 679 : if (NS_FAILED(rv)) return rv;
313 :
314 679 : rv = InitConnectionMgr();
315 679 : if (NS_FAILED(rv)) return rv;
316 :
317 : #ifdef ANDROID
318 : mProductSub.AssignLiteral(MOZILLA_UAVERSION);
319 : #else
320 679 : mProductSub.AssignLiteral(MOZ_UA_BUILDID);
321 : #endif
322 679 : if (mProductSub.IsEmpty() && appInfo)
323 299 : appInfo->GetPlatformBuildID(mProductSub);
324 679 : if (mProductSub.Length() > 8)
325 233 : mProductSub.SetLength(8);
326 :
327 : // Startup the http category
328 : // Bring alive the objects in the http-protocol-startup category
329 : NS_CreateServicesFromCategory(NS_HTTP_STARTUP_CATEGORY,
330 : static_cast<nsISupports*>(static_cast<void*>(this)),
331 679 : NS_HTTP_STARTUP_TOPIC);
332 :
333 679 : mObserverService = mozilla::services::GetObserverService();
334 679 : if (mObserverService) {
335 679 : mObserverService->AddObserver(this, "profile-change-net-teardown", true);
336 679 : mObserverService->AddObserver(this, "profile-change-net-restore", true);
337 679 : mObserverService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
338 679 : mObserverService->AddObserver(this, "net:clear-active-logins", true);
339 679 : mObserverService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true);
340 679 : mObserverService->AddObserver(this, "net:prune-dead-connections", true);
341 : }
342 :
343 679 : return NS_OK;
344 : }
345 :
346 : nsresult
347 679 : nsHttpHandler::InitConnectionMgr()
348 : {
349 : NS_TIME_FUNCTION;
350 :
351 : nsresult rv;
352 :
353 679 : if (!mConnMgr) {
354 679 : mConnMgr = new nsHttpConnectionMgr();
355 679 : if (!mConnMgr)
356 0 : return NS_ERROR_OUT_OF_MEMORY;
357 679 : NS_ADDREF(mConnMgr);
358 : }
359 :
360 : rv = mConnMgr->Init(mMaxConnections,
361 : mMaxConnectionsPerServer,
362 : mMaxConnectionsPerServer,
363 : mMaxPersistentConnectionsPerServer,
364 : mMaxPersistentConnectionsPerProxy,
365 : mMaxRequestDelay,
366 679 : mMaxPipelinedRequests);
367 679 : return rv;
368 : }
369 :
370 : nsresult
371 3514 : nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
372 : PRUint8 caps,
373 : bool useProxy)
374 : {
375 : nsresult rv;
376 :
377 : // Add the "User-Agent" header
378 3514 : rv = request->SetHeader(nsHttp::User_Agent, UserAgent());
379 3514 : if (NS_FAILED(rv)) return rv;
380 :
381 : // MIME based content negotiation lives!
382 : // Add the "Accept" header
383 3514 : rv = request->SetHeader(nsHttp::Accept, mAccept);
384 3514 : if (NS_FAILED(rv)) return rv;
385 :
386 : // Add the "Accept-Language" header
387 3514 : if (!mAcceptLanguages.IsEmpty()) {
388 : // Add the "Accept-Language" header
389 3514 : rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages);
390 3514 : if (NS_FAILED(rv)) return rv;
391 : }
392 :
393 : // Add the "Accept-Encoding" header
394 3514 : rv = request->SetHeader(nsHttp::Accept_Encoding, mAcceptEncodings);
395 3514 : if (NS_FAILED(rv)) return rv;
396 :
397 : // RFC2616 section 19.6.2 states that the "Connection: keep-alive"
398 : // and "Keep-alive" request headers should not be sent by HTTP/1.1
399 : // user-agents. Otherwise, problems with proxy servers (especially
400 : // transparent proxies) can result.
401 : //
402 : // However, we need to send something so that we can use keepalive
403 : // with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when
404 : // we're talking to an http proxy, and "Connection:" otherwise.
405 : // We no longer send the Keep-Alive request header.
406 :
407 7028 : NS_NAMED_LITERAL_CSTRING(close, "close");
408 7028 : NS_NAMED_LITERAL_CSTRING(keepAlive, "keep-alive");
409 :
410 3514 : const nsACString *connectionType = &close;
411 3514 : if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
412 3514 : connectionType = &keepAlive;
413 0 : } else if (useProxy) {
414 : // Bug 92006
415 0 : request->SetHeader(nsHttp::Connection, close);
416 : }
417 :
418 : // Add the "Do-Not-Track" header
419 3514 : if (mDoNotTrackEnabled) {
420 : rv = request->SetHeader(nsHttp::DoNotTrack,
421 0 : NS_LITERAL_CSTRING("1"));
422 0 : if (NS_FAILED(rv)) return rv;
423 : }
424 :
425 : const nsHttpAtom &header = useProxy ? nsHttp::Proxy_Connection
426 3514 : : nsHttp::Connection;
427 3514 : return request->SetHeader(header, *connectionType);
428 : }
429 :
430 : bool
431 4 : nsHttpHandler::IsAcceptableEncoding(const char *enc)
432 : {
433 4 : if (!enc)
434 0 : return false;
435 :
436 : // HTTP 1.1 allows servers to send x-gzip and x-compress instead
437 : // of gzip and compress, for example. So, we'll always strip off
438 : // an "x-" prefix before matching the encoding to one we claim
439 : // to accept.
440 4 : if (!PL_strncasecmp(enc, "x-", 2))
441 0 : enc += 2;
442 :
443 4 : return nsHttp::FindToken(mAcceptEncodings.get(), enc, HTTP_LWS ",") != nsnull;
444 : }
445 :
446 : nsresult
447 2614 : nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy,
448 : nsICacheSession **result)
449 : {
450 : nsresult rv;
451 :
452 : // Skip cache if disabled in preferences
453 2614 : if (!mUseCache)
454 0 : return NS_ERROR_NOT_AVAILABLE;
455 :
456 : // We want to get the pointer to the cache service each time we're called,
457 : // because it's possible for some add-ons (such as Google Gears) to swap
458 : // in new cache services on the fly, and we want to pick them up as
459 : // appropriate.
460 : nsCOMPtr<nsICacheService> serv = do_GetService(NS_CACHESERVICE_CONTRACTID,
461 5228 : &rv);
462 2614 : if (NS_FAILED(rv)) return rv;
463 :
464 2614 : const char *sessionName = "HTTP";
465 2614 : switch (storagePolicy) {
466 : case nsICache::STORE_IN_MEMORY:
467 0 : sessionName = "HTTP-memory-only";
468 0 : break;
469 : case nsICache::STORE_OFFLINE:
470 0 : sessionName = "HTTP-offline";
471 0 : break;
472 : default:
473 2614 : break;
474 : }
475 :
476 5228 : nsCOMPtr<nsICacheSession> cacheSession;
477 2614 : rv = serv->CreateSession(sessionName,
478 : storagePolicy,
479 : nsICache::STREAM_BASED,
480 2614 : getter_AddRefs(cacheSession));
481 2614 : if (NS_FAILED(rv)) return rv;
482 :
483 2614 : rv = cacheSession->SetDoomEntriesIfExpired(false);
484 2614 : if (NS_FAILED(rv)) return rv;
485 :
486 2614 : NS_ADDREF(*result = cacheSession);
487 :
488 2614 : return NS_OK;
489 : }
490 :
491 : bool
492 0 : nsHttpHandler::InPrivateBrowsingMode()
493 : {
494 0 : if (PRIVATE_BROWSING_UNKNOWN == mInPrivateBrowsingMode) {
495 : // figure out if we're starting in private browsing mode
496 : nsCOMPtr<nsIPrivateBrowsingService> pbs =
497 0 : do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
498 0 : if (!pbs)
499 0 : return PRIVATE_BROWSING_OFF;
500 :
501 0 : bool p = false;
502 0 : pbs->GetPrivateBrowsingEnabled(&p);
503 0 : mInPrivateBrowsingMode = p ? PRIVATE_BROWSING_ON : PRIVATE_BROWSING_OFF;
504 : }
505 0 : return PRIVATE_BROWSING_ON == mInPrivateBrowsingMode;
506 : }
507 :
508 : nsresult
509 894 : nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
510 : {
511 894 : if (!mStreamConvSvc) {
512 : nsresult rv;
513 71 : mStreamConvSvc = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
514 71 : if (NS_FAILED(rv)) return rv;
515 : }
516 894 : *result = mStreamConvSvc;
517 894 : NS_ADDREF(*result);
518 894 : return NS_OK;
519 : }
520 :
521 : nsIStrictTransportSecurityService*
522 5051 : nsHttpHandler::GetSTSService()
523 : {
524 5051 : if (!mSTSService)
525 265 : mSTSService = do_GetService(NS_STSSERVICE_CONTRACTID);
526 5051 : return mSTSService;
527 : }
528 :
529 : nsICookieService *
530 3507 : nsHttpHandler::GetCookieService()
531 : {
532 3507 : if (!mCookieService)
533 265 : mCookieService = do_GetService(NS_COOKIESERVICE_CONTRACTID);
534 3507 : return mCookieService;
535 : }
536 :
537 : nsresult
538 327 : nsHttpHandler::GetIOService(nsIIOService** result)
539 : {
540 327 : NS_ADDREF(*result = mIOService);
541 327 : return NS_OK;
542 : }
543 :
544 : PRUint32
545 0 : nsHttpHandler::Get32BitsOfPseudoRandom()
546 : {
547 : // only confirm rand seeding on socket thread
548 0 : NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
549 :
550 : // rand() provides different amounts of PRNG on different platforms.
551 : // 15 or 31 bits are common amounts.
552 :
553 : PR_STATIC_ASSERT(RAND_MAX >= 0xfff);
554 :
555 : #if RAND_MAX < 0xffffU
556 : return ((PRUint16) rand() << 20) |
557 : (((PRUint16) rand() & 0xfff) << 8) |
558 : ((PRUint16) rand() & 0xff);
559 : #elif RAND_MAX < 0xffffffffU
560 0 : return ((PRUint16) rand() << 16) | ((PRUint16) rand() & 0xffff);
561 : #else
562 : return (PRUint32) rand();
563 : #endif
564 : }
565 :
566 : void
567 6553 : nsHttpHandler::NotifyObservers(nsIHttpChannel *chan, const char *event)
568 : {
569 6553 : LOG(("nsHttpHandler::NotifyObservers [chan=%x event=\"%s\"]\n", chan, event));
570 6553 : if (mObserverService)
571 6553 : mObserverService->NotifyObservers(chan, event, nsnull);
572 6553 : }
573 :
574 : nsresult
575 155 : nsHttpHandler::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
576 : PRUint32 flags)
577 : {
578 : // TODO E10S This helper has to be initialized on the other process
579 : nsRefPtr<nsAsyncRedirectVerifyHelper> redirectCallbackHelper =
580 310 : new nsAsyncRedirectVerifyHelper();
581 :
582 155 : return redirectCallbackHelper->Init(oldChan, newChan, flags);
583 : }
584 :
585 : /* static */ nsresult
586 3514 : nsHttpHandler::GenerateHostPort(const nsCString& host, PRInt32 port,
587 : nsCString& hostLine)
588 : {
589 3514 : return NS_GenerateHostPort(host, port, hostLine);
590 : }
591 :
592 : //-----------------------------------------------------------------------------
593 : // nsHttpHandler <private>
594 : //-----------------------------------------------------------------------------
595 :
596 : const nsAFlatCString &
597 3561 : nsHttpHandler::UserAgent()
598 : {
599 3561 : if (mUserAgentOverride) {
600 8 : LOG(("using general.useragent.override : %s\n", mUserAgentOverride.get()));
601 8 : return mUserAgentOverride;
602 : }
603 :
604 3553 : if (mUserAgentIsDirty) {
605 285 : BuildUserAgent();
606 285 : mUserAgentIsDirty = false;
607 : }
608 :
609 3553 : return mUserAgent;
610 : }
611 :
612 : void
613 285 : nsHttpHandler::BuildUserAgent()
614 : {
615 285 : LOG(("nsHttpHandler::BuildUserAgent\n"));
616 :
617 285 : NS_ASSERTION(!mLegacyAppName.IsEmpty() &&
618 : !mLegacyAppVersion.IsEmpty() &&
619 : !mPlatform.IsEmpty() &&
620 : !mOscpu.IsEmpty(),
621 : "HTTP cannot send practical requests without this much");
622 :
623 : // preallocate to worst-case size, which should always be better
624 : // than if we didn't preallocate at all.
625 285 : mUserAgent.SetCapacity(mLegacyAppName.Length() +
626 285 : mLegacyAppVersion.Length() +
627 : #ifndef UA_SPARE_PLATFORM
628 285 : mPlatform.Length() +
629 : #endif
630 285 : mOscpu.Length() +
631 285 : mMisc.Length() +
632 285 : mProduct.Length() +
633 285 : mProductSub.Length() +
634 285 : mAppName.Length() +
635 285 : mAppVersion.Length() +
636 285 : mCompatFirefox.Length() +
637 285 : mCompatDevice.Length() +
638 2850 : 13);
639 :
640 : // Application portion
641 285 : mUserAgent.Assign(mLegacyAppName);
642 285 : mUserAgent += '/';
643 285 : mUserAgent += mLegacyAppVersion;
644 285 : mUserAgent += ' ';
645 :
646 : // Application comment
647 285 : mUserAgent += '(';
648 : #ifndef UA_SPARE_PLATFORM
649 285 : mUserAgent += mPlatform;
650 285 : mUserAgent.AppendLiteral("; ");
651 : #endif
652 : #ifdef ANDROID
653 : if (!mCompatDevice.IsEmpty()) {
654 : mUserAgent += mCompatDevice;
655 : mUserAgent.AppendLiteral("; ");
656 : }
657 : #else
658 285 : mUserAgent += mOscpu;
659 285 : mUserAgent.AppendLiteral("; ");
660 : #endif
661 285 : mUserAgent += mMisc;
662 285 : mUserAgent += ')';
663 :
664 : // Product portion
665 285 : mUserAgent += ' ';
666 285 : mUserAgent += mProduct;
667 285 : mUserAgent += '/';
668 285 : mUserAgent += mProductSub;
669 :
670 : // "Firefox/x.y.z" compatibility token
671 285 : if (!mCompatFirefox.IsEmpty()) {
672 0 : mUserAgent += ' ';
673 0 : mUserAgent += mCompatFirefox;
674 : }
675 :
676 : // App portion
677 285 : mUserAgent += ' ';
678 285 : mUserAgent += mAppName;
679 285 : mUserAgent += '/';
680 285 : mUserAgent += mAppVersion;
681 285 : }
682 :
683 : #ifdef XP_WIN
684 : #define WNT_BASE "Windows NT %ld.%ld"
685 : #define W64_PREFIX "; Win64"
686 : #endif
687 :
688 : void
689 679 : nsHttpHandler::InitUserAgentComponents()
690 : {
691 : // Gather platform.
692 : mPlatform.AssignLiteral(
693 : #if defined(ANDROID)
694 : "Android"
695 : #elif defined(XP_OS2)
696 : "OS/2"
697 : #elif defined(XP_WIN)
698 : "Windows"
699 : #elif defined(XP_MACOSX)
700 : "Macintosh"
701 : #elif defined(MOZ_PLATFORM_MAEMO)
702 : "Maemo"
703 : #elif defined(MOZ_X11)
704 : "X11"
705 : #else
706 : "?"
707 : #endif
708 679 : );
709 :
710 : #if defined(ANDROID)
711 : nsCOMPtr<nsIPropertyBag2> infoService = do_GetService("@mozilla.org/system-info;1");
712 : NS_ASSERTION(infoService, "Could not find a system info service");
713 :
714 : bool isTablet = false;
715 : infoService->GetPropertyAsBool(NS_LITERAL_STRING("tablet"), &isTablet);
716 : if (isTablet)
717 : mCompatDevice.AssignLiteral("Tablet");
718 : else
719 : mCompatDevice.AssignLiteral("Mobile");
720 : #endif
721 :
722 : // Gather OS/CPU.
723 : #if defined(XP_OS2)
724 : ULONG os2ver = 0;
725 : DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_MINOR,
726 : &os2ver, sizeof(os2ver));
727 : if (os2ver == 11)
728 : mOscpu.AssignLiteral("2.11");
729 : else if (os2ver == 30)
730 : mOscpu.AssignLiteral("Warp 3");
731 : else if (os2ver == 40)
732 : mOscpu.AssignLiteral("Warp 4");
733 : else if (os2ver == 45)
734 : mOscpu.AssignLiteral("Warp 4.5");
735 :
736 : #elif defined(XP_WIN)
737 : OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
738 : if (GetVersionEx(&info)) {
739 : const char *format;
740 : #if defined _M_IA64
741 : format = WNT_BASE W64_PREFIX "; IA64";
742 : #elif defined _M_X64 || defined _M_AMD64
743 : format = WNT_BASE W64_PREFIX "; x64";
744 : #else
745 : BOOL isWow64 = FALSE;
746 : if (!IsWow64Process(GetCurrentProcess(), &isWow64)) {
747 : isWow64 = FALSE;
748 : }
749 : format = isWow64
750 : ? WNT_BASE "; WOW64"
751 : : WNT_BASE;
752 : #endif
753 : char *buf = PR_smprintf(format,
754 : info.dwMajorVersion,
755 : info.dwMinorVersion);
756 : if (buf) {
757 : mOscpu = buf;
758 : PR_smprintf_free(buf);
759 : }
760 : }
761 : #elif defined (XP_MACOSX)
762 : #if defined(__ppc__)
763 : mOscpu.AssignLiteral("PPC Mac OS X");
764 : #elif defined(__i386__) || defined(__x86_64__)
765 : mOscpu.AssignLiteral("Intel Mac OS X");
766 : #endif
767 : SInt32 majorVersion, minorVersion;
768 : if ((::Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
769 : (::Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
770 : mOscpu += nsPrintfCString(" %d.%d", majorVersion, minorVersion);
771 : }
772 : #elif defined (XP_UNIX)
773 : struct utsname name;
774 :
775 679 : int ret = uname(&name);
776 679 : if (ret >= 0) {
777 1358 : nsCAutoString buf;
778 679 : buf = (char*)name.sysname;
779 :
780 679 : if (strcmp(name.machine, "x86_64") == 0 &&
781 : sizeof(void *) == sizeof(PRInt32)) {
782 : // We're running 32-bit code on x86_64. Make this browser
783 : // look like it's running on i686 hardware, but append "
784 : // (x86_64)" to the end of the oscpu identifier to be able
785 : // to differentiate this from someone running 64-bit code
786 : // on x86_64..
787 :
788 0 : buf += " i686 on x86_64";
789 : } else {
790 679 : buf += ' ';
791 :
792 : #ifdef AIX
793 : // AIX uname returns machine specific info in the uname.machine
794 : // field and does not return the cpu type like other platforms.
795 : // We use the AIX version and release numbers instead.
796 : buf += (char*)name.version;
797 : buf += '.';
798 : buf += (char*)name.release;
799 : #else
800 679 : buf += (char*)name.machine;
801 : #endif
802 : }
803 :
804 679 : mOscpu.Assign(buf);
805 : }
806 : #endif
807 :
808 679 : mUserAgentIsDirty = true;
809 679 : }
810 :
811 : PRUint32
812 3656 : nsHttpHandler::MaxSocketCount()
813 : {
814 : PR_CallOnce(&nsSocketTransportService::gMaxCountInitOnce,
815 3656 : nsSocketTransportService::DiscoverMaxCount);
816 : // Don't use the full max count because sockets can be held in
817 : // the persistent connection pool for a long time and that could
818 : // starve other users.
819 :
820 3656 : PRUint32 maxCount = nsSocketTransportService::gMaxCount;
821 3656 : if (maxCount <= 8)
822 0 : maxCount = 1;
823 : else
824 3656 : maxCount -= 8;
825 :
826 3656 : return maxCount;
827 : }
828 :
829 : void
830 698 : nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
831 : {
832 698 : nsresult rv = NS_OK;
833 : PRInt32 val;
834 :
835 698 : LOG(("nsHttpHandler::PrefsChanged [pref=%s]\n", pref));
836 :
837 : #define PREF_CHANGED(p) ((pref == nsnull) || !PL_strcmp(pref, p))
838 : #define MULTI_PREF_CHANGED(p) \
839 : ((pref == nsnull) || !PL_strncmp(pref, p, sizeof(p) - 1))
840 :
841 : //
842 : // UA components
843 : //
844 :
845 698 : bool cVar = false;
846 :
847 698 : if (PREF_CHANGED(UA_PREF("compatMode.firefox"))) {
848 679 : rv = prefs->GetBoolPref(UA_PREF("compatMode.firefox"), &cVar);
849 679 : if (NS_SUCCEEDED(rv) && cVar) {
850 0 : mCompatFirefox.AssignLiteral("Firefox/" MOZ_UA_FIREFOX_VERSION);
851 : } else {
852 679 : mCompatFirefox.Truncate();
853 : }
854 679 : mUserAgentIsDirty = true;
855 : }
856 :
857 : // general.useragent.override
858 698 : if (PREF_CHANGED(UA_PREF("override"))) {
859 : prefs->GetCharPref(UA_PREF("override"),
860 682 : getter_Copies(mUserAgentOverride));
861 682 : mUserAgentIsDirty = true;
862 : }
863 :
864 : //
865 : // HTTP options
866 : //
867 :
868 698 : if (PREF_CHANGED(HTTP_PREF("keep-alive.timeout"))) {
869 679 : rv = prefs->GetIntPref(HTTP_PREF("keep-alive.timeout"), &val);
870 679 : if (NS_SUCCEEDED(rv))
871 679 : mIdleTimeout = PR_SecondsToInterval(clamped(val, 1, 0xffff));
872 : }
873 :
874 698 : if (PREF_CHANGED(HTTP_PREF("request.max-attempts"))) {
875 679 : rv = prefs->GetIntPref(HTTP_PREF("request.max-attempts"), &val);
876 679 : if (NS_SUCCEEDED(rv))
877 0 : mMaxRequestAttempts = (PRUint16) clamped(val, 1, 0xffff);
878 : }
879 :
880 698 : if (PREF_CHANGED(HTTP_PREF("request.max-start-delay"))) {
881 679 : rv = prefs->GetIntPref(HTTP_PREF("request.max-start-delay"), &val);
882 679 : if (NS_SUCCEEDED(rv)) {
883 679 : mMaxRequestDelay = (PRUint16) clamped(val, 0, 0xffff);
884 679 : if (mConnMgr)
885 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_REQUEST_DELAY,
886 0 : mMaxRequestDelay);
887 : }
888 : }
889 :
890 698 : if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
891 679 : rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
892 679 : if (NS_SUCCEEDED(rv)) {
893 :
894 : mMaxConnections = (PRUint16) clamped((PRUint32)val,
895 679 : (PRUint32)1, MaxSocketCount());
896 :
897 679 : if (mConnMgr)
898 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
899 0 : mMaxConnections);
900 : }
901 : }
902 :
903 698 : if (PREF_CHANGED(HTTP_PREF("max-connections-per-server"))) {
904 679 : rv = prefs->GetIntPref(HTTP_PREF("max-connections-per-server"), &val);
905 679 : if (NS_SUCCEEDED(rv)) {
906 679 : mMaxConnectionsPerServer = (PRUint8) clamped(val, 1, 0xff);
907 679 : if (mConnMgr) {
908 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS_PER_HOST,
909 0 : mMaxConnectionsPerServer);
910 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS_PER_PROXY,
911 0 : mMaxConnectionsPerServer);
912 : }
913 : }
914 : }
915 :
916 698 : if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-server"))) {
917 679 : rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-server"), &val);
918 679 : if (NS_SUCCEEDED(rv)) {
919 679 : mMaxPersistentConnectionsPerServer = (PRUint8) clamped(val, 1, 0xff);
920 679 : if (mConnMgr)
921 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_HOST,
922 0 : mMaxPersistentConnectionsPerServer);
923 : }
924 : }
925 :
926 698 : if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-proxy"))) {
927 679 : rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-proxy"), &val);
928 679 : if (NS_SUCCEEDED(rv)) {
929 679 : mMaxPersistentConnectionsPerProxy = (PRUint8) clamped(val, 1, 0xff);
930 679 : if (mConnMgr)
931 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
932 0 : mMaxPersistentConnectionsPerProxy);
933 : }
934 : }
935 :
936 698 : if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
937 679 : rv = prefs->GetIntPref(HTTP_PREF("sendRefererHeader"), &val);
938 679 : if (NS_SUCCEEDED(rv))
939 679 : mReferrerLevel = (PRUint8) clamped(val, 0, 0xff);
940 : }
941 :
942 698 : if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
943 679 : rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
944 679 : if (NS_SUCCEEDED(rv))
945 679 : mRedirectionLimit = (PRUint8) clamped(val, 0, 0xff);
946 : }
947 :
948 698 : if (PREF_CHANGED(HTTP_PREF("connection-retry-timeout"))) {
949 679 : rv = prefs->GetIntPref(HTTP_PREF("connection-retry-timeout"), &val);
950 679 : if (NS_SUCCEEDED(rv))
951 679 : mIdleSynTimeout = (PRUint16) clamped(val, 0, 3000);
952 : }
953 :
954 698 : if (PREF_CHANGED(HTTP_PREF("fast-fallback-to-IPv4"))) {
955 679 : rv = prefs->GetBoolPref(HTTP_PREF("fast-fallback-to-IPv4"), &cVar);
956 679 : if (NS_SUCCEEDED(rv))
957 679 : mFastFallbackToIPv4 = cVar;
958 : }
959 :
960 698 : if (PREF_CHANGED(HTTP_PREF("version"))) {
961 1358 : nsXPIDLCString httpVersion;
962 679 : prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));
963 679 : if (httpVersion) {
964 679 : if (!PL_strcmp(httpVersion, "1.1"))
965 679 : mHttpVersion = NS_HTTP_VERSION_1_1;
966 0 : else if (!PL_strcmp(httpVersion, "0.9"))
967 0 : mHttpVersion = NS_HTTP_VERSION_0_9;
968 : else
969 0 : mHttpVersion = NS_HTTP_VERSION_1_0;
970 : }
971 : }
972 :
973 698 : if (PREF_CHANGED(HTTP_PREF("proxy.version"))) {
974 1358 : nsXPIDLCString httpVersion;
975 679 : prefs->GetCharPref(HTTP_PREF("proxy.version"), getter_Copies(httpVersion));
976 679 : if (httpVersion) {
977 679 : if (!PL_strcmp(httpVersion, "1.1"))
978 679 : mProxyHttpVersion = NS_HTTP_VERSION_1_1;
979 : else
980 0 : mProxyHttpVersion = NS_HTTP_VERSION_1_0;
981 : // it does not make sense to issue a HTTP/0.9 request to a proxy server
982 : }
983 : }
984 :
985 698 : if (PREF_CHANGED(HTTP_PREF("keep-alive"))) {
986 679 : rv = prefs->GetBoolPref(HTTP_PREF("keep-alive"), &cVar);
987 679 : if (NS_SUCCEEDED(rv)) {
988 679 : if (cVar)
989 679 : mCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
990 : else
991 0 : mCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
992 : }
993 : }
994 :
995 698 : if (PREF_CHANGED(HTTP_PREF("proxy.keep-alive"))) {
996 679 : rv = prefs->GetBoolPref(HTTP_PREF("proxy.keep-alive"), &cVar);
997 679 : if (NS_SUCCEEDED(rv)) {
998 679 : if (cVar)
999 679 : mProxyCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
1000 : else
1001 0 : mProxyCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
1002 : }
1003 : }
1004 :
1005 698 : if (PREF_CHANGED(HTTP_PREF("pipelining"))) {
1006 679 : rv = prefs->GetBoolPref(HTTP_PREF("pipelining"), &cVar);
1007 679 : if (NS_SUCCEEDED(rv)) {
1008 679 : if (cVar)
1009 0 : mCapabilities |= NS_HTTP_ALLOW_PIPELINING;
1010 : else
1011 679 : mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
1012 : }
1013 : }
1014 :
1015 698 : if (PREF_CHANGED(HTTP_PREF("pipelining.maxrequests"))) {
1016 679 : rv = prefs->GetIntPref(HTTP_PREF("pipelining.maxrequests"), &val);
1017 679 : if (NS_SUCCEEDED(rv)) {
1018 679 : mMaxPipelinedRequests = clamped(val, 1, NS_HTTP_MAX_PIPELINED_REQUESTS);
1019 679 : if (mConnMgr)
1020 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PIPELINED_REQUESTS,
1021 0 : mMaxPipelinedRequests);
1022 : }
1023 : }
1024 :
1025 698 : if (PREF_CHANGED(HTTP_PREF("pipelining.ssl"))) {
1026 679 : rv = prefs->GetBoolPref(HTTP_PREF("pipelining.ssl"), &cVar);
1027 679 : if (NS_SUCCEEDED(rv))
1028 679 : mPipeliningOverSSL = cVar;
1029 : }
1030 :
1031 698 : if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
1032 679 : rv = prefs->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar);
1033 679 : if (NS_SUCCEEDED(rv)) {
1034 679 : if (cVar)
1035 0 : mProxyCapabilities |= NS_HTTP_ALLOW_PIPELINING;
1036 : else
1037 679 : mProxyCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
1038 : }
1039 : }
1040 :
1041 698 : if (PREF_CHANGED(HTTP_PREF("qos"))) {
1042 679 : rv = prefs->GetIntPref(HTTP_PREF("qos"), &val);
1043 679 : if (NS_SUCCEEDED(rv))
1044 679 : mQoSBits = (PRUint8) clamped(val, 0, 0xff);
1045 : }
1046 :
1047 698 : if (PREF_CHANGED(HTTP_PREF("sendSecureXSiteReferrer"))) {
1048 679 : rv = prefs->GetBoolPref(HTTP_PREF("sendSecureXSiteReferrer"), &cVar);
1049 679 : if (NS_SUCCEEDED(rv))
1050 679 : mSendSecureXSiteReferrer = cVar;
1051 : }
1052 :
1053 698 : if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
1054 1358 : nsXPIDLCString accept;
1055 : rv = prefs->GetCharPref(HTTP_PREF("accept.default"),
1056 679 : getter_Copies(accept));
1057 679 : if (NS_SUCCEEDED(rv))
1058 679 : SetAccept(accept);
1059 : }
1060 :
1061 698 : if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
1062 1358 : nsXPIDLCString acceptEncodings;
1063 : rv = prefs->GetCharPref(HTTP_PREF("accept-encoding"),
1064 679 : getter_Copies(acceptEncodings));
1065 679 : if (NS_SUCCEEDED(rv))
1066 679 : SetAcceptEncodings(acceptEncodings);
1067 : }
1068 :
1069 698 : if (PREF_CHANGED(HTTP_PREF("use-cache"))) {
1070 679 : rv = prefs->GetBoolPref(HTTP_PREF("use-cache"), &cVar);
1071 679 : if (NS_SUCCEEDED(rv)) {
1072 679 : mUseCache = cVar;
1073 : }
1074 : }
1075 :
1076 698 : if (PREF_CHANGED(HTTP_PREF("default-socket-type"))) {
1077 1358 : nsXPIDLCString sval;
1078 : rv = prefs->GetCharPref(HTTP_PREF("default-socket-type"),
1079 679 : getter_Copies(sval));
1080 679 : if (NS_SUCCEEDED(rv)) {
1081 679 : if (sval.IsEmpty())
1082 679 : mDefaultSocketType.Adopt(0);
1083 : else {
1084 : // verify that this socket type is actually valid
1085 : nsCOMPtr<nsISocketProviderService> sps(
1086 0 : do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID));
1087 0 : if (sps) {
1088 0 : nsCOMPtr<nsISocketProvider> sp;
1089 0 : rv = sps->GetSocketProvider(sval, getter_AddRefs(sp));
1090 0 : if (NS_SUCCEEDED(rv)) {
1091 : // OK, this looks like a valid socket provider.
1092 0 : mDefaultSocketType.Assign(sval);
1093 : }
1094 : }
1095 : }
1096 : }
1097 : }
1098 :
1099 698 : if (PREF_CHANGED(HTTP_PREF("prompt-temp-redirect"))) {
1100 679 : rv = prefs->GetBoolPref(HTTP_PREF("prompt-temp-redirect"), &cVar);
1101 679 : if (NS_SUCCEEDED(rv)) {
1102 679 : mPromptTempRedirect = cVar;
1103 : }
1104 : }
1105 :
1106 : // enable Persistent caching for HTTPS - bug#205921
1107 698 : if (PREF_CHANGED(BROWSER_PREF("disk_cache_ssl"))) {
1108 679 : cVar = false;
1109 679 : rv = prefs->GetBoolPref(BROWSER_PREF("disk_cache_ssl"), &cVar);
1110 679 : if (NS_SUCCEEDED(rv))
1111 679 : mEnablePersistentHttpsCaching = cVar;
1112 : }
1113 :
1114 698 : if (PREF_CHANGED(HTTP_PREF("phishy-userpass-length"))) {
1115 679 : rv = prefs->GetIntPref(HTTP_PREF("phishy-userpass-length"), &val);
1116 679 : if (NS_SUCCEEDED(rv))
1117 0 : mPhishyUserPassLength = (PRUint8) clamped(val, 0, 0xff);
1118 : }
1119 :
1120 698 : if (PREF_CHANGED(HTTP_PREF("spdy.enabled"))) {
1121 679 : rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled"), &cVar);
1122 679 : if (NS_SUCCEEDED(rv))
1123 679 : mEnableSpdy = cVar;
1124 : }
1125 :
1126 698 : if (PREF_CHANGED(HTTP_PREF("spdy.coalesce-hostnames"))) {
1127 679 : rv = prefs->GetBoolPref(HTTP_PREF("spdy.coalesce-hostnames"), &cVar);
1128 679 : if (NS_SUCCEEDED(rv))
1129 679 : mCoalesceSpdy = cVar;
1130 : }
1131 :
1132 698 : if (PREF_CHANGED(HTTP_PREF("spdy.use-alternate-protocol"))) {
1133 : rv = prefs->GetBoolPref(HTTP_PREF("spdy.use-alternate-protocol"),
1134 679 : &cVar);
1135 679 : if (NS_SUCCEEDED(rv))
1136 679 : mUseAlternateProtocol = cVar;
1137 : }
1138 :
1139 698 : if (PREF_CHANGED(HTTP_PREF("spdy.timeout"))) {
1140 679 : rv = prefs->GetIntPref(HTTP_PREF("spdy.timeout"), &val);
1141 679 : if (NS_SUCCEEDED(rv))
1142 679 : mSpdyTimeout = PR_SecondsToInterval(clamped(val, 1, 0xffff));
1143 : }
1144 :
1145 698 : if (PREF_CHANGED(HTTP_PREF("spdy.chunk-size"))) {
1146 679 : rv = prefs->GetIntPref(HTTP_PREF("spdy.chunk-size"), &val);
1147 679 : if (NS_SUCCEEDED(rv))
1148 679 : mSpdySendingChunkSize = (PRUint32) clamped(val, 1, 0x7fffffff);
1149 : }
1150 :
1151 : // The amount of idle seconds on a spdy connection before initiating a
1152 : // server ping. 0 will disable.
1153 698 : if (PREF_CHANGED(HTTP_PREF("spdy.ping-threshold"))) {
1154 679 : rv = prefs->GetIntPref(HTTP_PREF("spdy.ping-threshold"), &val);
1155 679 : if (NS_SUCCEEDED(rv))
1156 : mSpdyPingThreshold =
1157 679 : PR_SecondsToInterval((PRUint16) clamped(val, 0, 0x7fffffff));
1158 : }
1159 :
1160 : // The amount of seconds to wait for a spdy ping response before
1161 : // closing the session.
1162 698 : if (PREF_CHANGED(HTTP_PREF("spdy.ping-timeout"))) {
1163 679 : rv = prefs->GetIntPref(HTTP_PREF("spdy.ping-timeout"), &val);
1164 679 : if (NS_SUCCEEDED(rv))
1165 : mSpdyPingTimeout =
1166 679 : PR_SecondsToInterval((PRUint16) clamped(val, 0, 0x7fffffff));
1167 : }
1168 :
1169 : //
1170 : // INTL options
1171 : //
1172 :
1173 698 : if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) {
1174 1358 : nsCOMPtr<nsIPrefLocalizedString> pls;
1175 : prefs->GetComplexValue(INTL_ACCEPT_LANGUAGES,
1176 : NS_GET_IID(nsIPrefLocalizedString),
1177 679 : getter_AddRefs(pls));
1178 679 : if (pls) {
1179 1358 : nsXPIDLString uval;
1180 679 : pls->ToString(getter_Copies(uval));
1181 679 : if (uval)
1182 679 : SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval).get());
1183 : }
1184 : }
1185 :
1186 : //
1187 : // IDN options
1188 : //
1189 :
1190 698 : if (PREF_CHANGED(NETWORK_ENABLEIDN)) {
1191 679 : bool enableIDN = false;
1192 679 : prefs->GetBoolPref(NETWORK_ENABLEIDN, &enableIDN);
1193 : // No locking is required here since this method runs in the main
1194 : // UI thread, and so do all the methods in nsHttpChannel.cpp
1195 : // (mIDNConverter is used by nsHttpChannel)
1196 679 : if (enableIDN && !mIDNConverter) {
1197 679 : mIDNConverter = do_GetService(NS_IDNSERVICE_CONTRACTID);
1198 679 : NS_ASSERTION(mIDNConverter, "idnSDK not installed");
1199 : }
1200 0 : else if (!enableIDN && mIDNConverter)
1201 0 : mIDNConverter = nsnull;
1202 : }
1203 :
1204 : //
1205 : // Tracking options
1206 : //
1207 :
1208 698 : if (PREF_CHANGED(DONOTTRACK_HEADER_ENABLED)) {
1209 679 : cVar = false;
1210 679 : rv = prefs->GetBoolPref(DONOTTRACK_HEADER_ENABLED, &cVar);
1211 679 : if (NS_SUCCEEDED(rv)) {
1212 679 : mDoNotTrackEnabled = cVar;
1213 : }
1214 : }
1215 :
1216 : //
1217 : // Telemetry
1218 : //
1219 :
1220 698 : if (PREF_CHANGED(TELEMETRY_ENABLED)) {
1221 679 : cVar = false;
1222 679 : rv = prefs->GetBoolPref(TELEMETRY_ENABLED, &cVar);
1223 679 : if (NS_SUCCEEDED(rv)) {
1224 679 : mTelemetryEnabled = cVar;
1225 : }
1226 : }
1227 :
1228 : //
1229 : // network.allow-experiments
1230 : //
1231 :
1232 698 : if (PREF_CHANGED(ALLOW_EXPERIMENTS)) {
1233 679 : cVar = true;
1234 679 : rv = prefs->GetBoolPref(ALLOW_EXPERIMENTS, &cVar);
1235 679 : if (NS_SUCCEEDED(rv)) {
1236 679 : mAllowExperiments = cVar;
1237 : }
1238 : }
1239 :
1240 : #undef PREF_CHANGED
1241 : #undef MULTI_PREF_CHANGED
1242 698 : }
1243 :
1244 : /**
1245 : * Allocates a C string into that contains a ISO 639 language list
1246 : * notated with HTTP "q" values for output with a HTTP Accept-Language
1247 : * header. Previous q values will be stripped because the order of
1248 : * the langs imply the q value. The q values are calculated by dividing
1249 : * 1.0 amongst the number of languages present.
1250 : *
1251 : * Ex: passing: "en, ja"
1252 : * returns: "en,ja;q=0.5"
1253 : *
1254 : * passing: "en, ja, fr_CA"
1255 : * returns: "en,ja;q=0.7,fr_CA;q=0.3"
1256 : */
1257 : static nsresult
1258 679 : PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLanguages)
1259 : {
1260 679 : if (!i_AcceptLanguages)
1261 0 : return NS_OK;
1262 :
1263 : PRUint32 n, size, wrote;
1264 : double q, dec;
1265 : char *p, *p2, *token, *q_Accept, *o_Accept;
1266 : const char *comma;
1267 : PRInt32 available;
1268 :
1269 679 : o_Accept = nsCRT::strdup(i_AcceptLanguages);
1270 679 : if (!o_Accept)
1271 0 : return NS_ERROR_OUT_OF_MEMORY;
1272 6790 : for (p = o_Accept, n = size = 0; '\0' != *p; p++) {
1273 6111 : if (*p == ',') n++;
1274 6111 : size++;
1275 : }
1276 :
1277 679 : available = size + ++n * 11 + 1;
1278 1358 : q_Accept = new char[available];
1279 679 : if (!q_Accept) {
1280 0 : nsCRT::free(o_Accept);
1281 0 : return NS_ERROR_OUT_OF_MEMORY;
1282 : }
1283 679 : *q_Accept = '\0';
1284 679 : q = 1.0;
1285 679 : dec = q / (double) n;
1286 679 : n = 0;
1287 679 : p2 = q_Accept;
1288 2037 : for (token = nsCRT::strtok(o_Accept, ",", &p);
1289 : token != (char *) 0;
1290 1358 : token = nsCRT::strtok(p, ",", &p))
1291 : {
1292 1358 : token = net_FindCharNotInSet(token, HTTP_LWS);
1293 : char* trim;
1294 1358 : trim = net_FindCharInSet(token, ";" HTTP_LWS);
1295 1358 : if (trim != (char*)0) // remove "; q=..." if present
1296 1358 : *trim = '\0';
1297 :
1298 1358 : if (*token != '\0') {
1299 1358 : comma = n++ != 0 ? "," : ""; // delimiter if not first item
1300 1358 : PRUint32 u = QVAL_TO_UINT(q);
1301 1358 : if (u < 10)
1302 679 : wrote = PR_snprintf(p2, available, "%s%s;q=0.%u", comma, token, u);
1303 : else
1304 679 : wrote = PR_snprintf(p2, available, "%s%s", comma, token);
1305 1358 : q -= dec;
1306 1358 : p2 += wrote;
1307 1358 : available -= wrote;
1308 1358 : NS_ASSERTION(available > 0, "allocated string not long enough");
1309 : }
1310 : }
1311 679 : nsCRT::free(o_Accept);
1312 :
1313 679 : o_AcceptLanguages.Assign((const char *) q_Accept);
1314 679 : delete [] q_Accept;
1315 :
1316 679 : return NS_OK;
1317 : }
1318 :
1319 : nsresult
1320 679 : nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages)
1321 : {
1322 1358 : nsCAutoString buf;
1323 679 : nsresult rv = PrepareAcceptLanguages(aAcceptLanguages, buf);
1324 679 : if (NS_SUCCEEDED(rv))
1325 679 : mAcceptLanguages.Assign(buf);
1326 679 : return rv;
1327 : }
1328 :
1329 : nsresult
1330 679 : nsHttpHandler::SetAccept(const char *aAccept)
1331 : {
1332 679 : mAccept = aAccept;
1333 679 : return NS_OK;
1334 : }
1335 :
1336 : nsresult
1337 679 : nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings)
1338 : {
1339 679 : mAcceptEncodings = aAcceptEncodings;
1340 679 : return NS_OK;
1341 : }
1342 :
1343 : //-----------------------------------------------------------------------------
1344 : // nsHttpHandler::nsISupports
1345 : //-----------------------------------------------------------------------------
1346 :
1347 464964 : NS_IMPL_THREADSAFE_ISUPPORTS5(nsHttpHandler,
1348 : nsIHttpProtocolHandler,
1349 : nsIProxiedProtocolHandler,
1350 : nsIProtocolHandler,
1351 : nsIObserver,
1352 : nsISupportsWeakReference)
1353 :
1354 : //-----------------------------------------------------------------------------
1355 : // nsHttpHandler::nsIProtocolHandler
1356 : //-----------------------------------------------------------------------------
1357 :
1358 : NS_IMETHODIMP
1359 0 : nsHttpHandler::GetScheme(nsACString &aScheme)
1360 : {
1361 0 : aScheme.AssignLiteral("http");
1362 0 : return NS_OK;
1363 : }
1364 :
1365 : NS_IMETHODIMP
1366 3690 : nsHttpHandler::GetDefaultPort(PRInt32 *result)
1367 : {
1368 3690 : *result = NS_HTTP_DEFAULT_PORT;
1369 3690 : return NS_OK;
1370 : }
1371 :
1372 : NS_IMETHODIMP
1373 26451 : nsHttpHandler::GetProtocolFlags(PRUint32 *result)
1374 : {
1375 26451 : *result = NS_HTTP_PROTOCOL_FLAGS;
1376 26451 : return NS_OK;
1377 : }
1378 :
1379 : NS_IMETHODIMP
1380 34745 : nsHttpHandler::NewURI(const nsACString &aSpec,
1381 : const char *aCharset,
1382 : nsIURI *aBaseURI,
1383 : nsIURI **aURI)
1384 : {
1385 34745 : LOG(("nsHttpHandler::NewURI\n"));
1386 34745 : return ::NewURI(aSpec, aCharset, aBaseURI, NS_HTTP_DEFAULT_PORT, aURI);
1387 : }
1388 :
1389 : NS_IMETHODIMP
1390 3485 : nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
1391 : {
1392 3485 : LOG(("nsHttpHandler::NewChannel\n"));
1393 :
1394 3485 : NS_ENSURE_ARG_POINTER(uri);
1395 3485 : NS_ENSURE_ARG_POINTER(result);
1396 :
1397 3485 : bool isHttp = false, isHttps = false;
1398 :
1399 : // Verify that we have been given a valid scheme
1400 3485 : nsresult rv = uri->SchemeIs("http", &isHttp);
1401 3485 : if (NS_FAILED(rv)) return rv;
1402 3485 : if (!isHttp) {
1403 5 : rv = uri->SchemeIs("https", &isHttps);
1404 5 : if (NS_FAILED(rv)) return rv;
1405 5 : if (!isHttps) {
1406 0 : NS_WARNING("Invalid URI scheme");
1407 0 : return NS_ERROR_UNEXPECTED;
1408 : }
1409 : }
1410 :
1411 3485 : return NewProxiedChannel(uri, nsnull, result);
1412 : }
1413 :
1414 : NS_IMETHODIMP
1415 0 : nsHttpHandler::AllowPort(PRInt32 port, const char *scheme, bool *_retval)
1416 : {
1417 : // don't override anything.
1418 0 : *_retval = false;
1419 0 : return NS_OK;
1420 : }
1421 :
1422 : //-----------------------------------------------------------------------------
1423 : // nsHttpHandler::nsIProxiedProtocolHandler
1424 : //-----------------------------------------------------------------------------
1425 :
1426 : NS_IMETHODIMP
1427 3514 : nsHttpHandler::NewProxiedChannel(nsIURI *uri,
1428 : nsIProxyInfo* givenProxyInfo,
1429 : nsIChannel **result)
1430 : {
1431 7028 : nsRefPtr<HttpBaseChannel> httpChannel;
1432 :
1433 3514 : LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
1434 : givenProxyInfo));
1435 :
1436 7028 : nsCOMPtr<nsProxyInfo> proxyInfo;
1437 3514 : if (givenProxyInfo) {
1438 24 : proxyInfo = do_QueryInterface(givenProxyInfo);
1439 24 : NS_ENSURE_ARG(proxyInfo);
1440 : }
1441 :
1442 : bool https;
1443 3514 : nsresult rv = uri->SchemeIs("https", &https);
1444 3514 : if (NS_FAILED(rv))
1445 0 : return rv;
1446 :
1447 3514 : if (IsNeckoChild()) {
1448 0 : httpChannel = new HttpChannelChild();
1449 : } else {
1450 3514 : httpChannel = new nsHttpChannel();
1451 : }
1452 :
1453 : // select proxy caps if using a non-transparent proxy. SSL tunneling
1454 : // should not use proxy settings.
1455 : PRInt8 caps;
1456 3514 : if (proxyInfo && !nsCRT::strcmp(proxyInfo->Type(), "http") && !https)
1457 14 : caps = mProxyCapabilities;
1458 : else
1459 3500 : caps = mCapabilities;
1460 :
1461 3514 : if (https) {
1462 : // enable pipelining over SSL if requested
1463 5 : if (mPipeliningOverSSL)
1464 0 : caps |= NS_HTTP_ALLOW_PIPELINING;
1465 :
1466 5 : if (!IsNeckoChild()) {
1467 : // HACK: make sure PSM gets initialized on the main thread.
1468 5 : net_EnsurePSMInit();
1469 : }
1470 : }
1471 :
1472 3514 : rv = httpChannel->Init(uri, caps, proxyInfo);
1473 3514 : if (NS_FAILED(rv))
1474 0 : return rv;
1475 :
1476 3514 : httpChannel.forget(result);
1477 3514 : return NS_OK;
1478 : }
1479 :
1480 : //-----------------------------------------------------------------------------
1481 : // nsHttpHandler::nsIHttpProtocolHandler
1482 : //-----------------------------------------------------------------------------
1483 :
1484 : NS_IMETHODIMP
1485 47 : nsHttpHandler::GetUserAgent(nsACString &value)
1486 : {
1487 47 : value = UserAgent();
1488 47 : return NS_OK;
1489 : }
1490 :
1491 : NS_IMETHODIMP
1492 0 : nsHttpHandler::GetAppName(nsACString &value)
1493 : {
1494 0 : value = mLegacyAppName;
1495 0 : return NS_OK;
1496 : }
1497 :
1498 : NS_IMETHODIMP
1499 0 : nsHttpHandler::GetAppVersion(nsACString &value)
1500 : {
1501 0 : value = mLegacyAppVersion;
1502 0 : return NS_OK;
1503 : }
1504 :
1505 : NS_IMETHODIMP
1506 0 : nsHttpHandler::GetProduct(nsACString &value)
1507 : {
1508 0 : value = mProduct;
1509 0 : return NS_OK;
1510 : }
1511 :
1512 : NS_IMETHODIMP
1513 0 : nsHttpHandler::GetProductSub(nsACString &value)
1514 : {
1515 0 : value = mProductSub;
1516 0 : return NS_OK;
1517 : }
1518 :
1519 : NS_IMETHODIMP
1520 1 : nsHttpHandler::GetPlatform(nsACString &value)
1521 : {
1522 1 : value = mPlatform;
1523 1 : return NS_OK;
1524 : }
1525 :
1526 : NS_IMETHODIMP
1527 75 : nsHttpHandler::GetOscpu(nsACString &value)
1528 : {
1529 75 : value = mOscpu;
1530 75 : return NS_OK;
1531 : }
1532 :
1533 : NS_IMETHODIMP
1534 0 : nsHttpHandler::GetMisc(nsACString &value)
1535 : {
1536 0 : value = mMisc;
1537 0 : return NS_OK;
1538 : }
1539 :
1540 : //-----------------------------------------------------------------------------
1541 : // nsHttpHandler::nsIObserver
1542 : //-----------------------------------------------------------------------------
1543 :
1544 : NS_IMETHODIMP
1545 1478 : nsHttpHandler::Observe(nsISupports *subject,
1546 : const char *topic,
1547 : const PRUnichar *data)
1548 : {
1549 1478 : LOG(("nsHttpHandler::Observe [topic=\"%s\"]\n", topic));
1550 :
1551 1478 : if (strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
1552 38 : nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
1553 19 : if (prefBranch)
1554 19 : PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
1555 : }
1556 2386 : else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
1557 927 : strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
1558 :
1559 : // clear cache of all authentication credentials.
1560 1211 : mAuthCache.ClearAll();
1561 :
1562 : // ensure connection manager is shutdown
1563 1211 : if (mConnMgr)
1564 1211 : mConnMgr->Shutdown();
1565 :
1566 : // need to reset the session start time since cache validation may
1567 : // depend on this value.
1568 1211 : mSessionStartTime = NowInSeconds();
1569 : }
1570 248 : else if (strcmp(topic, "profile-change-net-restore") == 0) {
1571 : // initialize connection manager
1572 0 : InitConnectionMgr();
1573 : }
1574 248 : else if (strcmp(topic, "net:clear-active-logins") == 0) {
1575 1 : mAuthCache.ClearAll();
1576 : }
1577 247 : else if (strcmp(topic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
1578 123 : if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(data))
1579 56 : mInPrivateBrowsingMode = PRIVATE_BROWSING_ON;
1580 67 : else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(data))
1581 67 : mInPrivateBrowsingMode = PRIVATE_BROWSING_OFF;
1582 123 : if (mConnMgr)
1583 123 : mConnMgr->ClosePersistentConnections();
1584 : }
1585 124 : else if (strcmp(topic, "net:prune-dead-connections") == 0) {
1586 124 : if (mConnMgr) {
1587 124 : mConnMgr->PruneDeadConnections();
1588 : }
1589 : }
1590 :
1591 1478 : return NS_OK;
1592 : }
1593 :
1594 : //-----------------------------------------------------------------------------
1595 : // nsHttpsHandler implementation
1596 : //-----------------------------------------------------------------------------
1597 :
1598 3013 : NS_IMPL_THREADSAFE_ISUPPORTS4(nsHttpsHandler,
1599 : nsIHttpProtocolHandler,
1600 : nsIProxiedProtocolHandler,
1601 : nsIProtocolHandler,
1602 : nsISupportsWeakReference)
1603 :
1604 : nsresult
1605 39 : nsHttpsHandler::Init()
1606 : {
1607 : nsCOMPtr<nsIProtocolHandler> httpHandler(
1608 78 : do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http"));
1609 39 : NS_ASSERTION(httpHandler.get() != nsnull, "no http handler?");
1610 39 : return NS_OK;
1611 : }
1612 :
1613 : NS_IMETHODIMP
1614 0 : nsHttpsHandler::GetScheme(nsACString &aScheme)
1615 : {
1616 0 : aScheme.AssignLiteral("https");
1617 0 : return NS_OK;
1618 : }
1619 :
1620 : NS_IMETHODIMP
1621 26 : nsHttpsHandler::GetDefaultPort(PRInt32 *aPort)
1622 : {
1623 26 : *aPort = NS_HTTPS_DEFAULT_PORT;
1624 26 : return NS_OK;
1625 : }
1626 :
1627 : NS_IMETHODIMP
1628 14 : nsHttpsHandler::GetProtocolFlags(PRUint32 *aProtocolFlags)
1629 : {
1630 14 : *aProtocolFlags = NS_HTTP_PROTOCOL_FLAGS;
1631 14 : return NS_OK;
1632 : }
1633 :
1634 : NS_IMETHODIMP
1635 319 : nsHttpsHandler::NewURI(const nsACString &aSpec,
1636 : const char *aOriginCharset,
1637 : nsIURI *aBaseURI,
1638 : nsIURI **_retval)
1639 : {
1640 319 : return ::NewURI(aSpec, aOriginCharset, aBaseURI, NS_HTTPS_DEFAULT_PORT, _retval);
1641 : }
1642 :
1643 : NS_IMETHODIMP
1644 5 : nsHttpsHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
1645 : {
1646 5 : NS_ABORT_IF_FALSE(gHttpHandler, "Should have a HTTP handler by now.");
1647 5 : if (!gHttpHandler)
1648 0 : return NS_ERROR_UNEXPECTED;
1649 5 : return gHttpHandler->NewChannel(aURI, _retval);
1650 : }
1651 :
1652 : NS_IMETHODIMP
1653 0 : nsHttpsHandler::AllowPort(PRInt32 aPort, const char *aScheme, bool *_retval)
1654 : {
1655 : // don't override anything.
1656 0 : *_retval = false;
1657 0 : return NS_OK;
1658 : }
|