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 34303 : NewURI(const nsACString &aSpec,
144 : const char *aCharset,
145 : nsIURI *aBaseURI,
146 : PRInt32 aDefaultPort,
147 : nsIURI **aURI)
148 : {
149 34303 : nsStandardURL *url = new nsStandardURL();
150 34303 : if (!url)
151 0 : return NS_ERROR_OUT_OF_MEMORY;
152 34303 : NS_ADDREF(url);
153 :
154 : nsresult rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY,
155 34303 : aDefaultPort, aSpec, aCharset, aBaseURI);
156 34303 : if (NS_FAILED(rv)) {
157 36 : NS_RELEASE(url);
158 36 : return rv;
159 : }
160 :
161 34267 : *aURI = url; // no QI needed
162 34267 : return NS_OK;
163 : }
164 :
165 : //-----------------------------------------------------------------------------
166 : // nsHttpHandler <public>
167 : //-----------------------------------------------------------------------------
168 :
169 : nsHttpHandler *gHttpHandler = nsnull;
170 :
171 673 : 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 673 : , mIdleTimeout(PR_SecondsToInterval(10))
180 673 : , 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 673 : , 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 673 : , mSpdyPingThreshold(PR_SecondsToInterval(44))
212 3365 : , mSpdyPingTimeout(PR_SecondsToInterval(8))
213 : {
214 : #if defined(PR_LOGGING)
215 673 : gHttpLog = PR_NewLogModule("nsHttp");
216 : #endif
217 :
218 673 : LOG(("Creating nsHttpHandler [this=%x].\n", this));
219 :
220 673 : NS_ASSERTION(!gHttpHandler, "HTTP handler already created!");
221 673 : gHttpHandler = this;
222 673 : }
223 :
224 2013 : nsHttpHandler::~nsHttpHandler()
225 : {
226 671 : LOG(("Deleting nsHttpHandler [this=%x]\n", this));
227 :
228 : // make sure the connection manager is shutdown
229 671 : if (mConnMgr) {
230 671 : mConnMgr->Shutdown();
231 671 : 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 671 : nsHttp::DestroyAtomTable();
238 :
239 671 : gHttpHandler = nsnull;
240 2684 : }
241 :
242 : nsresult
243 673 : nsHttpHandler::Init()
244 : {
245 : NS_TIME_FUNCTION;
246 :
247 : nsresult rv;
248 :
249 673 : LOG(("nsHttpHandler::Init\n"));
250 :
251 673 : rv = nsHttp::CreateAtomTable();
252 673 : if (NS_FAILED(rv))
253 0 : return rv;
254 :
255 673 : mIOService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
256 673 : if (NS_FAILED(rv)) {
257 0 : NS_WARNING("unable to continue without io service");
258 0 : return rv;
259 : }
260 :
261 673 : if (IsNeckoChild())
262 0 : NeckoChild::InitNeckoChild();
263 :
264 673 : InitUserAgentComponents();
265 :
266 : // monitor some preference changes
267 1346 : nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
268 673 : if (prefBranch) {
269 673 : prefBranch->AddObserver(HTTP_PREF_PREFIX, this, true);
270 673 : prefBranch->AddObserver(UA_PREF_PREFIX, this, true);
271 673 : prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, true);
272 673 : prefBranch->AddObserver(NETWORK_ENABLEIDN, this, true);
273 673 : prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, true);
274 673 : prefBranch->AddObserver(DONOTTRACK_HEADER_ENABLED, this, true);
275 673 : prefBranch->AddObserver(TELEMETRY_ENABLED, this, true);
276 :
277 673 : PrefsChanged(prefBranch, nsnull);
278 : }
279 :
280 673 : mMisc.AssignLiteral("rv:" MOZILLA_UAVERSION);
281 :
282 : nsCOMPtr<nsIXULAppInfo> appInfo =
283 1346 : do_GetService("@mozilla.org/xre/app-info;1");
284 :
285 673 : mAppName.AssignLiteral(MOZ_APP_UA_NAME);
286 673 : if (mAppName.Length() == 0 && appInfo) {
287 299 : appInfo->GetName(mAppName);
288 299 : appInfo->GetVersion(mAppVersion);
289 299 : mAppName.StripChars(" ()<>@,;:\\\"/[]?={}");
290 : } else {
291 374 : mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION);
292 : }
293 :
294 : #if DEBUG
295 : // dump user agent prefs
296 673 : LOG(("> legacy-app-name = %s\n", mLegacyAppName.get()));
297 673 : LOG(("> legacy-app-version = %s\n", mLegacyAppVersion.get()));
298 673 : LOG(("> platform = %s\n", mPlatform.get()));
299 673 : LOG(("> oscpu = %s\n", mOscpu.get()));
300 673 : LOG(("> misc = %s\n", mMisc.get()));
301 673 : LOG(("> product = %s\n", mProduct.get()));
302 673 : LOG(("> product-sub = %s\n", mProductSub.get()));
303 673 : LOG(("> app-name = %s\n", mAppName.get()));
304 673 : LOG(("> app-version = %s\n", mAppVersion.get()));
305 673 : LOG(("> compat-firefox = %s\n", mCompatFirefox.get()));
306 673 : LOG(("> user-agent = %s\n", UserAgent().get()));
307 : #endif
308 :
309 673 : mSessionStartTime = NowInSeconds();
310 :
311 673 : rv = mAuthCache.Init();
312 673 : if (NS_FAILED(rv)) return rv;
313 :
314 673 : rv = InitConnectionMgr();
315 673 : if (NS_FAILED(rv)) return rv;
316 :
317 : #ifdef ANDROID
318 : mProductSub.AssignLiteral(MOZILLA_UAVERSION);
319 : #else
320 673 : mProductSub.AssignLiteral(MOZ_UA_BUILDID);
321 : #endif
322 673 : if (mProductSub.IsEmpty() && appInfo)
323 299 : appInfo->GetPlatformBuildID(mProductSub);
324 673 : 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 673 : NS_HTTP_STARTUP_TOPIC);
332 :
333 673 : mObserverService = mozilla::services::GetObserverService();
334 673 : if (mObserverService) {
335 673 : mObserverService->AddObserver(this, "profile-change-net-teardown", true);
336 673 : mObserverService->AddObserver(this, "profile-change-net-restore", true);
337 673 : mObserverService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
338 673 : mObserverService->AddObserver(this, "net:clear-active-logins", true);
339 673 : mObserverService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true);
340 673 : mObserverService->AddObserver(this, "net:prune-dead-connections", true);
341 : }
342 :
343 673 : return NS_OK;
344 : }
345 :
346 : nsresult
347 673 : nsHttpHandler::InitConnectionMgr()
348 : {
349 : NS_TIME_FUNCTION;
350 :
351 : nsresult rv;
352 :
353 673 : if (!mConnMgr) {
354 673 : mConnMgr = new nsHttpConnectionMgr();
355 673 : if (!mConnMgr)
356 0 : return NS_ERROR_OUT_OF_MEMORY;
357 673 : NS_ADDREF(mConnMgr);
358 : }
359 :
360 : rv = mConnMgr->Init(mMaxConnections,
361 : mMaxConnectionsPerServer,
362 : mMaxConnectionsPerServer,
363 : mMaxPersistentConnectionsPerServer,
364 : mMaxPersistentConnectionsPerProxy,
365 : mMaxRequestDelay,
366 673 : mMaxPipelinedRequests);
367 673 : return rv;
368 : }
369 :
370 : nsresult
371 3529 : nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
372 : PRUint8 caps,
373 : bool useProxy)
374 : {
375 : nsresult rv;
376 :
377 : // Add the "User-Agent" header
378 3529 : rv = request->SetHeader(nsHttp::User_Agent, UserAgent());
379 3529 : if (NS_FAILED(rv)) return rv;
380 :
381 : // MIME based content negotiation lives!
382 : // Add the "Accept" header
383 3529 : rv = request->SetHeader(nsHttp::Accept, mAccept);
384 3529 : if (NS_FAILED(rv)) return rv;
385 :
386 : // Add the "Accept-Language" header
387 3529 : if (!mAcceptLanguages.IsEmpty()) {
388 : // Add the "Accept-Language" header
389 3529 : rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages);
390 3529 : if (NS_FAILED(rv)) return rv;
391 : }
392 :
393 : // Add the "Accept-Encoding" header
394 3529 : rv = request->SetHeader(nsHttp::Accept_Encoding, mAcceptEncodings);
395 3529 : 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 7058 : NS_NAMED_LITERAL_CSTRING(close, "close");
408 7058 : NS_NAMED_LITERAL_CSTRING(keepAlive, "keep-alive");
409 :
410 3529 : const nsACString *connectionType = &close;
411 3529 : if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
412 3529 : 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 3529 : 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 3529 : : nsHttp::Connection;
427 3529 : 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 907 : nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
510 : {
511 907 : if (!mStreamConvSvc) {
512 : nsresult rv;
513 71 : mStreamConvSvc = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
514 71 : if (NS_FAILED(rv)) return rv;
515 : }
516 907 : *result = mStreamConvSvc;
517 907 : NS_ADDREF(*result);
518 907 : return NS_OK;
519 : }
520 :
521 : nsIStrictTransportSecurityService*
522 5064 : nsHttpHandler::GetSTSService()
523 : {
524 5064 : if (!mSTSService)
525 265 : mSTSService = do_GetService(NS_STSSERVICE_CONTRACTID);
526 5064 : return mSTSService;
527 : }
528 :
529 : nsICookieService *
530 3520 : nsHttpHandler::GetCookieService()
531 : {
532 3520 : if (!mCookieService)
533 265 : mCookieService = do_GetService(NS_COOKIESERVICE_CONTRACTID);
534 3520 : 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 6579 : nsHttpHandler::NotifyObservers(nsIHttpChannel *chan, const char *event)
568 : {
569 6579 : LOG(("nsHttpHandler::NotifyObservers [chan=%x event=\"%s\"]\n", chan, event));
570 6579 : if (mObserverService)
571 6579 : mObserverService->NotifyObservers(chan, event, nsnull);
572 6579 : }
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 3529 : nsHttpHandler::GenerateHostPort(const nsCString& host, PRInt32 port,
587 : nsCString& hostLine)
588 : {
589 3529 : return NS_GenerateHostPort(host, port, hostLine);
590 : }
591 :
592 : //-----------------------------------------------------------------------------
593 : // nsHttpHandler <private>
594 : //-----------------------------------------------------------------------------
595 :
596 : const nsAFlatCString &
597 3576 : nsHttpHandler::UserAgent()
598 : {
599 3576 : if (mUserAgentOverride) {
600 8 : LOG(("using general.useragent.override : %s\n", mUserAgentOverride.get()));
601 8 : return mUserAgentOverride;
602 : }
603 :
604 3568 : if (mUserAgentIsDirty) {
605 286 : BuildUserAgent();
606 286 : mUserAgentIsDirty = false;
607 : }
608 :
609 3568 : return mUserAgent;
610 : }
611 :
612 : void
613 286 : nsHttpHandler::BuildUserAgent()
614 : {
615 286 : LOG(("nsHttpHandler::BuildUserAgent\n"));
616 :
617 286 : 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 286 : mUserAgent.SetCapacity(mLegacyAppName.Length() +
626 286 : mLegacyAppVersion.Length() +
627 : #ifndef UA_SPARE_PLATFORM
628 286 : mPlatform.Length() +
629 : #endif
630 286 : mOscpu.Length() +
631 286 : mMisc.Length() +
632 286 : mProduct.Length() +
633 286 : mProductSub.Length() +
634 286 : mAppName.Length() +
635 286 : mAppVersion.Length() +
636 286 : mCompatFirefox.Length() +
637 286 : mCompatDevice.Length() +
638 2860 : 13);
639 :
640 : // Application portion
641 286 : mUserAgent.Assign(mLegacyAppName);
642 286 : mUserAgent += '/';
643 286 : mUserAgent += mLegacyAppVersion;
644 286 : mUserAgent += ' ';
645 :
646 : // Application comment
647 286 : mUserAgent += '(';
648 : #ifndef UA_SPARE_PLATFORM
649 286 : mUserAgent += mPlatform;
650 286 : mUserAgent.AppendLiteral("; ");
651 : #endif
652 : #ifdef ANDROID
653 : if (!mCompatDevice.IsEmpty()) {
654 : mUserAgent += mCompatDevice;
655 : mUserAgent.AppendLiteral("; ");
656 : }
657 : #else
658 286 : mUserAgent += mOscpu;
659 286 : mUserAgent.AppendLiteral("; ");
660 : #endif
661 286 : mUserAgent += mMisc;
662 286 : mUserAgent += ')';
663 :
664 : // Product portion
665 286 : mUserAgent += ' ';
666 286 : mUserAgent += mProduct;
667 286 : mUserAgent += '/';
668 286 : mUserAgent += mProductSub;
669 :
670 : // "Firefox/x.y.z" compatibility token
671 286 : if (!mCompatFirefox.IsEmpty()) {
672 0 : mUserAgent += ' ';
673 0 : mUserAgent += mCompatFirefox;
674 : }
675 :
676 : // App portion
677 286 : mUserAgent += ' ';
678 286 : mUserAgent += mAppName;
679 286 : mUserAgent += '/';
680 286 : mUserAgent += mAppVersion;
681 286 : }
682 :
683 : #ifdef XP_WIN
684 : #define WNT_BASE "Windows NT %ld.%ld"
685 : #define W64_PREFIX "; Win64"
686 : #endif
687 :
688 : void
689 673 : 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 673 : );
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 673 : int ret = uname(&name);
776 673 : if (ret >= 0) {
777 1346 : nsCAutoString buf;
778 673 : buf = (char*)name.sysname;
779 :
780 673 : 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 673 : 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 673 : buf += (char*)name.machine;
801 : #endif
802 : }
803 :
804 673 : mOscpu.Assign(buf);
805 : }
806 : #endif
807 :
808 673 : mUserAgentIsDirty = true;
809 673 : }
810 :
811 : PRUint32
812 3663 : nsHttpHandler::MaxSocketCount()
813 : {
814 : PR_CallOnce(&nsSocketTransportService::gMaxCountInitOnce,
815 3663 : 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 3663 : PRUint32 maxCount = nsSocketTransportService::gMaxCount;
821 3663 : if (maxCount <= 8)
822 0 : maxCount = 1;
823 : else
824 3663 : maxCount -= 8;
825 :
826 3663 : return maxCount;
827 : }
828 :
829 : void
830 692 : nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
831 : {
832 692 : nsresult rv = NS_OK;
833 : PRInt32 val;
834 :
835 692 : 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 692 : bool cVar = false;
846 :
847 692 : if (PREF_CHANGED(UA_PREF("compatMode.firefox"))) {
848 673 : rv = prefs->GetBoolPref(UA_PREF("compatMode.firefox"), &cVar);
849 673 : if (NS_SUCCEEDED(rv) && cVar) {
850 0 : mCompatFirefox.AssignLiteral("Firefox/" MOZ_UA_FIREFOX_VERSION);
851 : } else {
852 673 : mCompatFirefox.Truncate();
853 : }
854 673 : mUserAgentIsDirty = true;
855 : }
856 :
857 : // general.useragent.override
858 692 : if (PREF_CHANGED(UA_PREF("override"))) {
859 : prefs->GetCharPref(UA_PREF("override"),
860 676 : getter_Copies(mUserAgentOverride));
861 676 : mUserAgentIsDirty = true;
862 : }
863 :
864 : //
865 : // HTTP options
866 : //
867 :
868 692 : if (PREF_CHANGED(HTTP_PREF("keep-alive.timeout"))) {
869 673 : rv = prefs->GetIntPref(HTTP_PREF("keep-alive.timeout"), &val);
870 673 : if (NS_SUCCEEDED(rv))
871 673 : mIdleTimeout = PR_SecondsToInterval(clamped(val, 1, 0xffff));
872 : }
873 :
874 692 : if (PREF_CHANGED(HTTP_PREF("request.max-attempts"))) {
875 673 : rv = prefs->GetIntPref(HTTP_PREF("request.max-attempts"), &val);
876 673 : if (NS_SUCCEEDED(rv))
877 0 : mMaxRequestAttempts = (PRUint16) clamped(val, 1, 0xffff);
878 : }
879 :
880 692 : if (PREF_CHANGED(HTTP_PREF("request.max-start-delay"))) {
881 673 : rv = prefs->GetIntPref(HTTP_PREF("request.max-start-delay"), &val);
882 673 : if (NS_SUCCEEDED(rv)) {
883 673 : mMaxRequestDelay = (PRUint16) clamped(val, 0, 0xffff);
884 673 : if (mConnMgr)
885 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_REQUEST_DELAY,
886 0 : mMaxRequestDelay);
887 : }
888 : }
889 :
890 692 : if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
891 673 : rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
892 673 : if (NS_SUCCEEDED(rv)) {
893 :
894 : mMaxConnections = (PRUint16) clamped((PRUint32)val,
895 673 : (PRUint32)1, MaxSocketCount());
896 :
897 673 : if (mConnMgr)
898 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
899 0 : mMaxConnections);
900 : }
901 : }
902 :
903 692 : if (PREF_CHANGED(HTTP_PREF("max-connections-per-server"))) {
904 673 : rv = prefs->GetIntPref(HTTP_PREF("max-connections-per-server"), &val);
905 673 : if (NS_SUCCEEDED(rv)) {
906 673 : mMaxConnectionsPerServer = (PRUint8) clamped(val, 1, 0xff);
907 673 : 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 692 : if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-server"))) {
917 673 : rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-server"), &val);
918 673 : if (NS_SUCCEEDED(rv)) {
919 673 : mMaxPersistentConnectionsPerServer = (PRUint8) clamped(val, 1, 0xff);
920 673 : if (mConnMgr)
921 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_HOST,
922 0 : mMaxPersistentConnectionsPerServer);
923 : }
924 : }
925 :
926 692 : if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-proxy"))) {
927 673 : rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-proxy"), &val);
928 673 : if (NS_SUCCEEDED(rv)) {
929 673 : mMaxPersistentConnectionsPerProxy = (PRUint8) clamped(val, 1, 0xff);
930 673 : if (mConnMgr)
931 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
932 0 : mMaxPersistentConnectionsPerProxy);
933 : }
934 : }
935 :
936 692 : if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
937 673 : rv = prefs->GetIntPref(HTTP_PREF("sendRefererHeader"), &val);
938 673 : if (NS_SUCCEEDED(rv))
939 673 : mReferrerLevel = (PRUint8) clamped(val, 0, 0xff);
940 : }
941 :
942 692 : if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
943 673 : rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
944 673 : if (NS_SUCCEEDED(rv))
945 673 : mRedirectionLimit = (PRUint8) clamped(val, 0, 0xff);
946 : }
947 :
948 692 : if (PREF_CHANGED(HTTP_PREF("connection-retry-timeout"))) {
949 673 : rv = prefs->GetIntPref(HTTP_PREF("connection-retry-timeout"), &val);
950 673 : if (NS_SUCCEEDED(rv))
951 673 : mIdleSynTimeout = (PRUint16) clamped(val, 0, 3000);
952 : }
953 :
954 692 : if (PREF_CHANGED(HTTP_PREF("fast-fallback-to-IPv4"))) {
955 673 : rv = prefs->GetBoolPref(HTTP_PREF("fast-fallback-to-IPv4"), &cVar);
956 673 : if (NS_SUCCEEDED(rv))
957 673 : mFastFallbackToIPv4 = cVar;
958 : }
959 :
960 692 : if (PREF_CHANGED(HTTP_PREF("version"))) {
961 1346 : nsXPIDLCString httpVersion;
962 673 : prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));
963 673 : if (httpVersion) {
964 673 : if (!PL_strcmp(httpVersion, "1.1"))
965 673 : 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 692 : if (PREF_CHANGED(HTTP_PREF("proxy.version"))) {
974 1346 : nsXPIDLCString httpVersion;
975 673 : prefs->GetCharPref(HTTP_PREF("proxy.version"), getter_Copies(httpVersion));
976 673 : if (httpVersion) {
977 673 : if (!PL_strcmp(httpVersion, "1.1"))
978 673 : 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 692 : if (PREF_CHANGED(HTTP_PREF("keep-alive"))) {
986 673 : rv = prefs->GetBoolPref(HTTP_PREF("keep-alive"), &cVar);
987 673 : if (NS_SUCCEEDED(rv)) {
988 673 : if (cVar)
989 673 : mCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
990 : else
991 0 : mCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
992 : }
993 : }
994 :
995 692 : if (PREF_CHANGED(HTTP_PREF("proxy.keep-alive"))) {
996 673 : rv = prefs->GetBoolPref(HTTP_PREF("proxy.keep-alive"), &cVar);
997 673 : if (NS_SUCCEEDED(rv)) {
998 673 : if (cVar)
999 673 : mProxyCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
1000 : else
1001 0 : mProxyCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
1002 : }
1003 : }
1004 :
1005 692 : if (PREF_CHANGED(HTTP_PREF("pipelining"))) {
1006 673 : rv = prefs->GetBoolPref(HTTP_PREF("pipelining"), &cVar);
1007 673 : if (NS_SUCCEEDED(rv)) {
1008 673 : if (cVar)
1009 0 : mCapabilities |= NS_HTTP_ALLOW_PIPELINING;
1010 : else
1011 673 : mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
1012 : }
1013 : }
1014 :
1015 692 : if (PREF_CHANGED(HTTP_PREF("pipelining.maxrequests"))) {
1016 673 : rv = prefs->GetIntPref(HTTP_PREF("pipelining.maxrequests"), &val);
1017 673 : if (NS_SUCCEEDED(rv)) {
1018 673 : mMaxPipelinedRequests = clamped(val, 1, NS_HTTP_MAX_PIPELINED_REQUESTS);
1019 673 : if (mConnMgr)
1020 : mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PIPELINED_REQUESTS,
1021 0 : mMaxPipelinedRequests);
1022 : }
1023 : }
1024 :
1025 692 : if (PREF_CHANGED(HTTP_PREF("pipelining.ssl"))) {
1026 673 : rv = prefs->GetBoolPref(HTTP_PREF("pipelining.ssl"), &cVar);
1027 673 : if (NS_SUCCEEDED(rv))
1028 673 : mPipeliningOverSSL = cVar;
1029 : }
1030 :
1031 692 : if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
1032 673 : rv = prefs->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar);
1033 673 : if (NS_SUCCEEDED(rv)) {
1034 673 : if (cVar)
1035 0 : mProxyCapabilities |= NS_HTTP_ALLOW_PIPELINING;
1036 : else
1037 673 : mProxyCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
1038 : }
1039 : }
1040 :
1041 692 : if (PREF_CHANGED(HTTP_PREF("qos"))) {
1042 673 : rv = prefs->GetIntPref(HTTP_PREF("qos"), &val);
1043 673 : if (NS_SUCCEEDED(rv))
1044 673 : mQoSBits = (PRUint8) clamped(val, 0, 0xff);
1045 : }
1046 :
1047 692 : if (PREF_CHANGED(HTTP_PREF("sendSecureXSiteReferrer"))) {
1048 673 : rv = prefs->GetBoolPref(HTTP_PREF("sendSecureXSiteReferrer"), &cVar);
1049 673 : if (NS_SUCCEEDED(rv))
1050 673 : mSendSecureXSiteReferrer = cVar;
1051 : }
1052 :
1053 692 : if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
1054 1346 : nsXPIDLCString accept;
1055 : rv = prefs->GetCharPref(HTTP_PREF("accept.default"),
1056 673 : getter_Copies(accept));
1057 673 : if (NS_SUCCEEDED(rv))
1058 673 : SetAccept(accept);
1059 : }
1060 :
1061 692 : if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
1062 1346 : nsXPIDLCString acceptEncodings;
1063 : rv = prefs->GetCharPref(HTTP_PREF("accept-encoding"),
1064 673 : getter_Copies(acceptEncodings));
1065 673 : if (NS_SUCCEEDED(rv))
1066 673 : SetAcceptEncodings(acceptEncodings);
1067 : }
1068 :
1069 692 : if (PREF_CHANGED(HTTP_PREF("use-cache"))) {
1070 673 : rv = prefs->GetBoolPref(HTTP_PREF("use-cache"), &cVar);
1071 673 : if (NS_SUCCEEDED(rv)) {
1072 673 : mUseCache = cVar;
1073 : }
1074 : }
1075 :
1076 692 : if (PREF_CHANGED(HTTP_PREF("default-socket-type"))) {
1077 1346 : nsXPIDLCString sval;
1078 : rv = prefs->GetCharPref(HTTP_PREF("default-socket-type"),
1079 673 : getter_Copies(sval));
1080 673 : if (NS_SUCCEEDED(rv)) {
1081 673 : if (sval.IsEmpty())
1082 673 : 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 692 : if (PREF_CHANGED(HTTP_PREF("prompt-temp-redirect"))) {
1100 673 : rv = prefs->GetBoolPref(HTTP_PREF("prompt-temp-redirect"), &cVar);
1101 673 : if (NS_SUCCEEDED(rv)) {
1102 673 : mPromptTempRedirect = cVar;
1103 : }
1104 : }
1105 :
1106 : // enable Persistent caching for HTTPS - bug#205921
1107 692 : if (PREF_CHANGED(BROWSER_PREF("disk_cache_ssl"))) {
1108 673 : cVar = false;
1109 673 : rv = prefs->GetBoolPref(BROWSER_PREF("disk_cache_ssl"), &cVar);
1110 673 : if (NS_SUCCEEDED(rv))
1111 673 : mEnablePersistentHttpsCaching = cVar;
1112 : }
1113 :
1114 692 : if (PREF_CHANGED(HTTP_PREF("phishy-userpass-length"))) {
1115 673 : rv = prefs->GetIntPref(HTTP_PREF("phishy-userpass-length"), &val);
1116 673 : if (NS_SUCCEEDED(rv))
1117 0 : mPhishyUserPassLength = (PRUint8) clamped(val, 0, 0xff);
1118 : }
1119 :
1120 692 : if (PREF_CHANGED(HTTP_PREF("spdy.enabled"))) {
1121 673 : rv = prefs->GetBoolPref(HTTP_PREF("spdy.enabled"), &cVar);
1122 673 : if (NS_SUCCEEDED(rv))
1123 673 : mEnableSpdy = cVar;
1124 : }
1125 :
1126 692 : if (PREF_CHANGED(HTTP_PREF("spdy.coalesce-hostnames"))) {
1127 673 : rv = prefs->GetBoolPref(HTTP_PREF("spdy.coalesce-hostnames"), &cVar);
1128 673 : if (NS_SUCCEEDED(rv))
1129 673 : mCoalesceSpdy = cVar;
1130 : }
1131 :
1132 692 : if (PREF_CHANGED(HTTP_PREF("spdy.use-alternate-protocol"))) {
1133 : rv = prefs->GetBoolPref(HTTP_PREF("spdy.use-alternate-protocol"),
1134 673 : &cVar);
1135 673 : if (NS_SUCCEEDED(rv))
1136 673 : mUseAlternateProtocol = cVar;
1137 : }
1138 :
1139 692 : if (PREF_CHANGED(HTTP_PREF("spdy.timeout"))) {
1140 673 : rv = prefs->GetIntPref(HTTP_PREF("spdy.timeout"), &val);
1141 673 : if (NS_SUCCEEDED(rv))
1142 673 : mSpdyTimeout = PR_SecondsToInterval(clamped(val, 1, 0xffff));
1143 : }
1144 :
1145 692 : if (PREF_CHANGED(HTTP_PREF("spdy.chunk-size"))) {
1146 673 : rv = prefs->GetIntPref(HTTP_PREF("spdy.chunk-size"), &val);
1147 673 : if (NS_SUCCEEDED(rv))
1148 673 : 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 692 : if (PREF_CHANGED(HTTP_PREF("spdy.ping-threshold"))) {
1154 673 : rv = prefs->GetIntPref(HTTP_PREF("spdy.ping-threshold"), &val);
1155 673 : if (NS_SUCCEEDED(rv))
1156 : mSpdyPingThreshold =
1157 673 : 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 692 : if (PREF_CHANGED(HTTP_PREF("spdy.ping-timeout"))) {
1163 673 : rv = prefs->GetIntPref(HTTP_PREF("spdy.ping-timeout"), &val);
1164 673 : if (NS_SUCCEEDED(rv))
1165 : mSpdyPingTimeout =
1166 673 : PR_SecondsToInterval((PRUint16) clamped(val, 0, 0x7fffffff));
1167 : }
1168 :
1169 : //
1170 : // INTL options
1171 : //
1172 :
1173 692 : if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) {
1174 1346 : nsCOMPtr<nsIPrefLocalizedString> pls;
1175 : prefs->GetComplexValue(INTL_ACCEPT_LANGUAGES,
1176 : NS_GET_IID(nsIPrefLocalizedString),
1177 673 : getter_AddRefs(pls));
1178 673 : if (pls) {
1179 1346 : nsXPIDLString uval;
1180 673 : pls->ToString(getter_Copies(uval));
1181 673 : if (uval)
1182 673 : SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval).get());
1183 : }
1184 : }
1185 :
1186 : //
1187 : // IDN options
1188 : //
1189 :
1190 692 : if (PREF_CHANGED(NETWORK_ENABLEIDN)) {
1191 673 : bool enableIDN = false;
1192 673 : 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 673 : if (enableIDN && !mIDNConverter) {
1197 673 : mIDNConverter = do_GetService(NS_IDNSERVICE_CONTRACTID);
1198 673 : 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 692 : if (PREF_CHANGED(DONOTTRACK_HEADER_ENABLED)) {
1209 673 : cVar = false;
1210 673 : rv = prefs->GetBoolPref(DONOTTRACK_HEADER_ENABLED, &cVar);
1211 673 : if (NS_SUCCEEDED(rv)) {
1212 673 : mDoNotTrackEnabled = cVar;
1213 : }
1214 : }
1215 :
1216 : //
1217 : // Telemetry
1218 : //
1219 :
1220 692 : if (PREF_CHANGED(TELEMETRY_ENABLED)) {
1221 673 : cVar = false;
1222 673 : rv = prefs->GetBoolPref(TELEMETRY_ENABLED, &cVar);
1223 673 : if (NS_SUCCEEDED(rv)) {
1224 673 : mTelemetryEnabled = cVar;
1225 : }
1226 : }
1227 :
1228 : //
1229 : // network.allow-experiments
1230 : //
1231 :
1232 692 : if (PREF_CHANGED(ALLOW_EXPERIMENTS)) {
1233 673 : cVar = true;
1234 673 : rv = prefs->GetBoolPref(ALLOW_EXPERIMENTS, &cVar);
1235 673 : if (NS_SUCCEEDED(rv)) {
1236 673 : mAllowExperiments = cVar;
1237 : }
1238 : }
1239 :
1240 : #undef PREF_CHANGED
1241 : #undef MULTI_PREF_CHANGED
1242 692 : }
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 673 : PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLanguages)
1259 : {
1260 673 : 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 673 : o_Accept = nsCRT::strdup(i_AcceptLanguages);
1270 673 : if (!o_Accept)
1271 0 : return NS_ERROR_OUT_OF_MEMORY;
1272 6730 : for (p = o_Accept, n = size = 0; '\0' != *p; p++) {
1273 6057 : if (*p == ',') n++;
1274 6057 : size++;
1275 : }
1276 :
1277 673 : available = size + ++n * 11 + 1;
1278 1346 : q_Accept = new char[available];
1279 673 : if (!q_Accept) {
1280 0 : nsCRT::free(o_Accept);
1281 0 : return NS_ERROR_OUT_OF_MEMORY;
1282 : }
1283 673 : *q_Accept = '\0';
1284 673 : q = 1.0;
1285 673 : dec = q / (double) n;
1286 673 : n = 0;
1287 673 : p2 = q_Accept;
1288 2019 : for (token = nsCRT::strtok(o_Accept, ",", &p);
1289 : token != (char *) 0;
1290 1346 : token = nsCRT::strtok(p, ",", &p))
1291 : {
1292 1346 : token = net_FindCharNotInSet(token, HTTP_LWS);
1293 : char* trim;
1294 1346 : trim = net_FindCharInSet(token, ";" HTTP_LWS);
1295 1346 : if (trim != (char*)0) // remove "; q=..." if present
1296 1346 : *trim = '\0';
1297 :
1298 1346 : if (*token != '\0') {
1299 1346 : comma = n++ != 0 ? "," : ""; // delimiter if not first item
1300 1346 : PRUint32 u = QVAL_TO_UINT(q);
1301 1346 : if (u < 10)
1302 673 : wrote = PR_snprintf(p2, available, "%s%s;q=0.%u", comma, token, u);
1303 : else
1304 673 : wrote = PR_snprintf(p2, available, "%s%s", comma, token);
1305 1346 : q -= dec;
1306 1346 : p2 += wrote;
1307 1346 : available -= wrote;
1308 1346 : NS_ASSERTION(available > 0, "allocated string not long enough");
1309 : }
1310 : }
1311 673 : nsCRT::free(o_Accept);
1312 :
1313 673 : o_AcceptLanguages.Assign((const char *) q_Accept);
1314 673 : delete [] q_Accept;
1315 :
1316 673 : return NS_OK;
1317 : }
1318 :
1319 : nsresult
1320 673 : nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages)
1321 : {
1322 1346 : nsCAutoString buf;
1323 673 : nsresult rv = PrepareAcceptLanguages(aAcceptLanguages, buf);
1324 673 : if (NS_SUCCEEDED(rv))
1325 673 : mAcceptLanguages.Assign(buf);
1326 673 : return rv;
1327 : }
1328 :
1329 : nsresult
1330 673 : nsHttpHandler::SetAccept(const char *aAccept)
1331 : {
1332 673 : mAccept = aAccept;
1333 673 : return NS_OK;
1334 : }
1335 :
1336 : nsresult
1337 673 : nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings)
1338 : {
1339 673 : mAcceptEncodings = aAcceptEncodings;
1340 673 : return NS_OK;
1341 : }
1342 :
1343 : //-----------------------------------------------------------------------------
1344 : // nsHttpHandler::nsISupports
1345 : //-----------------------------------------------------------------------------
1346 :
1347 459095 : 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 3705 : nsHttpHandler::GetDefaultPort(PRInt32 *result)
1367 : {
1368 3705 : *result = NS_HTTP_DEFAULT_PORT;
1369 3705 : return NS_OK;
1370 : }
1371 :
1372 : NS_IMETHODIMP
1373 26288 : nsHttpHandler::GetProtocolFlags(PRUint32 *result)
1374 : {
1375 26288 : *result = NS_HTTP_PROTOCOL_FLAGS;
1376 26288 : return NS_OK;
1377 : }
1378 :
1379 : NS_IMETHODIMP
1380 34020 : nsHttpHandler::NewURI(const nsACString &aSpec,
1381 : const char *aCharset,
1382 : nsIURI *aBaseURI,
1383 : nsIURI **aURI)
1384 : {
1385 34020 : LOG(("nsHttpHandler::NewURI\n"));
1386 34020 : return ::NewURI(aSpec, aCharset, aBaseURI, NS_HTTP_DEFAULT_PORT, aURI);
1387 : }
1388 :
1389 : NS_IMETHODIMP
1390 3500 : nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
1391 : {
1392 3500 : LOG(("nsHttpHandler::NewChannel\n"));
1393 :
1394 3500 : NS_ENSURE_ARG_POINTER(uri);
1395 3500 : NS_ENSURE_ARG_POINTER(result);
1396 :
1397 3500 : bool isHttp = false, isHttps = false;
1398 :
1399 : // Verify that we have been given a valid scheme
1400 3500 : nsresult rv = uri->SchemeIs("http", &isHttp);
1401 3500 : if (NS_FAILED(rv)) return rv;
1402 3500 : 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 3500 : 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 3529 : nsHttpHandler::NewProxiedChannel(nsIURI *uri,
1428 : nsIProxyInfo* givenProxyInfo,
1429 : nsIChannel **result)
1430 : {
1431 7058 : nsRefPtr<HttpBaseChannel> httpChannel;
1432 :
1433 3529 : LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
1434 : givenProxyInfo));
1435 :
1436 7058 : nsCOMPtr<nsProxyInfo> proxyInfo;
1437 3529 : if (givenProxyInfo) {
1438 24 : proxyInfo = do_QueryInterface(givenProxyInfo);
1439 24 : NS_ENSURE_ARG(proxyInfo);
1440 : }
1441 :
1442 : bool https;
1443 3529 : nsresult rv = uri->SchemeIs("https", &https);
1444 3529 : if (NS_FAILED(rv))
1445 0 : return rv;
1446 :
1447 3529 : if (IsNeckoChild()) {
1448 0 : httpChannel = new HttpChannelChild();
1449 : } else {
1450 3529 : 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 3529 : if (proxyInfo && !nsCRT::strcmp(proxyInfo->Type(), "http") && !https)
1457 14 : caps = mProxyCapabilities;
1458 : else
1459 3515 : caps = mCapabilities;
1460 :
1461 3529 : 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 3529 : rv = httpChannel->Init(uri, caps, proxyInfo);
1473 3529 : if (NS_FAILED(rv))
1474 0 : return rv;
1475 :
1476 3529 : httpChannel.forget(result);
1477 3529 : 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 1469 : nsHttpHandler::Observe(nsISupports *subject,
1546 : const char *topic,
1547 : const PRUnichar *data)
1548 : {
1549 1469 : LOG(("nsHttpHandler::Observe [topic=\"%s\"]\n", topic));
1550 :
1551 1469 : 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 2371 : else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
1557 921 : strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
1558 :
1559 : // clear cache of all authentication credentials.
1560 1202 : mAuthCache.ClearAll();
1561 :
1562 : // ensure connection manager is shutdown
1563 1202 : if (mConnMgr)
1564 1202 : mConnMgr->Shutdown();
1565 :
1566 : // need to reset the session start time since cache validation may
1567 : // depend on this value.
1568 1202 : 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 1469 : return NS_OK;
1592 : }
1593 :
1594 : //-----------------------------------------------------------------------------
1595 : // nsHttpsHandler implementation
1596 : //-----------------------------------------------------------------------------
1597 :
1598 2721 : NS_IMPL_THREADSAFE_ISUPPORTS4(nsHttpsHandler,
1599 : nsIHttpProtocolHandler,
1600 : nsIProxiedProtocolHandler,
1601 : nsIProtocolHandler,
1602 : nsISupportsWeakReference)
1603 :
1604 : nsresult
1605 38 : nsHttpsHandler::Init()
1606 : {
1607 : nsCOMPtr<nsIProtocolHandler> httpHandler(
1608 76 : do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http"));
1609 38 : NS_ASSERTION(httpHandler.get() != nsnull, "no http handler?");
1610 38 : 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 283 : nsHttpsHandler::NewURI(const nsACString &aSpec,
1636 : const char *aOriginCharset,
1637 : nsIURI *aBaseURI,
1638 : nsIURI **_retval)
1639 : {
1640 283 : 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 : }
|