forked from mirrors/gecko-dev
Losing a TCP SYN requires a long painful (typically 3 second) delay before being retried. This patch creates a second parallel connection attempt for any nsHttpConnection which has not become writable before a timeout occurs. If you assume .5% packet loss, this converts a full 3 second delay from a 1 in 200 event into a 1 in 40,000 event. Whichever connection establishes itself first is used. If another one has been started and it does connect before the one being used is closed then the extra one is handed to the connection manager for use by a different transaction - essentially a persistent connection with 0 previous transactions on it. (Another way to think about is pre-fetching a 3WHS on a high latency connection). The pref network.http.connection-retry-timeout controls the amount of time in ms to wait for success on the initial connection before beginning the second one. Setting it to 0 disables the parallel connection, the default is 250.
1689 lines
51 KiB
C++
1689 lines
51 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* vim:set ts=4 sw=4 sts=4 et cin: */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Mozilla.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications.
|
|
* Portions created by the Initial Developer are Copyright (C) 2001
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Darin Fisher <darin@netscape.com> (original author)
|
|
* Gagan Saksena <gagan@netscape.com>
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
* Christopher Blizzard <blizzard@mozilla.org>
|
|
* Adrian Havill <havill@redhat.com>
|
|
* Gervase Markham <gerv@gerv.net>
|
|
* Bradley Baetz <bbaetz@netscape.com>
|
|
* Benjamin Smedberg <bsmedberg@covad.net>
|
|
* Josh Aas <josh@mozilla.com>
|
|
* Dão Gottwald <dao@mozilla.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#include "nsHttp.h"
|
|
#include "nsHttpHandler.h"
|
|
#include "nsHttpChannel.h"
|
|
#include "nsHttpConnection.h"
|
|
#include "nsHttpResponseHead.h"
|
|
#include "nsHttpTransaction.h"
|
|
#include "nsHttpAuthCache.h"
|
|
#include "nsStandardURL.h"
|
|
#include "nsIHttpChannel.h"
|
|
#include "nsIURL.h"
|
|
#include "nsIStandardURL.h"
|
|
#include "nsICacheService.h"
|
|
#include "nsICategoryManager.h"
|
|
#include "nsCategoryManagerUtils.h"
|
|
#include "nsICacheService.h"
|
|
#include "nsIPrefService.h"
|
|
#include "nsIPrefBranch2.h"
|
|
#include "nsIPrefLocalizedString.h"
|
|
#include "nsISocketProviderService.h"
|
|
#include "nsISocketProvider.h"
|
|
#include "nsPrintfCString.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsNetCID.h"
|
|
#include "nsAutoLock.h"
|
|
#include "prprf.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsQuickSort.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsIOService.h"
|
|
#include "nsAsyncRedirectVerifyHelper.h"
|
|
#include "nsSocketTransportService2.h"
|
|
|
|
#include "nsIXULAppInfo.h"
|
|
|
|
#ifdef MOZ_IPC
|
|
#include "mozilla/net/NeckoChild.h"
|
|
#endif
|
|
|
|
#if defined(XP_UNIX) || defined(XP_BEOS)
|
|
#include <sys/utsname.h>
|
|
#endif
|
|
|
|
#if defined(XP_WIN)
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#if defined(XP_MACOSX)
|
|
#include <CoreServices/CoreServices.h>
|
|
#endif
|
|
|
|
#if defined(XP_OS2)
|
|
#define INCL_DOSMISC
|
|
#include <os2.h>
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
using namespace mozilla::net;
|
|
#ifdef MOZ_IPC
|
|
#include "mozilla/net/HttpChannelChild.h"
|
|
#endif
|
|
|
|
#include "mozilla/FunctionTimer.h"
|
|
|
|
#ifdef DEBUG
|
|
// defined by the socket transport service while active
|
|
extern PRThread *gSocketThread;
|
|
#endif
|
|
|
|
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
|
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
|
|
static NS_DEFINE_CID(kCookieServiceCID, NS_COOKIESERVICE_CID);
|
|
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
|
|
static NS_DEFINE_CID(kSocketProviderServiceCID, NS_SOCKETPROVIDERSERVICE_CID);
|
|
|
|
#define UA_PREF_PREFIX "general.useragent."
|
|
#ifdef XP_WIN
|
|
#define UA_SPARE_PLATFORM
|
|
#endif
|
|
|
|
#define HTTP_PREF_PREFIX "network.http."
|
|
#define INTL_ACCEPT_LANGUAGES "intl.accept_languages"
|
|
#define INTL_ACCEPT_CHARSET "intl.charset.default"
|
|
#define NETWORK_ENABLEIDN "network.enableIDN"
|
|
#define BROWSER_PREF_PREFIX "browser.cache."
|
|
|
|
#define UA_PREF(_pref) UA_PREF_PREFIX _pref
|
|
#define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
|
|
#define BROWSER_PREF(_pref) BROWSER_PREF_PREFIX _pref
|
|
|
|
#define NS_HTTP_PROTOCOL_FLAGS (URI_STD | ALLOWS_PROXY | ALLOWS_PROXY_HTTP | URI_LOADABLE_BY_ANYONE)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static nsresult
|
|
NewURI(const nsACString &aSpec,
|
|
const char *aCharset,
|
|
nsIURI *aBaseURI,
|
|
PRInt32 aDefaultPort,
|
|
nsIURI **aURI)
|
|
{
|
|
nsStandardURL *url = new nsStandardURL();
|
|
if (!url)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
NS_ADDREF(url);
|
|
|
|
nsresult rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY,
|
|
aDefaultPort, aSpec, aCharset, aBaseURI);
|
|
if (NS_FAILED(rv)) {
|
|
NS_RELEASE(url);
|
|
return rv;
|
|
}
|
|
|
|
*aURI = url; // no QI needed
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsHttpHandler <public>
|
|
//-----------------------------------------------------------------------------
|
|
|
|
nsHttpHandler *gHttpHandler = nsnull;
|
|
|
|
nsHttpHandler::nsHttpHandler()
|
|
: mConnMgr(nsnull)
|
|
, mHttpVersion(NS_HTTP_VERSION_1_1)
|
|
, mProxyHttpVersion(NS_HTTP_VERSION_1_1)
|
|
, mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
|
, mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
|
, mReferrerLevel(0xff) // by default we always send a referrer
|
|
, mIdleTimeout(10)
|
|
, mMaxRequestAttempts(10)
|
|
, mMaxRequestDelay(10)
|
|
, mIdleSynTimeout(250)
|
|
, mMaxConnections(24)
|
|
, mMaxConnectionsPerServer(8)
|
|
, mMaxPersistentConnectionsPerServer(2)
|
|
, mMaxPersistentConnectionsPerProxy(4)
|
|
, mMaxPipelinedRequests(2)
|
|
, mRedirectionLimit(10)
|
|
, mInPrivateBrowsingMode(PR_FALSE)
|
|
, mPhishyUserPassLength(1)
|
|
, mQoSBits(0x00)
|
|
, mPipeliningOverSSL(PR_FALSE)
|
|
, mLastUniqueID(NowInSeconds())
|
|
, mSessionStartTime(0)
|
|
, mLegacyAppName("Mozilla")
|
|
, mLegacyAppVersion("5.0")
|
|
, mProduct("Gecko")
|
|
, mUserAgentIsDirty(PR_TRUE)
|
|
, mUseCache(PR_TRUE)
|
|
, mPromptTempRedirect(PR_TRUE)
|
|
, mSendSecureXSiteReferrer(PR_TRUE)
|
|
, mEnablePersistentHttpsCaching(PR_FALSE)
|
|
{
|
|
#if defined(PR_LOGGING)
|
|
gHttpLog = PR_NewLogModule("nsHttp");
|
|
#endif
|
|
|
|
LOG(("Creating nsHttpHandler [this=%x].\n", this));
|
|
|
|
NS_ASSERTION(!gHttpHandler, "HTTP handler already created!");
|
|
gHttpHandler = this;
|
|
}
|
|
|
|
nsHttpHandler::~nsHttpHandler()
|
|
{
|
|
LOG(("Deleting nsHttpHandler [this=%x]\n", this));
|
|
|
|
// make sure the connection manager is shutdown
|
|
if (mConnMgr) {
|
|
mConnMgr->Shutdown();
|
|
NS_RELEASE(mConnMgr);
|
|
}
|
|
|
|
// Note: don't call NeckoChild::DestroyNeckoChild() here, as it's too late
|
|
// and it'll segfault. NeckoChild will get cleaned up by process exit.
|
|
|
|
nsHttp::DestroyAtomTable();
|
|
|
|
gHttpHandler = nsnull;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::Init()
|
|
{
|
|
NS_TIME_FUNCTION;
|
|
|
|
nsresult rv;
|
|
|
|
LOG(("nsHttpHandler::Init\n"));
|
|
|
|
rv = nsHttp::CreateAtomTable();
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
mIOService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
|
|
if (NS_FAILED(rv)) {
|
|
NS_WARNING("unable to continue without io service");
|
|
return rv;
|
|
}
|
|
|
|
#ifdef MOZ_IPC
|
|
if (IsNeckoChild())
|
|
NeckoChild::InitNeckoChild();
|
|
#endif // MOZ_IPC
|
|
|
|
// figure out if we're starting in private browsing mode
|
|
nsCOMPtr<nsIPrivateBrowsingService> pbs =
|
|
do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
|
|
if (pbs)
|
|
pbs->GetPrivateBrowsingEnabled(&mInPrivateBrowsingMode);
|
|
|
|
InitUserAgentComponents();
|
|
|
|
// monitor some preference changes
|
|
nsCOMPtr<nsIPrefBranch2> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
if (prefBranch) {
|
|
prefBranch->AddObserver(HTTP_PREF_PREFIX, this, PR_TRUE);
|
|
prefBranch->AddObserver(UA_PREF_PREFIX, this, PR_TRUE);
|
|
prefBranch->AddObserver(INTL_ACCEPT_LANGUAGES, this, PR_TRUE);
|
|
prefBranch->AddObserver(INTL_ACCEPT_CHARSET, this, PR_TRUE);
|
|
prefBranch->AddObserver(NETWORK_ENABLEIDN, this, PR_TRUE);
|
|
prefBranch->AddObserver(BROWSER_PREF("disk_cache_ssl"), this, PR_TRUE);
|
|
|
|
PrefsChanged(prefBranch, nsnull);
|
|
}
|
|
|
|
mMisc.AssignLiteral("rv:" MOZILLA_VERSION);
|
|
|
|
nsCOMPtr<nsIXULAppInfo> appInfo =
|
|
do_GetService("@mozilla.org/xre/app-info;1");
|
|
|
|
mAppName.AssignLiteral(MOZ_APP_UA_NAME);
|
|
if (mAppName.Length() == 0 && appInfo) {
|
|
appInfo->GetName(mAppName);
|
|
appInfo->GetVersion(mAppVersion);
|
|
mAppName.StripChars(" ()<>@,;:\\\"/[]?={}");
|
|
} else {
|
|
mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION);
|
|
}
|
|
|
|
#if DEBUG
|
|
// dump user agent prefs
|
|
LOG(("> legacy-app-name = %s\n", mLegacyAppName.get()));
|
|
LOG(("> legacy-app-version = %s\n", mLegacyAppVersion.get()));
|
|
LOG(("> platform = %s\n", mPlatform.get()));
|
|
LOG(("> oscpu = %s\n", mOscpu.get()));
|
|
LOG(("> language = %s\n", mLanguage.get()));
|
|
LOG(("> misc = %s\n", mMisc.get()));
|
|
LOG(("> product = %s\n", mProduct.get()));
|
|
LOG(("> product-sub = %s\n", mProductSub.get()));
|
|
LOG(("> app-name = %s\n", mAppName.get()));
|
|
LOG(("> app-version = %s\n", mAppVersion.get()));
|
|
LOG(("> compat-firefox = %s\n", mCompatFirefox.get()));
|
|
LOG(("> user-agent = %s\n", UserAgent().get()));
|
|
#endif
|
|
|
|
mSessionStartTime = NowInSeconds();
|
|
|
|
rv = mAuthCache.Init();
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = InitConnectionMgr();
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
mProductSub.AssignLiteral(MOZ_UA_BUILDID);
|
|
if (mProductSub.IsEmpty() && appInfo)
|
|
appInfo->GetPlatformBuildID(mProductSub);
|
|
if (mProductSub.Length() > 8)
|
|
mProductSub.SetLength(8);
|
|
|
|
// Startup the http category
|
|
// Bring alive the objects in the http-protocol-startup category
|
|
NS_CreateServicesFromCategory(NS_HTTP_STARTUP_CATEGORY,
|
|
static_cast<nsISupports*>(static_cast<void*>(this)),
|
|
NS_HTTP_STARTUP_TOPIC);
|
|
|
|
mObserverService = mozilla::services::GetObserverService();
|
|
if (mObserverService) {
|
|
mObserverService->AddObserver(this, "profile-change-net-teardown", PR_TRUE);
|
|
mObserverService->AddObserver(this, "profile-change-net-restore", PR_TRUE);
|
|
mObserverService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_TRUE);
|
|
mObserverService->AddObserver(this, "net:clear-active-logins", PR_TRUE);
|
|
mObserverService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, PR_TRUE);
|
|
mObserverService->AddObserver(this, "net:prune-dead-connections", PR_TRUE);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::InitConnectionMgr()
|
|
{
|
|
NS_TIME_FUNCTION;
|
|
|
|
nsresult rv;
|
|
|
|
if (!mConnMgr) {
|
|
mConnMgr = new nsHttpConnectionMgr();
|
|
if (!mConnMgr)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
NS_ADDREF(mConnMgr);
|
|
}
|
|
|
|
rv = mConnMgr->Init(mMaxConnections,
|
|
mMaxConnectionsPerServer,
|
|
mMaxConnectionsPerServer,
|
|
mMaxPersistentConnectionsPerServer,
|
|
mMaxPersistentConnectionsPerProxy,
|
|
mMaxRequestDelay,
|
|
mMaxPipelinedRequests);
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
|
PRUint8 caps,
|
|
PRBool useProxy)
|
|
{
|
|
nsresult rv;
|
|
|
|
// Add the "User-Agent" header
|
|
rv = request->SetHeader(nsHttp::User_Agent, UserAgent());
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// MIME based content negotiation lives!
|
|
// Add the "Accept" header
|
|
rv = request->SetHeader(nsHttp::Accept, mAccept);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Add the "Accept-Language" header
|
|
if (!mAcceptLanguages.IsEmpty()) {
|
|
// Add the "Accept-Language" header
|
|
rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
|
|
// Add the "Accept-Encoding" header
|
|
rv = request->SetHeader(nsHttp::Accept_Encoding, mAcceptEncodings);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// Add the "Accept-Charset" header
|
|
rv = request->SetHeader(nsHttp::Accept_Charset, mAcceptCharsets);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
// RFC2616 section 19.6.2 states that the "Connection: keep-alive"
|
|
// and "Keep-alive" request headers should not be sent by HTTP/1.1
|
|
// user-agents. Otherwise, problems with proxy servers (especially
|
|
// transparent proxies) can result.
|
|
//
|
|
// However, we need to send something so that we can use keepalive
|
|
// with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when
|
|
// we're talking to an http proxy, and "Connection:" otherwise
|
|
|
|
NS_NAMED_LITERAL_CSTRING(close, "close");
|
|
NS_NAMED_LITERAL_CSTRING(keepAlive, "keep-alive");
|
|
|
|
const nsACString *connectionType = &close;
|
|
if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
|
|
rv = request->SetHeader(nsHttp::Keep_Alive, nsPrintfCString("%u", mIdleTimeout));
|
|
if (NS_FAILED(rv)) return rv;
|
|
connectionType = &keepAlive;
|
|
} else if (useProxy) {
|
|
// Bug 92006
|
|
request->SetHeader(nsHttp::Connection, close);
|
|
}
|
|
|
|
const nsHttpAtom &header = useProxy ? nsHttp::Proxy_Connection
|
|
: nsHttp::Connection;
|
|
return request->SetHeader(header, *connectionType);
|
|
}
|
|
|
|
PRBool
|
|
nsHttpHandler::IsAcceptableEncoding(const char *enc)
|
|
{
|
|
if (!enc)
|
|
return PR_FALSE;
|
|
|
|
// HTTP 1.1 allows servers to send x-gzip and x-compress instead
|
|
// of gzip and compress, for example. So, we'll always strip off
|
|
// an "x-" prefix before matching the encoding to one we claim
|
|
// to accept.
|
|
if (!PL_strncasecmp(enc, "x-", 2))
|
|
enc += 2;
|
|
|
|
return nsHttp::FindToken(mAcceptEncodings.get(), enc, HTTP_LWS ",") != nsnull;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy,
|
|
nsICacheSession **result)
|
|
{
|
|
nsresult rv;
|
|
|
|
// Skip cache if disabled in preferences
|
|
if (!mUseCache)
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
// We want to get the pointer to the cache service each time we're called,
|
|
// because it's possible for some add-ons (such as Google Gears) to swap
|
|
// in new cache services on the fly, and we want to pick them up as
|
|
// appropriate.
|
|
nsCOMPtr<nsICacheService> serv = do_GetService(NS_CACHESERVICE_CONTRACTID,
|
|
&rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
const char *sessionName = "HTTP";
|
|
switch (storagePolicy) {
|
|
case nsICache::STORE_IN_MEMORY:
|
|
sessionName = "HTTP-memory-only";
|
|
break;
|
|
case nsICache::STORE_OFFLINE:
|
|
sessionName = "HTTP-offline";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
nsCOMPtr<nsICacheSession> cacheSession;
|
|
rv = serv->CreateSession(sessionName,
|
|
storagePolicy,
|
|
nsICache::STREAM_BASED,
|
|
getter_AddRefs(cacheSession));
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
rv = cacheSession->SetDoomEntriesIfExpired(PR_FALSE);
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
NS_ADDREF(*result = cacheSession);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
|
|
{
|
|
if (!mStreamConvSvc) {
|
|
nsresult rv;
|
|
mStreamConvSvc = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
|
|
if (NS_FAILED(rv)) return rv;
|
|
}
|
|
*result = mStreamConvSvc;
|
|
NS_ADDREF(*result);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsIStrictTransportSecurityService*
|
|
nsHttpHandler::GetSTSService()
|
|
{
|
|
if (!mSTSService)
|
|
mSTSService = do_GetService(NS_STSSERVICE_CONTRACTID);
|
|
return mSTSService;
|
|
}
|
|
|
|
nsICookieService *
|
|
nsHttpHandler::GetCookieService()
|
|
{
|
|
if (!mCookieService)
|
|
mCookieService = do_GetService(NS_COOKIESERVICE_CONTRACTID);
|
|
return mCookieService;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::GetIOService(nsIIOService** result)
|
|
{
|
|
NS_ADDREF(*result = mIOService);
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
void
|
|
nsHttpHandler::NotifyObservers(nsIHttpChannel *chan, const char *event)
|
|
{
|
|
LOG(("nsHttpHandler::NotifyObservers [chan=%x event=\"%s\"]\n", chan, event));
|
|
if (mObserverService)
|
|
mObserverService->NotifyObservers(chan, event, nsnull);
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
|
|
PRUint32 flags)
|
|
{
|
|
// TODO E10S This helper has to be initialized on the other process
|
|
nsRefPtr<nsAsyncRedirectVerifyHelper> redirectCallbackHelper =
|
|
new nsAsyncRedirectVerifyHelper();
|
|
|
|
return redirectCallbackHelper->Init(oldChan, newChan, flags);
|
|
}
|
|
|
|
/* static */ nsresult
|
|
nsHttpHandler::GenerateHostPort(const nsCString& host, PRInt32 port,
|
|
nsCString& hostLine)
|
|
{
|
|
if (strchr(host.get(), ':')) {
|
|
// host is an IPv6 address literal and must be encapsulated in []'s
|
|
hostLine.Assign('[');
|
|
// scope id is not needed for Host header.
|
|
int scopeIdPos = host.FindChar('%');
|
|
if (scopeIdPos == kNotFound)
|
|
hostLine.Append(host);
|
|
else if (scopeIdPos > 0)
|
|
hostLine.Append(Substring(host, 0, scopeIdPos));
|
|
else
|
|
return NS_ERROR_MALFORMED_URI;
|
|
hostLine.Append(']');
|
|
}
|
|
else
|
|
hostLine.Assign(host);
|
|
if (port != -1) {
|
|
hostLine.Append(':');
|
|
hostLine.AppendInt(port);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsHttpHandler <private>
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const nsAFlatCString &
|
|
nsHttpHandler::UserAgent()
|
|
{
|
|
if (mUserAgentOverride) {
|
|
LOG(("using general.useragent.override : %s\n", mUserAgentOverride.get()));
|
|
return mUserAgentOverride;
|
|
}
|
|
|
|
if (mUserAgentIsDirty) {
|
|
BuildUserAgent();
|
|
mUserAgentIsDirty = PR_FALSE;
|
|
}
|
|
|
|
return mUserAgent;
|
|
}
|
|
|
|
void
|
|
nsHttpHandler::BuildUserAgent()
|
|
{
|
|
LOG(("nsHttpHandler::BuildUserAgent\n"));
|
|
|
|
NS_ASSERTION(!mLegacyAppName.IsEmpty() &&
|
|
!mLegacyAppVersion.IsEmpty() &&
|
|
!mPlatform.IsEmpty() &&
|
|
!mOscpu.IsEmpty(),
|
|
"HTTP cannot send practical requests without this much");
|
|
|
|
// preallocate to worst-case size, which should always be better
|
|
// than if we didn't preallocate at all.
|
|
mUserAgent.SetCapacity(mLegacyAppName.Length() +
|
|
mLegacyAppVersion.Length() +
|
|
#ifndef UA_SPARE_PLATFORM
|
|
mPlatform.Length() +
|
|
#endif
|
|
mOscpu.Length() +
|
|
mMisc.Length() +
|
|
mProduct.Length() +
|
|
mProductSub.Length() +
|
|
mAppName.Length() +
|
|
mAppVersion.Length() +
|
|
mCompatFirefox.Length() +
|
|
13);
|
|
|
|
// Application portion
|
|
mUserAgent.Assign(mLegacyAppName);
|
|
mUserAgent += '/';
|
|
mUserAgent += mLegacyAppVersion;
|
|
mUserAgent += ' ';
|
|
|
|
// Application comment
|
|
mUserAgent += '(';
|
|
#ifndef UA_SPARE_PLATFORM
|
|
mUserAgent += mPlatform;
|
|
mUserAgent.AppendLiteral("; ");
|
|
#endif
|
|
mUserAgent += mOscpu;
|
|
mUserAgent.AppendLiteral("; ");
|
|
mUserAgent += mMisc;
|
|
mUserAgent += ')';
|
|
|
|
// Product portion
|
|
mUserAgent += ' ';
|
|
mUserAgent += mProduct;
|
|
mUserAgent += '/';
|
|
mUserAgent += mProductSub;
|
|
|
|
// "Firefox/x.y.z" compatibility token
|
|
if (!mCompatFirefox.IsEmpty()) {
|
|
mUserAgent += ' ';
|
|
mUserAgent += mCompatFirefox;
|
|
}
|
|
|
|
// App portion
|
|
mUserAgent += ' ';
|
|
mUserAgent += mAppName;
|
|
mUserAgent += '/';
|
|
mUserAgent += mAppVersion;
|
|
}
|
|
|
|
#ifdef XP_WIN
|
|
typedef BOOL (WINAPI *IsWow64ProcessP) (HANDLE, PBOOL);
|
|
|
|
#define WNT_BASE "Windows NT %ld.%ld"
|
|
#define W64_PREFIX "; Win64"
|
|
#endif
|
|
|
|
void
|
|
nsHttpHandler::InitUserAgentComponents()
|
|
{
|
|
|
|
// Gather platform.
|
|
mPlatform.AssignLiteral(
|
|
#if defined(ANDROID)
|
|
"Android"
|
|
#elif defined(XP_OS2)
|
|
"OS/2"
|
|
#elif defined(XP_WIN)
|
|
"Windows"
|
|
#elif defined(XP_MACOSX)
|
|
"Macintosh"
|
|
#elif defined(XP_BEOS)
|
|
"BeOS"
|
|
#elif defined(MOZ_PLATFORM_MAEMO)
|
|
"Maemo"
|
|
#elif defined(MOZ_X11)
|
|
"X11"
|
|
#else
|
|
"?"
|
|
#endif
|
|
);
|
|
|
|
// Gather OS/CPU.
|
|
#if defined(XP_OS2)
|
|
ULONG os2ver = 0;
|
|
DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_MINOR,
|
|
&os2ver, sizeof(os2ver));
|
|
if (os2ver == 11)
|
|
mOscpu.AssignLiteral("2.11");
|
|
else if (os2ver == 30)
|
|
mOscpu.AssignLiteral("Warp 3");
|
|
else if (os2ver == 40)
|
|
mOscpu.AssignLiteral("Warp 4");
|
|
else if (os2ver == 45)
|
|
mOscpu.AssignLiteral("Warp 4.5");
|
|
|
|
#elif defined(WINCE) || defined(XP_WIN)
|
|
OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
|
|
if (GetVersionEx(&info)) {
|
|
const char *format;
|
|
#ifdef WINCE
|
|
format = "WindowsCE %ld.%ld";
|
|
#elif defined _M_IA64
|
|
format = WNT_BASE W64_PREFIX "; IA64";
|
|
#elif defined _M_X64 || defined _M_AMD64
|
|
format = WNT_BASE W64_PREFIX "; x64";
|
|
#else
|
|
BOOL isWow64 = FALSE;
|
|
IsWow64ProcessP fnIsWow64Process = (IsWow64ProcessP)
|
|
GetProcAddress(GetModuleHandleW(L"kernel32"), "IsWow64Process");
|
|
if (fnIsWow64Process &&
|
|
!fnIsWow64Process(GetCurrentProcess(), &isWow64)) {
|
|
isWow64 = FALSE;
|
|
}
|
|
format = isWow64
|
|
? WNT_BASE "; WOW64"
|
|
: WNT_BASE;
|
|
#endif
|
|
char *buf = PR_smprintf(format,
|
|
info.dwMajorVersion,
|
|
info.dwMinorVersion);
|
|
if (buf) {
|
|
mOscpu = buf;
|
|
PR_smprintf_free(buf);
|
|
}
|
|
}
|
|
#elif defined (XP_MACOSX)
|
|
#if defined(__ppc__)
|
|
mOscpu.AssignLiteral("PPC Mac OS X");
|
|
#elif defined(__i386__) || defined(__x86_64__)
|
|
mOscpu.AssignLiteral("Intel Mac OS X");
|
|
#endif
|
|
SInt32 majorVersion, minorVersion;
|
|
if ((::Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
|
|
(::Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
|
|
mOscpu += nsPrintfCString(" %d.%d", majorVersion, minorVersion);
|
|
}
|
|
#elif defined (XP_UNIX) || defined (XP_BEOS)
|
|
struct utsname name;
|
|
|
|
int ret = uname(&name);
|
|
if (ret >= 0) {
|
|
nsCAutoString buf;
|
|
buf = (char*)name.sysname;
|
|
|
|
if (strcmp(name.machine, "x86_64") == 0 &&
|
|
sizeof(void *) == sizeof(PRInt32)) {
|
|
// We're running 32-bit code on x86_64. Make this browser
|
|
// look like it's running on i686 hardware, but append "
|
|
// (x86_64)" to the end of the oscpu identifier to be able
|
|
// to differentiate this from someone running 64-bit code
|
|
// on x86_64..
|
|
|
|
buf += " i686 on x86_64";
|
|
} else {
|
|
buf += ' ';
|
|
|
|
#ifdef AIX
|
|
// AIX uname returns machine specific info in the uname.machine
|
|
// field and does not return the cpu type like other platforms.
|
|
// We use the AIX version and release numbers instead.
|
|
buf += (char*)name.version;
|
|
buf += '.';
|
|
buf += (char*)name.release;
|
|
#else
|
|
buf += (char*)name.machine;
|
|
#endif
|
|
}
|
|
|
|
mOscpu.Assign(buf);
|
|
}
|
|
#endif
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
}
|
|
|
|
void
|
|
nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
PRInt32 val;
|
|
|
|
LOG(("nsHttpHandler::PrefsChanged [pref=%s]\n", pref));
|
|
|
|
#define PREF_CHANGED(p) ((pref == nsnull) || !PL_strcmp(pref, p))
|
|
#define MULTI_PREF_CHANGED(p) \
|
|
((pref == nsnull) || !PL_strncmp(pref, p, sizeof(p) - 1))
|
|
|
|
//
|
|
// UA components
|
|
//
|
|
|
|
PRBool cVar = PR_FALSE;
|
|
|
|
if (PREF_CHANGED(UA_PREF("compatMode.firefox"))) {
|
|
rv = prefs->GetBoolPref(UA_PREF("compatMode.firefox"), &cVar);
|
|
if (NS_SUCCEEDED(rv) && cVar) {
|
|
mCompatFirefox.AssignLiteral("Firefox/" MOZ_UA_FIREFOX_VERSION);
|
|
} else {
|
|
mCompatFirefox.Truncate();
|
|
}
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
}
|
|
|
|
// Gather locale.
|
|
if (PREF_CHANGED(UA_PREF("locale"))) {
|
|
nsCOMPtr<nsIPrefLocalizedString> pls;
|
|
prefs->GetComplexValue(UA_PREF("locale"),
|
|
NS_GET_IID(nsIPrefLocalizedString),
|
|
getter_AddRefs(pls));
|
|
if (pls) {
|
|
nsXPIDLString uval;
|
|
pls->ToString(getter_Copies(uval));
|
|
if (uval)
|
|
CopyUTF16toUTF8(uval, mLanguage);
|
|
}
|
|
else {
|
|
nsXPIDLCString cval;
|
|
rv = prefs->GetCharPref(UA_PREF("locale"), getter_Copies(cval));
|
|
if (cval)
|
|
mLanguage.Assign(cval);
|
|
}
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
}
|
|
|
|
// general.useragent.override
|
|
if (PREF_CHANGED(UA_PREF("override"))) {
|
|
prefs->GetCharPref(UA_PREF("override"),
|
|
getter_Copies(mUserAgentOverride));
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
}
|
|
|
|
//
|
|
// HTTP options
|
|
//
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("keep-alive.timeout"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("keep-alive.timeout"), &val);
|
|
if (NS_SUCCEEDED(rv))
|
|
mIdleTimeout = (PRUint16) NS_CLAMP(val, 1, 0xffff);
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("request.max-attempts"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("request.max-attempts"), &val);
|
|
if (NS_SUCCEEDED(rv))
|
|
mMaxRequestAttempts = (PRUint16) NS_CLAMP(val, 1, 0xffff);
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("request.max-start-delay"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("request.max-start-delay"), &val);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mMaxRequestDelay = (PRUint16) NS_CLAMP(val, 0, 0xffff);
|
|
if (mConnMgr)
|
|
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_REQUEST_DELAY,
|
|
mMaxRequestDelay);
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mMaxConnections = (PRUint16) NS_CLAMP(val, 1, NS_SOCKET_MAX_COUNT);
|
|
if (mConnMgr)
|
|
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
|
|
mMaxConnections);
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("max-connections-per-server"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("max-connections-per-server"), &val);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mMaxConnectionsPerServer = (PRUint8) NS_CLAMP(val, 1, 0xff);
|
|
if (mConnMgr) {
|
|
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS_PER_HOST,
|
|
mMaxConnectionsPerServer);
|
|
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS_PER_PROXY,
|
|
mMaxConnectionsPerServer);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-server"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-server"), &val);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mMaxPersistentConnectionsPerServer = (PRUint8) NS_CLAMP(val, 1, 0xff);
|
|
if (mConnMgr)
|
|
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_HOST,
|
|
mMaxPersistentConnectionsPerServer);
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-proxy"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-proxy"), &val);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mMaxPersistentConnectionsPerProxy = (PRUint8) NS_CLAMP(val, 1, 0xff);
|
|
if (mConnMgr)
|
|
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
|
|
mMaxPersistentConnectionsPerProxy);
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("sendRefererHeader"), &val);
|
|
if (NS_SUCCEEDED(rv))
|
|
mReferrerLevel = (PRUint8) NS_CLAMP(val, 0, 0xff);
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
|
|
if (NS_SUCCEEDED(rv))
|
|
mRedirectionLimit = (PRUint8) NS_CLAMP(val, 0, 0xff);
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("connection-retry-timeout"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("connection-retry-timeout"), &val);
|
|
if (NS_SUCCEEDED(rv))
|
|
mIdleSynTimeout = (PRUint16) NS_CLAMP(val, 0, 3000);
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("version"))) {
|
|
nsXPIDLCString httpVersion;
|
|
prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));
|
|
if (httpVersion) {
|
|
if (!PL_strcmp(httpVersion, "1.1"))
|
|
mHttpVersion = NS_HTTP_VERSION_1_1;
|
|
else if (!PL_strcmp(httpVersion, "0.9"))
|
|
mHttpVersion = NS_HTTP_VERSION_0_9;
|
|
else
|
|
mHttpVersion = NS_HTTP_VERSION_1_0;
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("proxy.version"))) {
|
|
nsXPIDLCString httpVersion;
|
|
prefs->GetCharPref(HTTP_PREF("proxy.version"), getter_Copies(httpVersion));
|
|
if (httpVersion) {
|
|
if (!PL_strcmp(httpVersion, "1.1"))
|
|
mProxyHttpVersion = NS_HTTP_VERSION_1_1;
|
|
else
|
|
mProxyHttpVersion = NS_HTTP_VERSION_1_0;
|
|
// it does not make sense to issue a HTTP/0.9 request to a proxy server
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("keep-alive"))) {
|
|
rv = prefs->GetBoolPref(HTTP_PREF("keep-alive"), &cVar);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
if (cVar)
|
|
mCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
|
|
else
|
|
mCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("proxy.keep-alive"))) {
|
|
rv = prefs->GetBoolPref(HTTP_PREF("proxy.keep-alive"), &cVar);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
if (cVar)
|
|
mProxyCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
|
|
else
|
|
mProxyCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("pipelining"))) {
|
|
rv = prefs->GetBoolPref(HTTP_PREF("pipelining"), &cVar);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
if (cVar)
|
|
mCapabilities |= NS_HTTP_ALLOW_PIPELINING;
|
|
else
|
|
mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("pipelining.maxrequests"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("pipelining.maxrequests"), &val);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mMaxPipelinedRequests = NS_CLAMP(val, 1, NS_HTTP_MAX_PIPELINED_REQUESTS);
|
|
if (mConnMgr)
|
|
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_PIPELINED_REQUESTS,
|
|
mMaxPipelinedRequests);
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("pipelining.ssl"))) {
|
|
rv = prefs->GetBoolPref(HTTP_PREF("pipelining.ssl"), &cVar);
|
|
if (NS_SUCCEEDED(rv))
|
|
mPipeliningOverSSL = cVar;
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
|
|
rv = prefs->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
if (cVar)
|
|
mProxyCapabilities |= NS_HTTP_ALLOW_PIPELINING;
|
|
else
|
|
mProxyCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("qos"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("qos"), &val);
|
|
if (NS_SUCCEEDED(rv))
|
|
mQoSBits = (PRUint8) NS_CLAMP(val, 0, 0xff);
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("sendSecureXSiteReferrer"))) {
|
|
rv = prefs->GetBoolPref(HTTP_PREF("sendSecureXSiteReferrer"), &cVar);
|
|
if (NS_SUCCEEDED(rv))
|
|
mSendSecureXSiteReferrer = cVar;
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
|
|
nsXPIDLCString accept;
|
|
rv = prefs->GetCharPref(HTTP_PREF("accept.default"),
|
|
getter_Copies(accept));
|
|
if (NS_SUCCEEDED(rv))
|
|
SetAccept(accept);
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
|
|
nsXPIDLCString acceptEncodings;
|
|
rv = prefs->GetCharPref(HTTP_PREF("accept-encoding"),
|
|
getter_Copies(acceptEncodings));
|
|
if (NS_SUCCEEDED(rv))
|
|
SetAcceptEncodings(acceptEncodings);
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("use-cache"))) {
|
|
rv = prefs->GetBoolPref(HTTP_PREF("use-cache"), &cVar);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mUseCache = cVar;
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("default-socket-type"))) {
|
|
nsXPIDLCString sval;
|
|
rv = prefs->GetCharPref(HTTP_PREF("default-socket-type"),
|
|
getter_Copies(sval));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
if (sval.IsEmpty())
|
|
mDefaultSocketType.Adopt(0);
|
|
else {
|
|
// verify that this socket type is actually valid
|
|
nsCOMPtr<nsISocketProviderService> sps(
|
|
do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID));
|
|
if (sps) {
|
|
nsCOMPtr<nsISocketProvider> sp;
|
|
rv = sps->GetSocketProvider(sval, getter_AddRefs(sp));
|
|
if (NS_SUCCEEDED(rv)) {
|
|
// OK, this looks like a valid socket provider.
|
|
mDefaultSocketType.Assign(sval);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("prompt-temp-redirect"))) {
|
|
rv = prefs->GetBoolPref(HTTP_PREF("prompt-temp-redirect"), &cVar);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
mPromptTempRedirect = cVar;
|
|
}
|
|
}
|
|
|
|
// enable Persistent caching for HTTPS - bug#205921
|
|
if (PREF_CHANGED(BROWSER_PREF("disk_cache_ssl"))) {
|
|
cVar = PR_FALSE;
|
|
rv = prefs->GetBoolPref(BROWSER_PREF("disk_cache_ssl"), &cVar);
|
|
if (NS_SUCCEEDED(rv))
|
|
mEnablePersistentHttpsCaching = cVar;
|
|
}
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("phishy-userpass-length"))) {
|
|
rv = prefs->GetIntPref(HTTP_PREF("phishy-userpass-length"), &val);
|
|
if (NS_SUCCEEDED(rv))
|
|
mPhishyUserPassLength = (PRUint8) NS_CLAMP(val, 0, 0xff);
|
|
}
|
|
|
|
//
|
|
// INTL options
|
|
//
|
|
|
|
if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) {
|
|
nsCOMPtr<nsIPrefLocalizedString> pls;
|
|
prefs->GetComplexValue(INTL_ACCEPT_LANGUAGES,
|
|
NS_GET_IID(nsIPrefLocalizedString),
|
|
getter_AddRefs(pls));
|
|
if (pls) {
|
|
nsXPIDLString uval;
|
|
pls->ToString(getter_Copies(uval));
|
|
if (uval)
|
|
SetAcceptLanguages(NS_ConvertUTF16toUTF8(uval).get());
|
|
}
|
|
}
|
|
|
|
if (PREF_CHANGED(INTL_ACCEPT_CHARSET)) {
|
|
nsCOMPtr<nsIPrefLocalizedString> pls;
|
|
prefs->GetComplexValue(INTL_ACCEPT_CHARSET,
|
|
NS_GET_IID(nsIPrefLocalizedString),
|
|
getter_AddRefs(pls));
|
|
if (pls) {
|
|
nsXPIDLString uval;
|
|
pls->ToString(getter_Copies(uval));
|
|
if (uval)
|
|
SetAcceptCharsets(NS_ConvertUTF16toUTF8(uval).get());
|
|
}
|
|
}
|
|
|
|
//
|
|
// IDN options
|
|
//
|
|
|
|
if (PREF_CHANGED(NETWORK_ENABLEIDN)) {
|
|
PRBool enableIDN = PR_FALSE;
|
|
prefs->GetBoolPref(NETWORK_ENABLEIDN, &enableIDN);
|
|
// No locking is required here since this method runs in the main
|
|
// UI thread, and so do all the methods in nsHttpChannel.cpp
|
|
// (mIDNConverter is used by nsHttpChannel)
|
|
if (enableIDN && !mIDNConverter) {
|
|
mIDNConverter = do_GetService(NS_IDNSERVICE_CONTRACTID);
|
|
NS_ASSERTION(mIDNConverter, "idnSDK not installed");
|
|
}
|
|
else if (!enableIDN && mIDNConverter)
|
|
mIDNConverter = nsnull;
|
|
}
|
|
|
|
#undef PREF_CHANGED
|
|
#undef MULTI_PREF_CHANGED
|
|
}
|
|
|
|
/**
|
|
* Allocates a C string into that contains a ISO 639 language list
|
|
* notated with HTTP "q" values for output with a HTTP Accept-Language
|
|
* header. Previous q values will be stripped because the order of
|
|
* the langs imply the q value. The q values are calculated by dividing
|
|
* 1.0 amongst the number of languages present.
|
|
*
|
|
* Ex: passing: "en, ja"
|
|
* returns: "en,ja;q=0.5"
|
|
*
|
|
* passing: "en, ja, fr_CA"
|
|
* returns: "en,ja;q=0.7,fr_CA;q=0.3"
|
|
*/
|
|
static nsresult
|
|
PrepareAcceptLanguages(const char *i_AcceptLanguages, nsACString &o_AcceptLanguages)
|
|
{
|
|
if (!i_AcceptLanguages)
|
|
return NS_OK;
|
|
|
|
PRUint32 n, size, wrote;
|
|
double q, dec;
|
|
char *p, *p2, *token, *q_Accept, *o_Accept;
|
|
const char *comma;
|
|
PRInt32 available;
|
|
|
|
o_Accept = nsCRT::strdup(i_AcceptLanguages);
|
|
if (!o_Accept)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
for (p = o_Accept, n = size = 0; '\0' != *p; p++) {
|
|
if (*p == ',') n++;
|
|
size++;
|
|
}
|
|
|
|
available = size + ++n * 11 + 1;
|
|
q_Accept = new char[available];
|
|
if (!q_Accept) {
|
|
nsCRT::free(o_Accept);
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
*q_Accept = '\0';
|
|
q = 1.0;
|
|
dec = q / (double) n;
|
|
n = 0;
|
|
p2 = q_Accept;
|
|
for (token = nsCRT::strtok(o_Accept, ",", &p);
|
|
token != (char *) 0;
|
|
token = nsCRT::strtok(p, ",", &p))
|
|
{
|
|
token = net_FindCharNotInSet(token, HTTP_LWS);
|
|
char* trim;
|
|
trim = net_FindCharInSet(token, ";" HTTP_LWS);
|
|
if (trim != (char*)0) // remove "; q=..." if present
|
|
*trim = '\0';
|
|
|
|
if (*token != '\0') {
|
|
comma = n++ != 0 ? "," : ""; // delimiter if not first item
|
|
PRUint32 u = QVAL_TO_UINT(q);
|
|
if (u < 10)
|
|
wrote = PR_snprintf(p2, available, "%s%s;q=0.%u", comma, token, u);
|
|
else
|
|
wrote = PR_snprintf(p2, available, "%s%s", comma, token);
|
|
q -= dec;
|
|
p2 += wrote;
|
|
available -= wrote;
|
|
NS_ASSERTION(available > 0, "allocated string not long enough");
|
|
}
|
|
}
|
|
nsCRT::free(o_Accept);
|
|
|
|
o_AcceptLanguages.Assign((const char *) q_Accept);
|
|
delete [] q_Accept;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::SetAcceptLanguages(const char *aAcceptLanguages)
|
|
{
|
|
nsCAutoString buf;
|
|
nsresult rv = PrepareAcceptLanguages(aAcceptLanguages, buf);
|
|
if (NS_SUCCEEDED(rv))
|
|
mAcceptLanguages.Assign(buf);
|
|
return rv;
|
|
}
|
|
|
|
/**
|
|
* Allocates a C string into that contains a character set/encoding list
|
|
* notated with HTTP "q" values for output with a HTTP Accept-Charset
|
|
* header. If the UTF-8 character set is not present, it will be added.
|
|
* If a wildcard catch-all is not present, it will be added. If more than
|
|
* one charset is set (as of 2001-02-07, only one is used), they will be
|
|
* comma delimited and with q values set for each charset in decending order.
|
|
*
|
|
* Ex: passing: "euc-jp"
|
|
* returns: "euc-jp,utf-8;q=0.6,*;q=0.6"
|
|
*
|
|
* passing: "UTF-8"
|
|
* returns: "UTF-8, *"
|
|
*/
|
|
static nsresult
|
|
PrepareAcceptCharsets(const char *i_AcceptCharset, nsACString &o_AcceptCharset)
|
|
{
|
|
PRUint32 n, size, wrote, u;
|
|
PRInt32 available;
|
|
double q, dec;
|
|
char *p, *p2, *token, *q_Accept, *o_Accept;
|
|
const char *acceptable, *comma;
|
|
PRBool add_utf = PR_FALSE;
|
|
PRBool add_asterisk = PR_FALSE;
|
|
|
|
if (!i_AcceptCharset)
|
|
acceptable = "";
|
|
else
|
|
acceptable = i_AcceptCharset;
|
|
o_Accept = nsCRT::strdup(acceptable);
|
|
if (nsnull == o_Accept)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
for (p = o_Accept, n = size = 0; '\0' != *p; p++) {
|
|
if (*p == ',') n++;
|
|
size++;
|
|
}
|
|
|
|
// only add "utf-8" and "*" to the list if they aren't
|
|
// already specified.
|
|
|
|
if (PL_strcasestr(acceptable, "utf-8") == NULL) {
|
|
n++;
|
|
add_utf = PR_TRUE;
|
|
}
|
|
if (PL_strchr(acceptable, '*') == NULL) {
|
|
n++;
|
|
add_asterisk = PR_TRUE;
|
|
}
|
|
|
|
available = size + ++n * 11 + 1;
|
|
q_Accept = new char[available];
|
|
if ((char *) 0 == q_Accept)
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
*q_Accept = '\0';
|
|
q = 1.0;
|
|
dec = q / (double) n;
|
|
n = 0;
|
|
p2 = q_Accept;
|
|
for (token = nsCRT::strtok(o_Accept, ",", &p);
|
|
token != (char *) 0;
|
|
token = nsCRT::strtok(p, ",", &p)) {
|
|
token = net_FindCharNotInSet(token, HTTP_LWS);
|
|
char* trim;
|
|
trim = net_FindCharInSet(token, ";" HTTP_LWS);
|
|
if (trim != (char*)0) // remove "; q=..." if present
|
|
*trim = '\0';
|
|
|
|
if (*token != '\0') {
|
|
comma = n++ != 0 ? "," : ""; // delimiter if not first item
|
|
u = QVAL_TO_UINT(q);
|
|
if (u < 10)
|
|
wrote = PR_snprintf(p2, available, "%s%s;q=0.%u", comma, token, u);
|
|
else
|
|
wrote = PR_snprintf(p2, available, "%s%s", comma, token);
|
|
q -= dec;
|
|
p2 += wrote;
|
|
available -= wrote;
|
|
NS_ASSERTION(available > 0, "allocated string not long enough");
|
|
}
|
|
}
|
|
if (add_utf) {
|
|
comma = n++ != 0 ? "," : ""; // delimiter if not first item
|
|
u = QVAL_TO_UINT(q);
|
|
if (u < 10)
|
|
wrote = PR_snprintf(p2, available, "%sutf-8;q=0.%u", comma, u);
|
|
else
|
|
wrote = PR_snprintf(p2, available, "%sutf-8", comma);
|
|
q -= dec;
|
|
p2 += wrote;
|
|
available -= wrote;
|
|
NS_ASSERTION(available > 0, "allocated string not long enough");
|
|
}
|
|
if (add_asterisk) {
|
|
comma = n++ != 0 ? "," : ""; // delimiter if not first item
|
|
|
|
// keep q of "*" equal to the lowest q value
|
|
// in the event of a tie between the q of "*" and a non-wildcard
|
|
// the non-wildcard always receives preference.
|
|
|
|
q += dec;
|
|
u = QVAL_TO_UINT(q);
|
|
if (u < 10)
|
|
wrote = PR_snprintf(p2, available, "%s*;q=0.%u", comma, u);
|
|
else
|
|
wrote = PR_snprintf(p2, available, "%s*", comma);
|
|
available -= wrote;
|
|
p2 += wrote;
|
|
NS_ASSERTION(available > 0, "allocated string not long enough");
|
|
}
|
|
nsCRT::free(o_Accept);
|
|
|
|
// change alloc from C++ new/delete to nsCRT::strdup's way
|
|
o_AcceptCharset.Assign(q_Accept);
|
|
#if defined DEBUG_havill
|
|
printf("Accept-Charset: %s\n", q_Accept);
|
|
#endif
|
|
delete [] q_Accept;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::SetAcceptCharsets(const char *aAcceptCharsets)
|
|
{
|
|
nsCString buf;
|
|
nsresult rv = PrepareAcceptCharsets(aAcceptCharsets, buf);
|
|
if (NS_SUCCEEDED(rv))
|
|
mAcceptCharsets.Assign(buf);
|
|
return rv;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::SetAccept(const char *aAccept)
|
|
{
|
|
mAccept = aAccept;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings)
|
|
{
|
|
mAcceptEncodings = aAcceptEncodings;
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsHttpHandler::nsISupports
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS5(nsHttpHandler,
|
|
nsIHttpProtocolHandler,
|
|
nsIProxiedProtocolHandler,
|
|
nsIProtocolHandler,
|
|
nsIObserver,
|
|
nsISupportsWeakReference)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsHttpHandler::nsIProtocolHandler
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetScheme(nsACString &aScheme)
|
|
{
|
|
aScheme.AssignLiteral("http");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetDefaultPort(PRInt32 *result)
|
|
{
|
|
*result = NS_HTTP_DEFAULT_PORT;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetProtocolFlags(PRUint32 *result)
|
|
{
|
|
*result = NS_HTTP_PROTOCOL_FLAGS;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::NewURI(const nsACString &aSpec,
|
|
const char *aCharset,
|
|
nsIURI *aBaseURI,
|
|
nsIURI **aURI)
|
|
{
|
|
LOG(("nsHttpHandler::NewURI\n"));
|
|
return ::NewURI(aSpec, aCharset, aBaseURI, NS_HTTP_DEFAULT_PORT, aURI);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
|
|
{
|
|
LOG(("nsHttpHandler::NewChannel\n"));
|
|
|
|
NS_ENSURE_ARG_POINTER(uri);
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
PRBool isHttp = PR_FALSE, isHttps = PR_FALSE;
|
|
|
|
// Verify that we have been given a valid scheme
|
|
nsresult rv = uri->SchemeIs("http", &isHttp);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!isHttp) {
|
|
rv = uri->SchemeIs("https", &isHttps);
|
|
if (NS_FAILED(rv)) return rv;
|
|
if (!isHttps) {
|
|
NS_WARNING("Invalid URI scheme");
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
}
|
|
|
|
return NewProxiedChannel(uri, nsnull, result);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval)
|
|
{
|
|
// don't override anything.
|
|
*_retval = PR_FALSE;
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsHttpHandler::nsIProxiedProtocolHandler
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
|
nsIProxyInfo* givenProxyInfo,
|
|
nsIChannel **result)
|
|
{
|
|
nsRefPtr<HttpBaseChannel> httpChannel;
|
|
|
|
LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
|
|
givenProxyInfo));
|
|
|
|
nsCOMPtr<nsProxyInfo> proxyInfo;
|
|
if (givenProxyInfo) {
|
|
proxyInfo = do_QueryInterface(givenProxyInfo);
|
|
NS_ENSURE_ARG(proxyInfo);
|
|
}
|
|
|
|
PRBool https;
|
|
nsresult rv = uri->SchemeIs("https", &https);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
#ifdef MOZ_IPC
|
|
if (IsNeckoChild()) {
|
|
httpChannel = new HttpChannelChild();
|
|
} else
|
|
#endif
|
|
{
|
|
httpChannel = new nsHttpChannel();
|
|
}
|
|
|
|
// select proxy caps if using a non-transparent proxy. SSL tunneling
|
|
// should not use proxy settings.
|
|
PRInt8 caps;
|
|
if (proxyInfo && !nsCRT::strcmp(proxyInfo->Type(), "http") && !https)
|
|
caps = mProxyCapabilities;
|
|
else
|
|
caps = mCapabilities;
|
|
|
|
if (https) {
|
|
// enable pipelining over SSL if requested
|
|
if (mPipeliningOverSSL)
|
|
caps |= NS_HTTP_ALLOW_PIPELINING;
|
|
|
|
#ifdef MOZ_IPC
|
|
if (!IsNeckoChild())
|
|
#endif
|
|
{
|
|
// HACK: make sure PSM gets initialized on the main thread.
|
|
nsCOMPtr<nsISocketProviderService> spserv =
|
|
do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID);
|
|
if (spserv) {
|
|
nsCOMPtr<nsISocketProvider> provider;
|
|
spserv->GetSocketProvider("ssl", getter_AddRefs(provider));
|
|
}
|
|
}
|
|
}
|
|
|
|
rv = httpChannel->Init(uri, caps, proxyInfo);
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
httpChannel.forget(result);
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsHttpHandler::nsIHttpProtocolHandler
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetUserAgent(nsACString &value)
|
|
{
|
|
value = UserAgent();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetAppName(nsACString &value)
|
|
{
|
|
value = mLegacyAppName;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetAppVersion(nsACString &value)
|
|
{
|
|
value = mLegacyAppVersion;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetProduct(nsACString &value)
|
|
{
|
|
value = mProduct;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetProductSub(nsACString &value)
|
|
{
|
|
value = mProductSub;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetPlatform(nsACString &value)
|
|
{
|
|
value = mPlatform;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetOscpu(nsACString &value)
|
|
{
|
|
value = mOscpu;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetLanguage(nsACString &value)
|
|
{
|
|
value = mLanguage;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::GetMisc(nsACString &value)
|
|
{
|
|
value = mMisc;
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsHttpHandler::nsIObserver
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpHandler::Observe(nsISupports *subject,
|
|
const char *topic,
|
|
const PRUnichar *data)
|
|
{
|
|
LOG(("nsHttpHandler::Observe [topic=\"%s\"]\n", topic));
|
|
|
|
if (strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
|
|
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
|
|
if (prefBranch)
|
|
PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
|
|
}
|
|
else if (strcmp(topic, "profile-change-net-teardown") == 0 ||
|
|
strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
|
|
|
// clear cache of all authentication credentials.
|
|
mAuthCache.ClearAll();
|
|
|
|
// ensure connection manager is shutdown
|
|
if (mConnMgr)
|
|
mConnMgr->Shutdown();
|
|
|
|
// need to reset the session start time since cache validation may
|
|
// depend on this value.
|
|
mSessionStartTime = NowInSeconds();
|
|
}
|
|
else if (strcmp(topic, "profile-change-net-restore") == 0) {
|
|
// initialize connection manager
|
|
InitConnectionMgr();
|
|
}
|
|
else if (strcmp(topic, "net:clear-active-logins") == 0) {
|
|
mAuthCache.ClearAll();
|
|
}
|
|
else if (strcmp(topic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
|
|
if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(data))
|
|
mInPrivateBrowsingMode = PR_TRUE;
|
|
else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(data))
|
|
mInPrivateBrowsingMode = PR_FALSE;
|
|
}
|
|
else if (strcmp(topic, "net:prune-dead-connections") == 0) {
|
|
if (mConnMgr) {
|
|
mConnMgr->PruneDeadConnections();
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsHttpsHandler implementation
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS4(nsHttpsHandler,
|
|
nsIHttpProtocolHandler,
|
|
nsIProxiedProtocolHandler,
|
|
nsIProtocolHandler,
|
|
nsISupportsWeakReference)
|
|
|
|
nsresult
|
|
nsHttpsHandler::Init()
|
|
{
|
|
nsCOMPtr<nsIProtocolHandler> httpHandler(
|
|
do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http"));
|
|
NS_ASSERTION(httpHandler.get() != nsnull, "no http handler?");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpsHandler::GetScheme(nsACString &aScheme)
|
|
{
|
|
aScheme.AssignLiteral("https");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpsHandler::GetDefaultPort(PRInt32 *aPort)
|
|
{
|
|
*aPort = NS_HTTPS_DEFAULT_PORT;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpsHandler::GetProtocolFlags(PRUint32 *aProtocolFlags)
|
|
{
|
|
*aProtocolFlags = NS_HTTP_PROTOCOL_FLAGS;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpsHandler::NewURI(const nsACString &aSpec,
|
|
const char *aOriginCharset,
|
|
nsIURI *aBaseURI,
|
|
nsIURI **_retval)
|
|
{
|
|
return ::NewURI(aSpec, aOriginCharset, aBaseURI, NS_HTTPS_DEFAULT_PORT, _retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpsHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
|
|
{
|
|
NS_ABORT_IF_FALSE(gHttpHandler, "Should have a HTTP handler by now.");
|
|
if (!gHttpHandler)
|
|
return NS_ERROR_UNEXPECTED;
|
|
return gHttpHandler->NewChannel(aURI, _retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHttpsHandler::AllowPort(PRInt32 aPort, const char *aScheme, PRBool *_retval)
|
|
{
|
|
// don't override anything.
|
|
*_retval = PR_FALSE;
|
|
return NS_OK;
|
|
}
|