2001-05-11 21:04:09 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* 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 Netscape Communications are
|
|
|
|
* Copyright (C) 2001 by Netscape Communications. 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>
|
2001-05-17 00:17:34 +00:00
|
|
|
* Gervase Markham <gerv@gerv.net>
|
2001-07-17 20:22:19 +00:00
|
|
|
* Bradley Baetz <bbaetz@netscape.com>
|
2001-05-11 21:04:09 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nsHttp.h"
|
|
|
|
#include "nsHttpHandler.h"
|
|
|
|
#include "nsHttpChannel.h"
|
|
|
|
#include "nsHttpConnection.h"
|
|
|
|
#include "nsHttpResponseHead.h"
|
|
|
|
#include "nsHttpTransaction.h"
|
|
|
|
#include "nsHttpAuthCache.h"
|
2002-04-19 22:25:23 +00:00
|
|
|
#include "nsHttpPipeline.h"
|
2002-10-06 02:20:35 +00:00
|
|
|
#include "nsStandardURL.h"
|
2001-05-11 21:04:09 +00:00
|
|
|
#include "nsIHttpChannel.h"
|
|
|
|
#include "nsIHttpNotify.h"
|
|
|
|
#include "nsIURL.h"
|
2002-03-06 07:48:55 +00:00
|
|
|
#include "nsIStandardURL.h"
|
2001-05-11 21:04:09 +00:00
|
|
|
#include "nsICacheService.h"
|
|
|
|
#include "nsICategoryManager.h"
|
2002-07-18 05:09:10 +00:00
|
|
|
#include "nsCategoryManagerUtils.h"
|
2001-05-11 21:04:09 +00:00
|
|
|
#include "nsIObserverService.h"
|
|
|
|
#include "nsINetModRegEntry.h"
|
|
|
|
#include "nsICacheService.h"
|
2001-09-27 21:26:59 +00:00
|
|
|
#include "nsIPrefService.h"
|
|
|
|
#include "nsIPrefBranchInternal.h"
|
|
|
|
#include "nsIPrefLocalizedString.h"
|
2002-09-06 06:36:17 +00:00
|
|
|
#include "nsISocketProviderService.h"
|
|
|
|
#include "nsISocketProvider.h"
|
2001-05-11 21:04:09 +00:00
|
|
|
#include "nsPrintfCString.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsNetCID.h"
|
2001-06-11 21:20:29 +00:00
|
|
|
#include "nsAutoLock.h"
|
2001-05-11 21:04:09 +00:00
|
|
|
#include "prprf.h"
|
2001-06-17 05:23:38 +00:00
|
|
|
#include "nsReadableUtils.h"
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
#if defined(XP_UNIX) || defined(XP_BEOS)
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(XP_PC) && !defined(XP_OS2)
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2001-08-30 02:58:03 +00:00
|
|
|
#if defined(XP_MAC)
|
|
|
|
#include <Gestalt.h>
|
|
|
|
#endif
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
// defined by the socket transport service while active
|
|
|
|
extern PRThread *NS_SOCKET_THREAD;
|
|
|
|
#endif
|
|
|
|
|
2001-06-06 00:10:09 +00:00
|
|
|
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
2001-05-11 21:04:09 +00:00
|
|
|
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
|
|
|
|
static NS_DEFINE_CID(kNetModuleMgrCID, NS_NETMODULEMGR_CID);
|
|
|
|
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
|
|
|
|
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
|
|
|
|
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
2002-09-06 06:36:17 +00:00
|
|
|
static NS_DEFINE_CID(kSocketProviderServiceCID, NS_SOCKETPROVIDERSERVICE_CID);
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
#define UA_PREF_PREFIX "general.useragent."
|
|
|
|
#define UA_APPNAME "Mozilla"
|
|
|
|
#define UA_APPVERSION "5.0"
|
2001-05-11 21:04:09 +00:00
|
|
|
#define UA_APPSECURITY_FALLBACK "N"
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
#define HTTP_PREF_PREFIX "network.http."
|
|
|
|
#define INTL_ACCEPT_LANGUAGES "intl.accept_languages"
|
|
|
|
#define INTL_ACCEPT_CHARSET "intl.charset.default"
|
2001-10-05 07:50:21 +00:00
|
|
|
#define NETWORK_ENABLEIDN "network.enableIDN"
|
2001-09-27 21:26:59 +00:00
|
|
|
|
|
|
|
#define UA_PREF(_pref) UA_PREF_PREFIX _pref
|
|
|
|
#define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsHttpHandler <public>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
nsHttpHandler *nsHttpHandler::mGlobalInstance = 0;
|
|
|
|
|
|
|
|
nsHttpHandler::nsHttpHandler()
|
|
|
|
: mAuthCache(nsnull)
|
|
|
|
, mHttpVersion(NS_HTTP_VERSION_1_1)
|
2002-04-18 22:36:39 +00:00
|
|
|
, mProxyHttpVersion(NS_HTTP_VERSION_1_1)
|
2001-08-14 01:03:27 +00:00
|
|
|
, mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
|
|
|
, mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
2002-04-18 22:36:39 +00:00
|
|
|
, mReferrerLevel(0xff) // by default we always send a referrer
|
2001-05-11 21:04:09 +00:00
|
|
|
, mIdleTimeout(10)
|
2001-08-14 01:03:27 +00:00
|
|
|
, mMaxRequestAttempts(10)
|
2001-09-04 23:02:26 +00:00
|
|
|
, mMaxRequestDelay(10)
|
|
|
|
, mMaxConnections(24)
|
2001-05-11 21:04:09 +00:00
|
|
|
, mMaxConnectionsPerServer(8)
|
2001-09-04 23:02:26 +00:00
|
|
|
, mMaxPersistentConnectionsPerServer(2)
|
2001-11-04 05:46:06 +00:00
|
|
|
, mMaxPersistentConnectionsPerProxy(4)
|
2002-04-19 22:25:23 +00:00
|
|
|
, mMaxPipelinedRequests(2)
|
2001-12-08 00:23:04 +00:00
|
|
|
, mRedirectionLimit(10)
|
2001-10-22 23:24:26 +00:00
|
|
|
, mLastUniqueID(NowInSeconds())
|
|
|
|
, mSessionStartTime(0)
|
2001-05-11 21:04:09 +00:00
|
|
|
, mActiveConnections(0)
|
|
|
|
, mIdleConnections(0)
|
|
|
|
, mTransactionQ(0)
|
2001-10-22 23:24:26 +00:00
|
|
|
, mConnectionLock(nsnull)
|
2001-05-11 21:04:09 +00:00
|
|
|
, mUserAgentIsDirty(PR_TRUE)
|
2001-10-02 00:40:27 +00:00
|
|
|
, mUseCache(PR_TRUE)
|
2002-09-13 22:21:57 +00:00
|
|
|
, mSendSecureXSiteReferrer(PR_TRUE)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
|
|
|
NS_INIT_ISUPPORTS();
|
|
|
|
|
|
|
|
#if defined(PR_LOGGING)
|
|
|
|
gHttpLog = PR_NewLogModule("nsHttp");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOG(("Creating nsHttpHandler [this=%x].\n", this));
|
|
|
|
|
|
|
|
NS_ASSERTION(!mGlobalInstance, "HTTP handler already created!");
|
|
|
|
mGlobalInstance = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsHttpHandler::~nsHttpHandler()
|
|
|
|
{
|
2001-12-07 01:40:18 +00:00
|
|
|
// We do not deal with the timer cancellation in the destructor since
|
|
|
|
// it is taken care of in xpcom shutdown event in the Observe method.
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
LOG(("Deleting nsHttpHandler [this=%x]\n", this));
|
|
|
|
|
|
|
|
nsHttp::DestroyAtomTable();
|
|
|
|
|
2002-11-06 13:01:42 +00:00
|
|
|
// If the |nsHttpConnection| objects stop holding references to this
|
|
|
|
// object (as was done to fix bug 143821), then the code from
|
|
|
|
// |Observe| to call |DropConnections| should probably move back
|
|
|
|
// here.
|
|
|
|
NS_ASSERTION(!mActiveConnections.Count() && !mIdleConnections.Count(),
|
|
|
|
"Connections should own reference to nsHttpHandler");
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
if (mAuthCache) {
|
|
|
|
delete mAuthCache;
|
|
|
|
mAuthCache = nsnull;
|
|
|
|
}
|
|
|
|
|
2001-06-11 21:20:29 +00:00
|
|
|
if (mConnectionLock) {
|
|
|
|
PR_DestroyLock(mConnectionLock);
|
|
|
|
mConnectionLock = nsnull;
|
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
mGlobalInstance = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHttpHandler::Init()
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
LOG(("nsHttpHandler::Init\n"));
|
|
|
|
|
2001-06-06 00:10:09 +00:00
|
|
|
mIOService = do_GetService(kIOServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("unable to continue without io service");
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2001-06-11 21:20:29 +00:00
|
|
|
mConnectionLock = PR_NewLock();
|
|
|
|
if (!mConnectionLock)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
InitUserAgentComponents();
|
|
|
|
|
|
|
|
// monitor some preference changes
|
2001-10-02 00:40:27 +00:00
|
|
|
nsCOMPtr<nsIPrefBranch> prefBranch;
|
|
|
|
GetPrefBranch(getter_AddRefs(prefBranch));
|
|
|
|
if (prefBranch) {
|
|
|
|
nsCOMPtr<nsIPrefBranchInternal> pbi = do_QueryInterface(prefBranch);
|
|
|
|
if (pbi) {
|
2001-10-22 20:54:48 +00:00
|
|
|
pbi->AddObserver(HTTP_PREF_PREFIX, this, PR_TRUE);
|
|
|
|
pbi->AddObserver(UA_PREF_PREFIX, this, PR_TRUE);
|
|
|
|
pbi->AddObserver(INTL_ACCEPT_LANGUAGES, this, PR_TRUE);
|
|
|
|
pbi->AddObserver(INTL_ACCEPT_CHARSET, this, PR_TRUE);
|
|
|
|
pbi->AddObserver(NETWORK_ENABLEIDN, this, PR_TRUE);
|
2001-10-02 00:40:27 +00:00
|
|
|
}
|
|
|
|
PrefsChanged(prefBranch);
|
2001-09-27 21:26:59 +00:00
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
#if DEBUG
|
|
|
|
// dump user agent prefs
|
|
|
|
LOG(("> app-name = %s\n", mAppName.get()));
|
|
|
|
LOG(("> app-version = %s\n", mAppVersion.get()));
|
|
|
|
LOG(("> platform = %s\n", mPlatform.get()));
|
|
|
|
LOG(("> oscpu = %s\n", mOscpu.get()));
|
|
|
|
LOG(("> security = %s\n", mSecurity.get()));
|
|
|
|
LOG(("> language = %s\n", mLanguage.get()));
|
|
|
|
LOG(("> misc = %s\n", mMisc.get()));
|
|
|
|
LOG(("> vendor = %s\n", mVendor.get()));
|
|
|
|
LOG(("> vendor-sub = %s\n", mVendorSub.get()));
|
|
|
|
LOG(("> vendor-comment = %s\n", mVendorComment.get()));
|
|
|
|
LOG(("> product = %s\n", mProduct.get()));
|
|
|
|
LOG(("> product-sub = %s\n", mProductSub.get()));
|
|
|
|
LOG(("> product-comment = %s\n", mProductComment.get()));
|
2002-03-20 22:50:33 +00:00
|
|
|
LOG(("> user-agent = %s\n", UserAgent().get()));
|
2001-09-27 21:26:59 +00:00
|
|
|
#endif
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
mSessionStartTime = NowInSeconds();
|
|
|
|
|
|
|
|
mAuthCache = new nsHttpAuthCache();
|
|
|
|
if (!mAuthCache)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
rv = mAuthCache->Init();
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
// Startup the http category
|
|
|
|
// Bring alive the objects in the http-protocol-startup category
|
2001-08-28 22:22:27 +00:00
|
|
|
NS_CreateServicesFromCategory(NS_HTTP_STARTUP_CATEGORY,
|
|
|
|
NS_STATIC_CAST(nsISupports*,NS_STATIC_CAST(void*,this)),
|
2001-10-19 20:52:59 +00:00
|
|
|
NS_HTTP_STARTUP_TOPIC);
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIObserverService> observerSvc =
|
2001-10-22 22:01:27 +00:00
|
|
|
do_GetService("@mozilla.org/observer-service;1", &rv);
|
2001-09-21 05:04:25 +00:00
|
|
|
if (observerSvc) {
|
2002-10-14 14:42:13 +00:00
|
|
|
observerSvc->AddObserver(this, "profile-change-net-teardown", PR_TRUE);
|
2001-10-19 20:52:59 +00:00
|
|
|
observerSvc->AddObserver(this, "session-logout", PR_TRUE);
|
2001-12-07 01:40:18 +00:00
|
|
|
observerSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_TRUE);
|
2001-09-21 05:04:25 +00:00
|
|
|
}
|
2001-12-07 01:40:18 +00:00
|
|
|
|
|
|
|
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
// failure to create a timer is not a fatal error, but idle connections
|
|
|
|
// may not be cleaned up as aggressively.
|
|
|
|
if (mTimer)
|
2002-09-07 05:38:16 +00:00
|
|
|
mTimer->InitWithFuncCallback(DeadConnectionCleanupCB, this, 15*1000, // 15 seconds
|
|
|
|
nsITimer::TYPE_REPEATING_SLACK);
|
2001-12-07 01:40:18 +00:00
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
2001-08-14 01:03:27 +00:00
|
|
|
PRUint8 caps,
|
2001-07-17 20:22:19 +00:00
|
|
|
PRBool useProxy)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
LOG(("nsHttpHandler::AddStandardRequestHeaders\n"));
|
|
|
|
|
2001-07-17 20:22:19 +00:00
|
|
|
// Add the "User-Agent" header
|
2001-05-11 21:04:09 +00:00
|
|
|
rv = request->SetHeader(nsHttp::User_Agent, UserAgent());
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2001-05-17 00:17:34 +00:00
|
|
|
// MIME based content negotiation lives!
|
2001-07-17 20:22:19 +00:00
|
|
|
// Add the "Accept" header
|
2002-03-20 22:50:33 +00:00
|
|
|
rv = request->SetHeader(nsHttp::Accept, mAccept);
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2001-07-17 20:22:19 +00:00
|
|
|
// Add the "Accept-Language" header
|
2001-08-14 02:45:05 +00:00
|
|
|
if (!mAcceptLanguages.IsEmpty()) {
|
|
|
|
// Add the "Accept-Language" header
|
2002-03-20 22:50:33 +00:00
|
|
|
rv = request->SetHeader(nsHttp::Accept_Language, mAcceptLanguages);
|
2001-08-14 02:45:05 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-07-17 20:22:19 +00:00
|
|
|
// Add the "Accept-Encoding" header
|
2002-03-20 22:50:33 +00:00
|
|
|
rv = request->SetHeader(nsHttp::Accept_Encoding, mAcceptEncodings);
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2001-07-17 20:22:19 +00:00
|
|
|
// Add the "Accept-Charset" header
|
2002-03-20 22:50:33 +00:00
|
|
|
rv = request->SetHeader(nsHttp::Accept_Charset, mAcceptCharsets);
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2001-07-17 20:22:19 +00:00
|
|
|
// 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.
|
2001-08-14 01:03:27 +00:00
|
|
|
//
|
2001-07-17 20:22:19 +00:00
|
|
|
// However, we need to send something so that we can use keepalive
|
2001-08-14 01:03:27 +00:00
|
|
|
// with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when
|
|
|
|
// we're talking to an http proxy, and "Connection:" otherwise
|
2001-07-17 20:22:19 +00:00
|
|
|
|
|
|
|
const char* connectionType = "close";
|
2001-08-14 01:03:27 +00:00
|
|
|
if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
|
2002-03-20 22:50:33 +00:00
|
|
|
rv = request->SetHeader(nsHttp::Keep_Alive, nsPrintfCString("%u", mIdleTimeout));
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
connectionType = "keep-alive";
|
2001-08-10 22:04:51 +00:00
|
|
|
} else if (useProxy) {
|
|
|
|
// Bug 92006
|
2002-03-20 22:50:33 +00:00
|
|
|
request->SetHeader(nsHttp::Connection, NS_LITERAL_CSTRING("close"));
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
2001-07-17 20:22:19 +00:00
|
|
|
|
2001-08-14 01:03:27 +00:00
|
|
|
const nsHttpAtom &header =
|
|
|
|
useProxy ? nsHttp::Proxy_Connection : nsHttp::Connection;
|
2002-03-20 22:50:33 +00:00
|
|
|
return request->SetHeader(header, nsDependentCString(connectionType));
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2001-06-19 00:25:02 +00:00
|
|
|
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;
|
|
|
|
|
2001-10-24 23:47:43 +00:00
|
|
|
return PL_strcasestr(mAcceptEncodings.get(), enc) != nsnull;
|
2001-06-19 00:25:02 +00:00
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy,
|
|
|
|
nsICacheSession **result)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// Skip cache if disabled in preferences
|
2001-10-02 00:40:27 +00:00
|
|
|
if (!mUseCache)
|
2001-05-11 21:04:09 +00:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
|
|
|
|
if (!mCacheSession_ANY) {
|
|
|
|
nsCOMPtr<nsICacheService> serv = do_GetService(kCacheServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = serv->CreateSession("HTTP",
|
|
|
|
nsICache::STORE_ANYWHERE,
|
|
|
|
nsICache::STREAM_BASED,
|
|
|
|
getter_AddRefs(mCacheSession_ANY));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = mCacheSession_ANY->SetDoomEntriesIfExpired(PR_FALSE);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = serv->CreateSession("HTTP-memory-only",
|
|
|
|
nsICache::STORE_IN_MEMORY,
|
|
|
|
nsICache::STREAM_BASED,
|
|
|
|
getter_AddRefs(mCacheSession_MEM));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = mCacheSession_MEM->SetDoomEntriesIfExpired(PR_FALSE);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (storagePolicy == nsICache::STORE_IN_MEMORY)
|
|
|
|
NS_ADDREF(*result = mCacheSession_MEM);
|
|
|
|
else
|
|
|
|
NS_ADDREF(*result = mCacheSession_ANY);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-06-11 21:20:29 +00:00
|
|
|
// may be called from any thread
|
2001-05-11 21:04:09 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::InitiateTransaction(nsHttpTransaction *trans,
|
2001-09-04 23:02:26 +00:00
|
|
|
nsHttpConnectionInfo *ci)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
|
|
|
LOG(("nsHttpHandler::InitiateTransaction\n"));
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(trans);
|
|
|
|
NS_ENSURE_ARG_POINTER(ci);
|
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
PR_Lock(mConnectionLock);
|
|
|
|
|
|
|
|
nsHttpConnection *conn = nsnull;
|
|
|
|
nsresult rv;
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
GetConnection_Locked(ci, trans->Capabilities(), &conn);
|
|
|
|
if (!conn) {
|
|
|
|
rv = EnqueueTransaction_Locked(trans, ci);
|
|
|
|
PR_Unlock(mConnectionLock);
|
|
|
|
}
|
|
|
|
else {
|
2002-04-19 22:25:23 +00:00
|
|
|
rv = DispatchTransaction_Locked(trans, trans->Capabilities(), conn);
|
2001-12-06 02:21:03 +00:00
|
|
|
NS_RELEASE(conn);
|
|
|
|
}
|
|
|
|
return rv;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
// called from the socket thread
|
2001-05-11 21:04:09 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::ReclaimConnection(nsHttpConnection *conn)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(conn);
|
2002-04-19 22:25:23 +00:00
|
|
|
NS_ASSERTION(PR_GetCurrentThread() == NS_SOCKET_THREAD, "wrong thread");
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-06-20 01:21:43 +00:00
|
|
|
PRBool reusable = conn->CanReuse();
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
LOG(("nsHttpHandler::ReclaimConnection [conn=%x(%s:%d) keep-alive=%d]\n",
|
|
|
|
conn, conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port(), reusable));
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
PR_Lock(mConnectionLock);
|
2001-06-11 21:20:29 +00:00
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
// remove connection from the active connection list
|
|
|
|
mActiveConnections.RemoveElement(conn);
|
|
|
|
|
2001-06-20 01:21:43 +00:00
|
|
|
if (reusable) {
|
2001-09-04 23:02:26 +00:00
|
|
|
LOG(("adding connection to idle list [conn=%x]\n", conn));
|
|
|
|
// hold onto this connection in the idle list. we push it
|
|
|
|
// to the end of the list so as to ensure that we'll visit
|
|
|
|
// older connections first before getting to this one.
|
|
|
|
mIdleConnections.AppendElement(conn);
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
LOG(("closing connection: connection can't be reused\n"));
|
|
|
|
NS_RELEASE(conn);
|
|
|
|
}
|
|
|
|
|
2001-06-20 01:21:43 +00:00
|
|
|
LOG(("active connection count is now %u\n", mActiveConnections.Count()));
|
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
ProcessTransactionQ_Locked();
|
2001-09-04 23:02:26 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-12-07 01:40:18 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::PurgeDeadConnections()
|
|
|
|
{
|
|
|
|
nsAutoLock lock(mConnectionLock);
|
2002-11-06 13:01:42 +00:00
|
|
|
// Loop from end to beginning because of |RemoveElement| calls.
|
|
|
|
for (PRInt32 i = mIdleConnections.Count() - 1; i >= 0; --i) {
|
2001-12-07 01:40:18 +00:00
|
|
|
nsHttpConnection *conn = (nsHttpConnection *) mIdleConnections[i];
|
|
|
|
if (conn && !conn->CanReuse()) {
|
|
|
|
// Dead and idle connection; purge it
|
2002-11-06 13:01:42 +00:00
|
|
|
mIdleConnections.RemoveElementAt(i);
|
2001-12-07 01:40:18 +00:00
|
|
|
NS_RELEASE(conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
// called from the socket thread (see nsHttpConnection::OnDataAvailable)
|
|
|
|
nsresult
|
|
|
|
nsHttpHandler::ProcessTransactionQ()
|
|
|
|
{
|
|
|
|
LOG(("nsHttpHandler::ProcessTransactionQ\n"));
|
2002-04-19 22:25:23 +00:00
|
|
|
NS_ASSERTION(PR_GetCurrentThread() == NS_SOCKET_THREAD, "wrong thread");
|
2001-09-04 23:02:26 +00:00
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
PR_Lock(mConnectionLock);
|
2001-09-04 23:02:26 +00:00
|
|
|
|
|
|
|
// conn is no longer keep-alive, so we may be able to initiate
|
|
|
|
// a pending transaction to the same host.
|
2001-12-06 02:21:03 +00:00
|
|
|
ProcessTransactionQ_Locked();
|
2001-05-11 21:04:09 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-06-14 20:52:03 +00:00
|
|
|
// called from any thread, by the implementation of nsHttpTransaction::Cancel
|
2001-05-11 21:04:09 +00:00
|
|
|
nsresult
|
2001-06-14 20:52:03 +00:00
|
|
|
nsHttpHandler::CancelTransaction(nsHttpTransaction *trans, nsresult status)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2001-10-02 00:31:30 +00:00
|
|
|
nsAHttpConnection *conn;
|
2001-06-20 01:21:43 +00:00
|
|
|
|
2001-06-14 20:52:03 +00:00
|
|
|
LOG(("nsHttpHandler::CancelTransaction [trans=%x status=%x]\n",
|
2001-05-11 21:04:09 +00:00
|
|
|
trans, status));
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(trans);
|
|
|
|
|
2001-06-14 20:52:03 +00:00
|
|
|
// we need to be inside the connection lock in order to know whether
|
|
|
|
// or not this transaction has an associated connection. otherwise,
|
|
|
|
// we'd have a race condition (see bug 85822).
|
2001-06-20 01:21:43 +00:00
|
|
|
{
|
|
|
|
nsAutoLock lock(mConnectionLock);
|
|
|
|
|
|
|
|
conn = trans->Connection();
|
|
|
|
if (conn)
|
|
|
|
NS_ADDREF(conn); // make sure the connection stays around.
|
|
|
|
else
|
2001-12-06 02:21:03 +00:00
|
|
|
RemovePendingTransaction_Locked(trans);
|
2001-06-20 01:21:43 +00:00
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-06-20 01:21:43 +00:00
|
|
|
if (conn) {
|
|
|
|
conn->OnTransactionComplete(trans, status);
|
|
|
|
NS_RELEASE(conn);
|
|
|
|
}
|
2001-06-14 20:52:03 +00:00
|
|
|
else
|
2001-06-20 01:21:43 +00:00
|
|
|
trans->OnStopTransaction(status);
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-06-14 20:52:03 +00:00
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHttpHandler::GetProxyObjectManager(nsIProxyObjectManager **result)
|
|
|
|
{
|
|
|
|
if (!mProxyMgr) {
|
|
|
|
nsresult rv;
|
|
|
|
mProxyMgr = do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
*result = mProxyMgr;
|
|
|
|
NS_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHttpHandler::GetEventQueueService(nsIEventQueueService **result)
|
|
|
|
{
|
|
|
|
if (!mEventQueueService) {
|
|
|
|
nsresult rv;
|
|
|
|
mEventQueueService = do_GetService(kEventQueueServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
*result = mEventQueueService;
|
|
|
|
NS_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
|
|
|
|
{
|
|
|
|
if (!mStreamConvSvc) {
|
|
|
|
nsresult rv;
|
|
|
|
mStreamConvSvc = do_GetService(kStreamConverterServiceCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
*result = mStreamConvSvc;
|
|
|
|
NS_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-05-15 17:47:51 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::GetMimeService(nsIMIMEService **result)
|
|
|
|
{
|
|
|
|
if (!mMimeService) {
|
|
|
|
nsresult rv;
|
2002-01-27 06:03:39 +00:00
|
|
|
mMimeService = do_GetService("@mozilla.org/mime;1", &rv);
|
2001-05-15 17:47:51 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
*result = mMimeService;
|
|
|
|
NS_ADDREF(*result);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-06-06 00:10:09 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::GetIOService(nsIIOService** result)
|
|
|
|
{
|
|
|
|
NS_ADDREF(*result = mIOService);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::OnModifyRequest(nsIHttpChannel *chan)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
LOG(("nsHttpHandler::OnModifyRequest [chan=%x]\n", chan));
|
|
|
|
|
|
|
|
if (!mNetModuleMgr) {
|
|
|
|
mNetModuleMgr = do_GetService(kNetModuleMgrCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> modules;
|
|
|
|
rv = mNetModuleMgr->EnumerateModules(
|
|
|
|
NS_NETWORK_MODULE_MANAGER_HTTP_REQUEST_CONTRACTID,
|
|
|
|
getter_AddRefs(modules));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> sup;
|
|
|
|
|
|
|
|
// notify each module...
|
|
|
|
while (NS_SUCCEEDED(modules->GetNext(getter_AddRefs(sup)))) {
|
|
|
|
nsCOMPtr<nsINetModRegEntry> entry = do_QueryInterface(sup, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsINetNotify> netNotify;
|
|
|
|
rv = entry->GetSyncProxy(getter_AddRefs(netNotify));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIHttpNotify> httpNotify = do_QueryInterface(netNotify, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
// fire off the notification, ignore the return code.
|
|
|
|
httpNotify->OnModifyRequest(chan);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHttpHandler::OnExamineResponse(nsIHttpChannel *chan)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
LOG(("nsHttpHandler::OnExamineResponse [chan=%x]\n", chan));
|
|
|
|
|
|
|
|
if (!mNetModuleMgr) {
|
|
|
|
mNetModuleMgr = do_GetService(kNetModuleMgrCID, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsISimpleEnumerator> modules;
|
|
|
|
rv = mNetModuleMgr->EnumerateModules(
|
|
|
|
NS_NETWORK_MODULE_MANAGER_HTTP_RESPONSE_CONTRACTID,
|
|
|
|
getter_AddRefs(modules));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> sup;
|
|
|
|
nsCOMPtr<nsINetModRegEntry> entry;
|
|
|
|
nsCOMPtr<nsINetNotify> netNotify;
|
|
|
|
nsCOMPtr<nsIHttpNotify> httpNotify;
|
|
|
|
|
|
|
|
// notify each module...
|
|
|
|
while (NS_SUCCEEDED(modules->GetNext(getter_AddRefs(sup)))) {
|
|
|
|
entry = do_QueryInterface(sup, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
rv = entry->GetSyncProxy(getter_AddRefs(netNotify));
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
httpNotify = do_QueryInterface(netNotify, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
// fire off the notification, ignore the return code.
|
|
|
|
httpNotify->OnExamineResponse(chan);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsHttpHandler <private>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2002-03-20 22:50:33 +00:00
|
|
|
const nsAFlatCString &
|
2001-05-11 21:04:09 +00:00
|
|
|
nsHttpHandler::UserAgent()
|
|
|
|
{
|
2001-09-27 21:26:59 +00:00
|
|
|
if (mUserAgentOverride) {
|
|
|
|
LOG(("using general.useragent.override : %s\n", mUserAgentOverride.get()));
|
2002-03-20 22:50:33 +00:00
|
|
|
return mUserAgentOverride;
|
2001-09-27 21:26:59 +00:00
|
|
|
}
|
2001-05-18 22:45:34 +00:00
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
if (mUserAgentIsDirty) {
|
|
|
|
BuildUserAgent();
|
|
|
|
mUserAgentIsDirty = PR_FALSE;
|
|
|
|
}
|
2001-05-18 22:45:34 +00:00
|
|
|
|
2002-03-20 22:50:33 +00:00
|
|
|
return mUserAgent;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2001-06-11 21:20:29 +00:00
|
|
|
nsresult
|
2001-12-06 02:21:03 +00:00
|
|
|
nsHttpHandler::GetConnection_Locked(nsHttpConnectionInfo *ci,
|
|
|
|
PRUint8 caps,
|
|
|
|
nsHttpConnection **result)
|
2001-06-11 21:20:29 +00:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
LOG(("nsHttpHandler::GetConnection_Locked\n"));
|
2001-06-11 21:20:29 +00:00
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
*result = nsnull;
|
|
|
|
|
|
|
|
if (AtActiveConnectionLimit_Locked(ci, caps))
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-06-11 21:20:29 +00:00
|
|
|
|
|
|
|
nsHttpConnection *conn = nsnull;
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
|
|
|
|
// search the idle connection list
|
|
|
|
PRInt32 i;
|
|
|
|
for (i=0; i<mIdleConnections.Count(); ++i) {
|
|
|
|
conn = (nsHttpConnection *) mIdleConnections[i];
|
|
|
|
|
|
|
|
LOG((">> comparing against idle connection [conn=%x host=%s:%d]\n",
|
|
|
|
conn, conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port()));
|
|
|
|
|
|
|
|
// we check if the connection can be reused before even checking if it
|
|
|
|
// is a "matching" connection. this is how we keep the idle connection
|
|
|
|
// list fresh. we could alternatively use some sort of timer for this.
|
|
|
|
if (!conn->CanReuse()) {
|
|
|
|
LOG((" dropping stale connection: [conn=%x]\n", conn));
|
|
|
|
mIdleConnections.RemoveElementAt(i);
|
|
|
|
i--;
|
|
|
|
NS_RELEASE(conn);
|
|
|
|
}
|
|
|
|
else if (conn->ConnectionInfo()->Equals(ci)) {
|
|
|
|
LOG((" reusing connection [conn=%x]\n", conn));
|
|
|
|
mIdleConnections.RemoveElementAt(i);
|
|
|
|
i--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
conn = nsnull;
|
2001-06-11 21:20:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!conn) {
|
2001-09-04 23:02:26 +00:00
|
|
|
LOG((">> creating new connection...\n"));
|
2001-06-11 21:20:29 +00:00
|
|
|
NS_NEWXPCOM(conn, nsHttpConnection);
|
|
|
|
if (!conn)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(conn);
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
rv = conn->Init(ci, mMaxRequestDelay);
|
2001-06-20 01:21:43 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_RELEASE(conn);
|
|
|
|
return rv;
|
|
|
|
}
|
2002-02-22 14:02:40 +00:00
|
|
|
|
|
|
|
// We created a new connection
|
|
|
|
// If idle + active connections > max connections, then purge the oldest idle one.
|
|
|
|
if (mIdleConnections.Count() + mActiveConnections.Count() > mMaxConnections) {
|
|
|
|
LOG(("Created a new connection and popping oldest one [idlecount=%d activecount=%d maxConn=%d]\n",
|
|
|
|
mIdleConnections.Count(), mActiveConnections.Count(), mMaxConnections));
|
|
|
|
NS_ASSERTION(mIdleConnections.Count() > 0, "idle connection list is empty");
|
|
|
|
if (mIdleConnections.Count() > 0) {
|
|
|
|
nsHttpConnection *conn = (nsHttpConnection *) mIdleConnections[0];
|
|
|
|
NS_ASSERTION(conn, "mIdleConnections[0] is null but count > 0");
|
|
|
|
if (conn) {
|
|
|
|
LOG(("deleting connection [conn=%x host=%s:%d]\n",
|
|
|
|
conn, conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port()));
|
|
|
|
mIdleConnections.RemoveElementAt(0);
|
|
|
|
NS_RELEASE(conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-09-04 23:02:26 +00:00
|
|
|
}
|
|
|
|
else {
|
2001-08-10 22:04:51 +00:00
|
|
|
// Update the connectionInfo (bug 94038)
|
|
|
|
conn->ConnectionInfo()->SetOriginServer(ci->Host(), ci->Port());
|
2001-06-11 21:20:29 +00:00
|
|
|
}
|
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
*result = conn;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsHttpHandler::EnqueueTransaction_Locked(nsHttpTransaction *trans,
|
|
|
|
nsHttpConnectionInfo *ci)
|
|
|
|
{
|
|
|
|
LOG(("nsHttpHandler::EnqueueTransaction_Locked [trans=%x]\n", trans));
|
|
|
|
|
|
|
|
nsPendingTransaction *pt = new nsPendingTransaction(trans, ci);
|
|
|
|
if (!pt)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
mTransactionQ.AppendElement(pt);
|
|
|
|
|
|
|
|
LOG((">> transaction queue contains %u elements\n", mTransactionQ.Count()));
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dispatch this transaction, return unlocked
|
|
|
|
nsresult
|
2002-04-19 22:25:23 +00:00
|
|
|
nsHttpHandler::DispatchTransaction_Locked(nsAHttpTransaction *trans,
|
|
|
|
PRUint8 transCaps,
|
2001-12-06 02:21:03 +00:00
|
|
|
nsHttpConnection *conn)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
LOG(("nsHttpHandler::DispatchTransaction_Locked [trans=%x conn=%x]\n",
|
|
|
|
trans, conn));
|
|
|
|
|
2001-06-20 01:21:43 +00:00
|
|
|
// assign the connection to the transaction.
|
|
|
|
trans->SetConnection(conn);
|
2001-06-11 21:20:29 +00:00
|
|
|
|
2001-06-20 01:21:43 +00:00
|
|
|
// consider this connection active, even though it may fail.
|
2001-06-11 21:20:29 +00:00
|
|
|
mActiveConnections.AppendElement(conn);
|
2001-12-06 02:21:03 +00:00
|
|
|
|
|
|
|
// handler now owns a reference to this connection
|
|
|
|
NS_ADDREF(conn);
|
2001-06-20 01:21:43 +00:00
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
// we must not hold the connection lock while making the call to
|
|
|
|
// SetTransaction, as it could lead to deadlocks.
|
2001-06-20 01:21:43 +00:00
|
|
|
PR_Unlock(mConnectionLock);
|
2002-04-19 22:25:23 +00:00
|
|
|
rv = conn->SetTransaction(trans, transCaps);
|
2001-06-20 01:21:43 +00:00
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
2001-09-04 23:02:26 +00:00
|
|
|
LOG(("nsHttpConnection::SetTransaction failed [rv=%x]\n", rv));
|
2001-12-06 02:21:03 +00:00
|
|
|
nsAutoLock lock(mConnectionLock);
|
2001-06-20 01:21:43 +00:00
|
|
|
// the connection may already have been removed from the
|
|
|
|
// active connection list.
|
|
|
|
if (mActiveConnections.RemoveElement(conn))
|
|
|
|
NS_RELEASE(conn);
|
|
|
|
}
|
2001-06-11 21:20:29 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
// try to dispatch a pending transaction, return unlocked
|
|
|
|
void
|
|
|
|
nsHttpHandler::ProcessTransactionQ_Locked()
|
2001-06-14 20:52:03 +00:00
|
|
|
{
|
2001-12-06 02:21:03 +00:00
|
|
|
LOG(("nsHttpHandler::ProcessTransactionQ_Locked\n"));
|
2001-06-14 20:52:03 +00:00
|
|
|
|
|
|
|
nsPendingTransaction *pt = nsnull;
|
2001-12-06 02:21:03 +00:00
|
|
|
nsHttpConnection *conn = nsnull;
|
|
|
|
|
|
|
|
//
|
|
|
|
// step 1: locate a pending transaction that can be processed
|
|
|
|
//
|
2001-06-14 20:52:03 +00:00
|
|
|
PRInt32 i;
|
|
|
|
for (i=0; i<mTransactionQ.Count(); ++i) {
|
|
|
|
pt = (nsPendingTransaction *) mTransactionQ[i];
|
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
GetConnection_Locked(pt->ConnectionInfo(),
|
|
|
|
pt->Transaction()->Capabilities(),
|
|
|
|
&conn);
|
|
|
|
if (conn)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!conn) {
|
|
|
|
LOG((">> unable to process transaction queue at this time\n"));
|
|
|
|
// the caller expects us to unlock before returning...
|
|
|
|
PR_Unlock(mConnectionLock);
|
|
|
|
return;
|
2001-06-14 20:52:03 +00:00
|
|
|
}
|
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
//
|
|
|
|
// step 2: remove i'th pending transaction from the pending transaction
|
|
|
|
// queue. we'll put it back if there is a problem dispatching it.
|
|
|
|
//
|
|
|
|
// the call to DispatchTransaction_Locked will temporarily leave
|
|
|
|
// mConnectionLock, so this step is crucial as it ensures that our
|
|
|
|
// state is completely defined on the stack (not in member variables).
|
|
|
|
//
|
|
|
|
mTransactionQ.RemoveElementAt(i);
|
|
|
|
|
|
|
|
//
|
2002-04-19 22:25:23 +00:00
|
|
|
// step 3: determine if we can pipeline any other transactions along with
|
|
|
|
// this transaction. if pipelining is disabled or there are no other
|
|
|
|
// transactions that can be sent with this transaction, then simply send
|
|
|
|
// this transaction.
|
|
|
|
//
|
|
|
|
nsAHttpTransaction *trans = pt->Transaction();
|
|
|
|
PRUint8 caps = pt->Transaction()->Capabilities();
|
|
|
|
nsPipelineEnqueueState pipelineState;
|
|
|
|
if (conn->SupportsPipelining() &&
|
|
|
|
caps & NS_HTTP_ALLOW_PIPELINING &&
|
|
|
|
BuildPipeline_Locked(pipelineState,
|
|
|
|
pt->Transaction(),
|
|
|
|
pt->ConnectionInfo())) {
|
|
|
|
// ok... let's rock!
|
|
|
|
trans = pipelineState.Transaction();
|
|
|
|
caps = pipelineState.TransactionCaps();
|
|
|
|
NS_ASSERTION(trans, "no transaction");
|
|
|
|
}
|
2002-05-24 00:12:28 +00:00
|
|
|
#if defined(PR_LOGGING)
|
|
|
|
else
|
|
|
|
LOG(("no pipelining [because-of-server=%d because-of-caps=%d]\n",
|
|
|
|
conn->SupportsPipelining() == PR_FALSE,
|
|
|
|
caps & NS_HTTP_ALLOW_PIPELINING == PR_FALSE));
|
|
|
|
#endif
|
2002-04-19 22:25:23 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// step 4: dispatch this transaction
|
2001-12-06 02:21:03 +00:00
|
|
|
//
|
2002-04-19 22:25:23 +00:00
|
|
|
nsresult rv = DispatchTransaction_Locked(trans, caps, conn);
|
2001-12-06 02:21:03 +00:00
|
|
|
|
|
|
|
// we're no longer inside mConnectionLock
|
|
|
|
|
|
|
|
//
|
2002-04-19 22:25:23 +00:00
|
|
|
// step 5: handle errors / cleanup
|
2001-12-06 02:21:03 +00:00
|
|
|
//
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LOG((">> DispatchTransaction_Locked failed [rv=%x]\n", rv));
|
|
|
|
nsAutoLock lock(mConnectionLock);
|
|
|
|
// there must have been something wrong with the connection,
|
|
|
|
// requeue... we'll try again later.
|
2002-04-19 22:25:23 +00:00
|
|
|
if (caps & NS_HTTP_ALLOW_PIPELINING)
|
|
|
|
PipelineFailed_Locked(pipelineState);
|
2001-12-06 02:21:03 +00:00
|
|
|
mTransactionQ.AppendElement(pt);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
delete pt;
|
2002-04-19 22:25:23 +00:00
|
|
|
pipelineState.Cleanup();
|
2001-12-06 02:21:03 +00:00
|
|
|
NS_RELEASE(conn);
|
2001-06-14 20:52:03 +00:00
|
|
|
}
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
// we're at the active connection limit if any one of the following conditions is true:
|
|
|
|
// (1) at max-connections
|
2001-12-06 02:21:03 +00:00
|
|
|
// (2) keep-alive enabled and at max-persistent-connections-per-server/proxy
|
|
|
|
// (3) keep-alive disabled and at max-connections-per-server
|
2001-09-04 23:02:26 +00:00
|
|
|
PRBool
|
2001-12-06 02:21:03 +00:00
|
|
|
nsHttpHandler::AtActiveConnectionLimit_Locked(nsHttpConnectionInfo *ci, PRUint8 caps)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2001-12-06 02:21:03 +00:00
|
|
|
LOG(("nsHttpHandler::AtActiveConnectionLimit_Locked [host=%s:%d caps=%x]\n",
|
2001-09-04 23:02:26 +00:00
|
|
|
ci->Host(), ci->Port(), caps));
|
2001-06-11 21:20:29 +00:00
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
// use >= just to be safe
|
|
|
|
if (mActiveConnections.Count() >= mMaxConnections)
|
|
|
|
return PR_TRUE;
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
nsHttpConnection *conn;
|
|
|
|
PRUint8 totalCount = 0, persistentCount = 0;
|
2001-06-11 21:20:29 +00:00
|
|
|
PRInt32 i;
|
|
|
|
for (i=0; i<mActiveConnections.Count(); ++i) {
|
|
|
|
conn = NS_STATIC_CAST(nsHttpConnection *, mActiveConnections[i]);
|
2001-09-04 23:02:26 +00:00
|
|
|
LOG((">> comparing against active connection [conn=%x host=%s:%d]\n",
|
|
|
|
conn, conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port()));
|
2001-05-11 21:04:09 +00:00
|
|
|
if (conn->ConnectionInfo()->Equals(ci)) {
|
2001-09-04 23:02:26 +00:00
|
|
|
totalCount++;
|
|
|
|
if (conn->IsKeepAlive())
|
|
|
|
persistentCount++;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
LOG((" total-count=%u, persistent-count=%u\n",
|
|
|
|
PRUint32(totalCount), PRUint32(persistentCount)));
|
|
|
|
|
2001-11-04 05:46:06 +00:00
|
|
|
PRUint8 maxPersistentConnections =
|
|
|
|
ci->UsingHttpProxy() ? mMaxPersistentConnectionsPerProxy
|
|
|
|
: mMaxPersistentConnectionsPerServer;
|
|
|
|
|
2001-09-04 23:02:26 +00:00
|
|
|
// use >= just to be safe
|
|
|
|
return (totalCount >= mMaxConnectionsPerServer) ||
|
|
|
|
((caps & NS_HTTP_ALLOW_KEEPALIVE) &&
|
2001-11-04 05:46:06 +00:00
|
|
|
(persistentCount >= maxPersistentConnections));
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2001-12-06 02:21:03 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::RemovePendingTransaction_Locked(nsHttpTransaction *trans)
|
|
|
|
{
|
|
|
|
LOG(("nsHttpHandler::RemovePendingTransaction_Locked [trans=%x]\n", trans));
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(trans);
|
|
|
|
|
|
|
|
nsPendingTransaction *pt = nsnull;
|
|
|
|
PRInt32 i;
|
|
|
|
for (i=0; i<mTransactionQ.Count(); ++i) {
|
|
|
|
pt = (nsPendingTransaction *) mTransactionQ[i];
|
|
|
|
|
|
|
|
if (pt->Transaction() == trans) {
|
|
|
|
mTransactionQ.RemoveElementAt(i);
|
|
|
|
delete pt;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_WARNING("transaction not in pending queue");
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2001-12-07 01:40:18 +00:00
|
|
|
void
|
|
|
|
nsHttpHandler::DeadConnectionCleanupCB(nsITimer *timer, void *closure)
|
|
|
|
{
|
|
|
|
nsHttpHandler *self = NS_STATIC_CAST(nsHttpHandler*, closure);
|
|
|
|
if (self)
|
|
|
|
self->PurgeDeadConnections();
|
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
void
|
|
|
|
nsHttpHandler::DropConnections(nsVoidArray &connections)
|
|
|
|
{
|
|
|
|
nsHttpConnection *conn;
|
|
|
|
PRInt32 i;
|
|
|
|
for (i=0; i<connections.Count(); ++i) {
|
|
|
|
conn = (nsHttpConnection *) connections[i];
|
|
|
|
NS_RELEASE(conn);
|
|
|
|
}
|
|
|
|
connections.Clear();
|
|
|
|
}
|
|
|
|
|
2002-04-19 22:25:23 +00:00
|
|
|
PRBool
|
|
|
|
nsHttpHandler::BuildPipeline_Locked(nsPipelineEnqueueState &state,
|
|
|
|
nsHttpTransaction *firstTrans,
|
|
|
|
nsHttpConnectionInfo *ci)
|
|
|
|
{
|
|
|
|
if (mMaxPipelinedRequests < 2)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
LOG(("BuildPipeline_Locked [trans=%x]\n", firstTrans));
|
|
|
|
|
|
|
|
//
|
|
|
|
// need to search the pending transaction list for other transactions
|
|
|
|
// that can be pipelined along with |firstTrans|.
|
|
|
|
//
|
|
|
|
nsresult rv = NS_ERROR_FAILURE; // by default, nothing to pipeline
|
|
|
|
PRUint8 numAppended = 0;
|
|
|
|
PRInt32 i = 0;
|
|
|
|
while (i < mTransactionQ.Count()) {
|
|
|
|
nsPendingTransaction *pt = (nsPendingTransaction *) mTransactionQ[i];
|
|
|
|
if (pt->Transaction()->Capabilities() & (NS_HTTP_ALLOW_KEEPALIVE |
|
|
|
|
NS_HTTP_ALLOW_PIPELINING) &&
|
|
|
|
pt->ConnectionInfo()->Equals(ci)) {
|
|
|
|
|
|
|
|
//
|
|
|
|
// ok, we can add this transaction to our pipeline
|
|
|
|
//
|
|
|
|
if (numAppended == 0) {
|
|
|
|
rv = state.Init(firstTrans);
|
|
|
|
if (NS_FAILED(rv)) break;
|
|
|
|
}
|
|
|
|
rv = state.AppendTransaction(pt);
|
|
|
|
if (NS_FAILED(rv)) break;
|
|
|
|
|
|
|
|
//
|
|
|
|
// ok, remove the transaction from the pending queue; next time
|
|
|
|
// around the loop we'll still check the i-th element :-)
|
|
|
|
//
|
|
|
|
mTransactionQ.RemoveElementAt(i);
|
|
|
|
|
|
|
|
//
|
|
|
|
// we may have reached the pipelined requests limit...
|
|
|
|
//
|
|
|
|
if (++numAppended == (mMaxPipelinedRequests - 1))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
i++; // advance to next pending transaction
|
|
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
LOG((" unable to pipeline any transactions with this one\n"));
|
|
|
|
state.Cleanup();
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
LOG((" pipelined %u transactions\n", numAppended + 1));
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsHttpHandler::PipelineFailed_Locked(nsPipelineEnqueueState &state)
|
|
|
|
{
|
|
|
|
if ((mMaxPipelinedRequests < 2) || !state.HasPipeline())
|
|
|
|
return;
|
|
|
|
|
|
|
|
LOG(("PipelineFailed_Locked\n"));
|
|
|
|
|
|
|
|
// need to put any "appended" transactions back on the queue
|
|
|
|
PRInt32 i = 0;
|
|
|
|
while (i < state.NumAppendedTrans()) {
|
|
|
|
mTransactionQ.AppendElement(state.GetAppendedTrans(i));
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
state.DropAppendedTrans();
|
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
void
|
|
|
|
nsHttpHandler::BuildUserAgent()
|
|
|
|
{
|
|
|
|
LOG(("nsHttpHandler::BuildUserAgent\n"));
|
|
|
|
|
2002-03-20 22:50:33 +00:00
|
|
|
NS_ASSERTION(!mAppName.IsEmpty() &&
|
|
|
|
!mAppVersion.IsEmpty() &&
|
|
|
|
!mPlatform.IsEmpty() &&
|
|
|
|
!mSecurity.IsEmpty() &&
|
|
|
|
!mOscpu.IsEmpty(),
|
2001-05-11 21:04:09 +00:00
|
|
|
"HTTP cannot send practical requests without this much");
|
|
|
|
|
2002-03-20 22:50:33 +00:00
|
|
|
// preallocate to worst-case size, which should always be better
|
|
|
|
// than if we didn't preallocate at all.
|
|
|
|
mUserAgent.SetCapacity(mAppName.Length() +
|
|
|
|
mAppVersion.Length() +
|
|
|
|
mPlatform.Length() +
|
|
|
|
mSecurity.Length() +
|
|
|
|
mOscpu.Length() +
|
|
|
|
mLanguage.Length() +
|
|
|
|
mMisc.Length() +
|
|
|
|
mProduct.Length() +
|
|
|
|
mProductSub.Length() +
|
|
|
|
mProductComment.Length() +
|
|
|
|
mVendor.Length() +
|
|
|
|
mVendorSub.Length() +
|
|
|
|
mVendorComment.Length() +
|
|
|
|
22);
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
// Application portion
|
|
|
|
mUserAgent.Assign(mAppName);
|
|
|
|
mUserAgent += '/';
|
|
|
|
mUserAgent += mAppVersion;
|
|
|
|
mUserAgent += ' ';
|
|
|
|
|
|
|
|
// Application comment
|
|
|
|
mUserAgent += '(';
|
|
|
|
mUserAgent += mPlatform;
|
|
|
|
mUserAgent += "; ";
|
|
|
|
mUserAgent += mSecurity;
|
|
|
|
mUserAgent += "; ";
|
|
|
|
mUserAgent += mOscpu;
|
2002-03-20 22:50:33 +00:00
|
|
|
if (!mLanguage.IsEmpty()) {
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgent += "; ";
|
|
|
|
mUserAgent += mLanguage;
|
|
|
|
}
|
2002-03-20 22:50:33 +00:00
|
|
|
if (!mMisc.IsEmpty()) {
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgent += "; ";
|
|
|
|
mUserAgent += mMisc;
|
|
|
|
}
|
|
|
|
mUserAgent += ')';
|
|
|
|
|
|
|
|
// Product portion
|
2002-03-20 22:50:33 +00:00
|
|
|
if (!mProduct.IsEmpty()) {
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgent += ' ';
|
|
|
|
mUserAgent += mProduct;
|
2002-03-20 22:50:33 +00:00
|
|
|
if (!mProductSub.IsEmpty()) {
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgent += '/';
|
|
|
|
mUserAgent += mProductSub;
|
|
|
|
}
|
2002-03-20 22:50:33 +00:00
|
|
|
if (!mProductComment.IsEmpty()) {
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgent += " (";
|
|
|
|
mUserAgent += mProductComment;
|
|
|
|
mUserAgent += ')';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Vendor portion
|
2002-03-20 22:50:33 +00:00
|
|
|
if (!mVendor.IsEmpty()) {
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgent += ' ';
|
|
|
|
mUserAgent += mVendor;
|
2002-03-20 22:50:33 +00:00
|
|
|
if (!mVendorSub.IsEmpty()) {
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgent += '/';
|
|
|
|
mUserAgent += mVendorSub;
|
|
|
|
}
|
2002-03-20 22:50:33 +00:00
|
|
|
if (!mVendorComment.IsEmpty()) {
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgent += " (";
|
|
|
|
mUserAgent += mVendorComment;
|
|
|
|
mUserAgent += ')';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsHttpHandler::InitUserAgentComponents()
|
|
|
|
{
|
|
|
|
|
|
|
|
// Gather Application name and Version.
|
2001-06-17 05:23:38 +00:00
|
|
|
mAppName.Adopt(nsCRT::strdup(UA_APPNAME));
|
|
|
|
mAppVersion.Adopt(nsCRT::strdup(UA_APPVERSION));
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-06-17 05:23:38 +00:00
|
|
|
// Gather platform.
|
|
|
|
mPlatform.Adopt(nsCRT::strdup(
|
2001-12-09 09:14:34 +00:00
|
|
|
#if defined(MOZ_WIDGET_PHOTON)
|
|
|
|
"Photon"
|
|
|
|
#elif defined(XP_OS2)
|
2001-06-17 05:23:38 +00:00
|
|
|
"OS/2"
|
2001-12-09 09:14:34 +00:00
|
|
|
#elif defined(XP_WIN)
|
2001-06-17 05:23:38 +00:00
|
|
|
"Windows"
|
2001-10-27 07:38:18 +00:00
|
|
|
#elif defined(XP_MAC) || defined(XP_MACOSX)
|
2001-06-17 05:23:38 +00:00
|
|
|
"Macintosh"
|
2001-05-11 21:04:09 +00:00
|
|
|
#elif defined(XP_BEOS)
|
2001-06-17 05:23:38 +00:00
|
|
|
"BeOS"
|
2001-12-09 09:14:34 +00:00
|
|
|
#elif defined(NO_X11)
|
|
|
|
"?"
|
|
|
|
#else
|
|
|
|
"X11"
|
2001-05-11 21:04:09 +00:00
|
|
|
#endif
|
2001-06-17 05:23:38 +00:00
|
|
|
));
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
// Gather OS/CPU.
|
|
|
|
#if defined(XP_OS2)
|
|
|
|
ULONG os2ver = 0;
|
|
|
|
DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_MINOR,
|
|
|
|
&os2ver, sizeof(os2ver));
|
|
|
|
if (os2ver == 11)
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("2.11"));
|
2001-05-11 21:04:09 +00:00
|
|
|
else if (os2ver == 30)
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("Warp 3"));
|
2001-05-11 21:04:09 +00:00
|
|
|
else if (os2ver == 40)
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("Warp 4"));
|
2001-05-11 21:04:09 +00:00
|
|
|
else if (os2ver == 45)
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("Warp 4.5"));
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
#elif defined(XP_PC)
|
|
|
|
OSVERSIONINFO info = { sizeof OSVERSIONINFO };
|
|
|
|
if (GetVersionEx(&info)) {
|
|
|
|
if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
|
|
|
if (info.dwMajorVersion == 3)
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("WinNT3.51"));
|
2001-05-11 21:04:09 +00:00
|
|
|
else if (info.dwMajorVersion == 4)
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("WinNT4.0"));
|
2001-06-19 22:40:34 +00:00
|
|
|
else {
|
2001-05-11 21:04:09 +00:00
|
|
|
char *buf = PR_smprintf("Windows NT %ld.%ld",
|
|
|
|
info.dwMajorVersion,
|
|
|
|
info.dwMinorVersion);
|
|
|
|
if (buf) {
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup(buf));
|
2001-05-11 21:04:09 +00:00
|
|
|
PR_smprintf_free(buf);
|
|
|
|
}
|
|
|
|
}
|
2001-06-19 22:40:34 +00:00
|
|
|
} else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
|
|
|
|
info.dwMajorVersion == 4) {
|
2001-05-11 21:04:09 +00:00
|
|
|
if (info.dwMinorVersion == 90)
|
2001-06-19 22:40:34 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("Win 9x 4.90")); // Windows Me
|
2001-05-11 21:04:09 +00:00
|
|
|
else if (info.dwMinorVersion > 0)
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("Win98"));
|
2001-05-11 21:04:09 +00:00
|
|
|
else
|
2001-06-17 05:23:38 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("Win95"));
|
2001-06-19 22:40:34 +00:00
|
|
|
} else {
|
|
|
|
char *buf = PR_smprintf("Windows %ld.%ld",
|
|
|
|
info.dwMajorVersion,
|
|
|
|
info.dwMinorVersion);
|
|
|
|
if (buf) {
|
|
|
|
mOscpu.Adopt(nsCRT::strdup(buf));
|
|
|
|
PR_smprintf_free(buf);
|
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
2002-04-24 00:55:53 +00:00
|
|
|
#elif defined (XP_MACOSX)
|
2002-11-13 04:29:47 +00:00
|
|
|
mOscpu.Adopt(nsCRT::strdup("PPC Mac OS X Mach-O"));
|
2002-04-24 00:55:53 +00:00
|
|
|
#elif defined (XP_MAC)
|
|
|
|
long version;
|
|
|
|
if (::Gestalt(gestaltSystemVersion, &version) == noErr && version >= 0x00001000)
|
|
|
|
mOscpu.Adopt(nsCRT::strdup("PPC Mac OS X"));
|
|
|
|
else
|
|
|
|
mOscpu.Adopt(nsCRT::strdup("PPC"));
|
2001-05-11 21:04:09 +00:00
|
|
|
#elif defined (XP_UNIX) || defined (XP_BEOS)
|
|
|
|
struct utsname name;
|
|
|
|
|
|
|
|
int ret = uname(&name);
|
|
|
|
if (ret >= 0) {
|
|
|
|
nsCString buf;
|
|
|
|
buf = (char*)name.sysname;
|
|
|
|
buf += ' ';
|
|
|
|
buf += (char*)name.machine;
|
2001-11-28 05:22:57 +00:00
|
|
|
mOscpu.Assign(buf);
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2001-10-02 00:40:27 +00:00
|
|
|
nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
2001-08-14 01:03:27 +00:00
|
|
|
PRInt32 val;
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-10-04 01:40:35 +00:00
|
|
|
LOG(("nsHttpHandler::PrefsChanged [pref=%s]\n", pref));
|
2001-09-27 21:26:59 +00:00
|
|
|
|
|
|
|
#define PREF_CHANGED(p) ((pref == nsnull) || !PL_strcmp(pref, p))
|
|
|
|
|
|
|
|
//
|
|
|
|
// UA components
|
|
|
|
//
|
|
|
|
|
|
|
|
// Gather vendor values.
|
|
|
|
if (PREF_CHANGED(UA_PREF("vendor"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(UA_PREF("vendor"),
|
2001-09-27 21:26:59 +00:00
|
|
|
getter_Copies(mVendor));
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
if (PREF_CHANGED(UA_PREF("vendorSub"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(UA_PREF("vendorSub"),
|
2001-09-27 21:26:59 +00:00
|
|
|
getter_Copies(mVendorSub));
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
if (PREF_CHANGED(UA_PREF("vendorComment"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(UA_PREF("vendorComment"),
|
2001-09-27 21:26:59 +00:00
|
|
|
getter_Copies(mVendorComment));
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gather product values.
|
|
|
|
if (PREF_CHANGED(UA_PREF("product"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(UA_PREF_PREFIX "product",
|
2001-09-27 21:26:59 +00:00
|
|
|
getter_Copies(mProduct));
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
if (PREF_CHANGED(UA_PREF("productSub"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(UA_PREF("productSub"),
|
2001-09-27 21:26:59 +00:00
|
|
|
getter_Copies(mProductSub));
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
if (PREF_CHANGED(UA_PREF("productComment"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(UA_PREF("productComment"),
|
2001-09-27 21:26:59 +00:00
|
|
|
getter_Copies(mProductComment));
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gather misc value.
|
|
|
|
if (PREF_CHANGED(UA_PREF("misc"))) {
|
2001-10-05 07:50:21 +00:00
|
|
|
prefs->GetCharPref(UA_PREF("misc"), getter_Copies(mMisc));
|
2001-09-27 21:26:59 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get Security level supported
|
|
|
|
if (PREF_CHANGED(UA_PREF("security"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(UA_PREF("security"), getter_Copies(mSecurity));
|
2001-09-27 21:26:59 +00:00
|
|
|
if (!mSecurity)
|
|
|
|
mSecurity.Adopt(nsCRT::strdup(UA_APPSECURITY_FALLBACK));
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gather locale.
|
|
|
|
if (PREF_CHANGED(UA_PREF("locale"))) {
|
|
|
|
nsCOMPtr<nsIPrefLocalizedString> pls;
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetComplexValue(UA_PREF("locale"),
|
2001-09-27 21:26:59 +00:00
|
|
|
NS_GET_IID(nsIPrefLocalizedString),
|
|
|
|
getter_AddRefs(pls));
|
|
|
|
if (pls) {
|
|
|
|
nsXPIDLString uval;
|
|
|
|
pls->ToString(getter_Copies(uval));
|
|
|
|
if (uval)
|
|
|
|
mLanguage.Adopt(ToNewUTF8String(nsDependentString(uval)));
|
|
|
|
}
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// general.useragent.override
|
|
|
|
if (PREF_CHANGED(UA_PREF("override"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(UA_PREF("override"),
|
2001-09-27 21:26:59 +00:00
|
|
|
getter_Copies(mUserAgentOverride));
|
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// HTTP options
|
|
|
|
//
|
|
|
|
|
|
|
|
if (PREF_CHANGED(HTTP_PREF("keep-alive.timeout"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("keep-alive.timeout"), &val);
|
2001-08-14 01:03:27 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mIdleTimeout = (PRUint16) CLAMP(val, 1, 0xffff);
|
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("request.max-attempts"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("request.max-attempts"), &val);
|
2001-08-14 01:03:27 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mMaxRequestAttempts = (PRUint16) CLAMP(val, 1, 0xffff);
|
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("request.max-start-delay"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("request.max-start-delay"), &val);
|
2001-09-04 23:02:26 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mMaxRequestDelay = (PRUint16) CLAMP(val, 0, 0xffff);
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
|
2001-08-14 01:03:27 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mMaxConnections = (PRUint16) CLAMP(val, 1, 0xffff);
|
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("max-connections-per-server"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("max-connections-per-server"), &val);
|
2001-08-14 01:03:27 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mMaxConnectionsPerServer = (PRUint8) CLAMP(val, 1, 0xff);
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("max-persistent-connections-per-server"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("max-persistent-connections-per-server"), &val);
|
2001-08-14 01:03:27 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
2001-09-04 23:02:26 +00:00
|
|
|
mMaxPersistentConnectionsPerServer = (PRUint8) CLAMP(val, 1, 0xff);
|
2001-08-14 01:03:27 +00:00
|
|
|
}
|
|
|
|
|
2001-11-04 05:46:06 +00:00
|
|
|
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) CLAMP(val, 1, 0xff);
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
|
2001-12-08 00:23:04 +00:00
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("sendRefererHeader"), &val);
|
2001-08-14 01:03:27 +00:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mReferrerLevel = (PRUint8) CLAMP(val, 0, 0xff);
|
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-12-08 00:23:04 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
|
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mRedirectionLimit = (PRUint8) CLAMP(val, 0, 0xff);
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("version"))) {
|
2001-05-11 21:04:09 +00:00
|
|
|
nsXPIDLCString httpVersion;
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));
|
2001-05-11 21:04:09 +00:00
|
|
|
if (httpVersion) {
|
2001-09-27 21:26:59 +00:00
|
|
|
if (!PL_strcmp(httpVersion, "1.1"))
|
2001-05-11 21:04:09 +00:00
|
|
|
mHttpVersion = NS_HTTP_VERSION_1_1;
|
2001-09-27 21:26:59 +00:00
|
|
|
else if (!PL_strcmp(httpVersion, "0.9"))
|
2001-05-11 21:04:09 +00:00
|
|
|
mHttpVersion = NS_HTTP_VERSION_0_9;
|
|
|
|
else
|
|
|
|
mHttpVersion = NS_HTTP_VERSION_1_0;
|
|
|
|
}
|
2002-04-18 22:36:39 +00:00
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2002-04-18 22:36:39 +00:00
|
|
|
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
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool cVar = PR_FALSE;
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("keep-alive"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetBoolPref(HTTP_PREF("keep-alive"), &cVar);
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (cVar)
|
2001-08-14 01:03:27 +00:00
|
|
|
mCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
|
2001-05-11 21:04:09 +00:00
|
|
|
else
|
2001-08-14 01:03:27 +00:00
|
|
|
mCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("proxy.keep-alive"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetBoolPref(HTTP_PREF("proxy.keep-alive"), &cVar);
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (cVar)
|
2001-08-14 01:03:27 +00:00
|
|
|
mProxyCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
|
2001-05-11 21:04:09 +00:00
|
|
|
else
|
2001-08-14 01:03:27 +00:00
|
|
|
mProxyCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("pipelining"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetBoolPref(HTTP_PREF("pipelining"), &cVar);
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (cVar)
|
2001-08-14 01:03:27 +00:00
|
|
|
mCapabilities |= NS_HTTP_ALLOW_PIPELINING;
|
2001-05-11 21:04:09 +00:00
|
|
|
else
|
2001-08-14 01:03:27 +00:00
|
|
|
mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-19 22:25:23 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("pipelining.maxrequests"))) {
|
|
|
|
rv = prefs->GetIntPref(HTTP_PREF("pipelining.maxrequests"), &val);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mMaxPipelinedRequests = CLAMP(val, 1, NS_HTTP_MAX_PIPELINED_REQUESTS);
|
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("proxy.pipelining"))) {
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetBoolPref(HTTP_PREF("proxy.pipelining"), &cVar);
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (cVar)
|
2001-08-14 01:03:27 +00:00
|
|
|
mProxyCapabilities |= NS_HTTP_ALLOW_PIPELINING;
|
2001-05-11 21:04:09 +00:00
|
|
|
else
|
2001-08-14 01:03:27 +00:00
|
|
|
mProxyCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-03-18 05:20:58 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("sendSecureXSiteReferrer"))) {
|
|
|
|
rv = prefs->GetBoolPref(HTTP_PREF("sendSecureXSiteReferrer"), &cVar);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
mSendSecureXSiteReferrer = cVar;
|
|
|
|
}
|
|
|
|
|
2001-08-14 01:03:27 +00:00
|
|
|
/*
|
2001-05-11 21:04:09 +00:00
|
|
|
if (bChangedAll || PL_strcmp(pref, "network.http.connect.timeout") == 0)
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetIntPref("network.http.connect.timeout", &mConnectTimeout);
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
if (bChangedAll || PL_strcmp(pref, "network.http.request.timeout") == 0)
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetIntPref("network.http.request.timeout", &mRequestTimeout);
|
2001-08-14 01:03:27 +00:00
|
|
|
*/
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("accept.default"))) {
|
2001-05-17 00:17:34 +00:00
|
|
|
nsXPIDLCString accept;
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetCharPref(HTTP_PREF("accept.default"),
|
2001-05-17 00:17:34 +00:00
|
|
|
getter_Copies(accept));
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
SetAccept(accept);
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("accept-encoding"))) {
|
2001-05-11 21:04:09 +00:00
|
|
|
nsXPIDLCString acceptEncodings;
|
2001-10-02 00:40:27 +00:00
|
|
|
rv = prefs->GetCharPref(HTTP_PREF("accept-encoding"),
|
2001-05-11 21:04:09 +00:00
|
|
|
getter_Copies(acceptEncodings));
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
SetAcceptEncodings(acceptEncodings);
|
|
|
|
}
|
|
|
|
|
2001-10-02 00:40:27 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("use-cache"))) {
|
|
|
|
rv = prefs->GetBoolPref(HTTP_PREF("use-cache"), &cVar);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
mUseCache = cVar;
|
|
|
|
if (!mUseCache) {
|
|
|
|
// release our references to the cache
|
|
|
|
mCacheSession_ANY = 0;
|
|
|
|
mCacheSession_MEM = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-06 06:36:17 +00:00
|
|
|
if (PREF_CHANGED(HTTP_PREF("default-socket-type"))) {
|
|
|
|
nsXPIDLCString val;
|
|
|
|
rv = prefs->GetCharPref(HTTP_PREF("default-socket-type"),
|
|
|
|
getter_Copies(val));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
if (val.IsEmpty())
|
|
|
|
mDefaultSocketType.Adopt(0);
|
|
|
|
else {
|
|
|
|
// verify that this socket type is actually valid
|
|
|
|
nsCOMPtr<nsISocketProviderService> sps(
|
|
|
|
do_GetService(kSocketProviderServiceCID, &rv));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsCOMPtr<nsISocketProvider> sp;
|
|
|
|
rv = sps->GetSocketProvider(val, getter_AddRefs(sp));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// OK, this looks like a valid socket provider.
|
|
|
|
mDefaultSocketType.Assign(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
//
|
|
|
|
// INTL options
|
|
|
|
//
|
|
|
|
|
|
|
|
if (PREF_CHANGED(INTL_ACCEPT_LANGUAGES)) {
|
|
|
|
nsCOMPtr<nsIPrefLocalizedString> pls;
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetComplexValue(INTL_ACCEPT_LANGUAGES,
|
2001-09-27 21:26:59 +00:00
|
|
|
NS_GET_IID(nsIPrefLocalizedString),
|
|
|
|
getter_AddRefs(pls));
|
|
|
|
if (pls) {
|
|
|
|
nsXPIDLString uval;
|
|
|
|
pls->ToString(getter_Copies(uval));
|
|
|
|
if (uval)
|
|
|
|
SetAcceptLanguages(NS_ConvertUCS2toUTF8(uval).get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PREF_CHANGED(INTL_ACCEPT_CHARSET)) {
|
|
|
|
nsCOMPtr<nsIPrefLocalizedString> pls;
|
2001-10-02 00:40:27 +00:00
|
|
|
prefs->GetComplexValue(INTL_ACCEPT_CHARSET,
|
2001-09-27 21:26:59 +00:00
|
|
|
NS_GET_IID(nsIPrefLocalizedString),
|
|
|
|
getter_AddRefs(pls));
|
|
|
|
if (pls) {
|
|
|
|
nsXPIDLString uval;
|
|
|
|
pls->ToString(getter_Copies(uval));
|
|
|
|
if (uval)
|
|
|
|
SetAcceptCharsets(NS_ConvertUCS2toUTF8(uval).get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-05 07:50:21 +00:00
|
|
|
//
|
|
|
|
// 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, &rv);
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "idnSDK not installed");
|
|
|
|
}
|
|
|
|
else if (!enableIDN && mIDNConverter)
|
|
|
|
mIDNConverter = nsnull;
|
|
|
|
}
|
|
|
|
|
2001-09-27 21:26:59 +00:00
|
|
|
#undef PREF_CHANGED
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2001-10-02 00:40:27 +00:00
|
|
|
void
|
|
|
|
nsHttpHandler::GetPrefBranch(nsIPrefBranch **result)
|
|
|
|
{
|
|
|
|
*result = nsnull;
|
|
|
|
nsCOMPtr<nsIPrefService> prefService =
|
|
|
|
do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
|
|
if (prefService)
|
|
|
|
prefService->GetBranch(nsnull, result);
|
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
/**
|
|
|
|
* 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"
|
2002-11-20 20:51:12 +00:00
|
|
|
* returns: "en,ja;q=0.5"
|
2001-05-11 21:04:09 +00:00
|
|
|
*
|
|
|
|
* passing: "en, ja, fr_CA"
|
2002-11-20 20:51:12 +00:00
|
|
|
* returns: "en,ja;q=0.7,fr_CA;q=0.3"
|
2001-05-11 21:04:09 +00:00
|
|
|
*/
|
|
|
|
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 (nsnull == 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 ((char *) 0 == q_Accept)
|
|
|
|
return nsnull;
|
|
|
|
*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))
|
|
|
|
{
|
|
|
|
while (*token == ' ' || *token == '\x9') token++;
|
|
|
|
char* trim;
|
|
|
|
trim = PL_strpbrk(token, "; \x9");
|
|
|
|
if (trim != (char*)0) // remove "; q=..." if present
|
|
|
|
*trim = '\0';
|
|
|
|
|
|
|
|
if (*token != '\0') {
|
2002-11-20 20:51:12 +00:00
|
|
|
comma = n++ != 0 ? "," : ""; // delimiter if not first item
|
2001-05-11 21:04:09 +00:00
|
|
|
if (q < 0.9995)
|
2002-11-20 20:51:12 +00:00
|
|
|
wrote = PR_snprintf(p2, available, "%s%s;q=0.%01u", comma, token, QVAL_TO_UINT(q));
|
2001-05-11 21:04:09 +00:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
nsCString buf;
|
|
|
|
nsresult rv = PrepareAcceptLanguages(aAcceptLanguages, buf);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
2002-03-20 22:50:33 +00:00
|
|
|
mAcceptLanguages.Assign(buf);
|
2001-05-11 21:04:09 +00:00
|
|
|
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"
|
2002-11-20 20:51:12 +00:00
|
|
|
* returns: "euc-jp,utf-8;q=0.6,*;q=0.6"
|
2001-05-11 21:04:09 +00:00
|
|
|
*
|
|
|
|
* passing: "UTF-8"
|
|
|
|
* returns: "UTF-8, *"
|
|
|
|
*/
|
|
|
|
static nsresult
|
|
|
|
PrepareAcceptCharsets(const char *i_AcceptCharset, nsACString &o_AcceptCharset)
|
|
|
|
{
|
|
|
|
PRUint32 n, size, wrote;
|
|
|
|
PRInt32 available;
|
|
|
|
double q, dec;
|
|
|
|
char *p, *p2, *token, *q_Accept, *o_Accept;
|
|
|
|
const char *acceptable, *comma;
|
|
|
|
PRBool add_utf = PR_FALSE;
|
2001-12-23 23:23:41 +00:00
|
|
|
PRBool add_asterisk = PR_FALSE;
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
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_strstr(acceptable, "*") == NULL) {
|
|
|
|
n++;
|
2001-12-23 23:23:41 +00:00
|
|
|
add_asterisk = PR_TRUE;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
while (*token == ' ' || *token == '\x9') token++;
|
|
|
|
char* trim;
|
|
|
|
trim = PL_strpbrk(token, "; \x9");
|
|
|
|
if (trim != (char*)0) // remove "; q=..." if present
|
|
|
|
*trim = '\0';
|
|
|
|
|
|
|
|
if (*token != '\0') {
|
2002-11-20 20:51:12 +00:00
|
|
|
comma = n++ != 0 ? "," : ""; // delimiter if not first item
|
2001-05-11 21:04:09 +00:00
|
|
|
if (q < 0.9995)
|
2002-11-20 20:51:12 +00:00
|
|
|
wrote = PR_snprintf(p2, available, "%s%s;q=0.%01u", comma, token, QVAL_TO_UINT(q));
|
2001-05-11 21:04:09 +00:00
|
|
|
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) {
|
2002-11-20 20:51:12 +00:00
|
|
|
comma = n++ != 0 ? "," : ""; // delimiter if not first item
|
2001-05-11 21:04:09 +00:00
|
|
|
if (q < 0.9995)
|
2002-11-20 20:51:12 +00:00
|
|
|
wrote = PR_snprintf(p2, available, "%sutf-8;q=0.%01u", comma, QVAL_TO_UINT(q));
|
2001-05-11 21:04:09 +00:00
|
|
|
else
|
|
|
|
wrote = PR_snprintf(p2, available, "%sutf-8", comma);
|
|
|
|
q -= dec;
|
|
|
|
p2 += wrote;
|
|
|
|
available -= wrote;
|
|
|
|
NS_ASSERTION(available > 0, "allocated string not long enough");
|
|
|
|
}
|
2001-12-23 23:23:41 +00:00
|
|
|
if (add_asterisk) {
|
2002-11-20 20:51:12 +00:00
|
|
|
comma = n++ != 0 ? "," : ""; // delimiter if not first item
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
if (q < 0.9995) {
|
2002-11-20 20:51:12 +00:00
|
|
|
wrote = PR_snprintf(p2, available, "%s*;q=0.%01u", comma, QVAL_TO_UINT(q));
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
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))
|
2002-03-20 22:50:33 +00:00
|
|
|
mAcceptCharsets.Assign(buf);
|
2001-05-11 21:04:09 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2001-05-17 00:17:34 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::SetAccept(const char *aAccept)
|
|
|
|
{
|
|
|
|
mAccept = aAccept;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
nsresult
|
|
|
|
nsHttpHandler::SetAcceptEncodings(const char *aAcceptEncodings)
|
|
|
|
{
|
|
|
|
mAcceptEncodings = aAcceptEncodings;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsHttpHandler::nsISupports
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-09-13 02:21:05 +00:00
|
|
|
NS_IMPL_THREADSAFE_ISUPPORTS5(nsHttpHandler,
|
2001-05-11 21:04:09 +00:00
|
|
|
nsIHttpProtocolHandler,
|
2001-09-13 02:21:05 +00:00
|
|
|
nsIProxiedProtocolHandler,
|
2001-05-11 21:04:09 +00:00
|
|
|
nsIProtocolHandler,
|
|
|
|
nsIObserver,
|
|
|
|
nsISupportsWeakReference)
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsHttpHandler::nsIProtocolHandler
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-06 07:48:55 +00:00
|
|
|
nsHttpHandler::GetScheme(nsACString &aScheme)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-08-13 20:33:45 +00:00
|
|
|
aScheme = NS_LITERAL_CSTRING("http");
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-08-13 20:33:45 +00:00
|
|
|
nsHttpHandler::GetDefaultPort(PRInt32 *result)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-08-13 20:33:45 +00:00
|
|
|
*result = 80;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2001-08-07 20:42:57 +00:00
|
|
|
NS_IMETHODIMP
|
2001-09-13 02:21:05 +00:00
|
|
|
nsHttpHandler::GetProtocolFlags(PRUint32 *result)
|
2001-08-07 20:42:57 +00:00
|
|
|
{
|
2001-09-13 02:21:05 +00:00
|
|
|
*result = URI_STD | ALLOWS_PROXY | ALLOWS_PROXY_HTTP;
|
2001-08-07 20:42:57 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
NS_IMETHODIMP
|
2002-03-06 07:48:55 +00:00
|
|
|
nsHttpHandler::NewURI(const nsACString &aSpec,
|
|
|
|
const char *aCharset,
|
|
|
|
nsIURI *aBaseURI,
|
|
|
|
nsIURI **aURI)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
LOG(("nsHttpHandler::NewURI\n"));
|
|
|
|
|
2002-10-06 02:20:35 +00:00
|
|
|
nsCOMPtr<nsIStandardURL> url;
|
|
|
|
NS_NEWXPCOM(url, nsStandardURL);
|
|
|
|
if (!url)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
// use the correct default port
|
|
|
|
PRInt32 defaultPort;
|
|
|
|
GetDefaultPort(&defaultPort);
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2002-10-06 02:20:35 +00:00
|
|
|
rv = url->Init(nsIStandardURL::URLTYPE_AUTHORITY,
|
|
|
|
defaultPort, aSpec, aCharset, aBaseURI);
|
2001-05-11 21:04:09 +00:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
return CallQueryInterface(url, 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-18 22:36:39 +00:00
|
|
|
return NewProxiedChannel(uri, nsnull, result);
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2001-06-06 00:10:09 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHttpHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval)
|
|
|
|
{
|
|
|
|
// don't override anything.
|
|
|
|
*_retval = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
2001-09-13 02:21:05 +00:00
|
|
|
// nsHttpHandler::nsIProxiedProtocolHandler
|
2001-05-11 21:04:09 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
2001-09-13 02:21:05 +00:00
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
NS_IMETHODIMP
|
2001-09-13 02:21:05 +00:00
|
|
|
nsHttpHandler::NewProxiedChannel(nsIURI *uri,
|
|
|
|
nsIProxyInfo* proxyInfo,
|
|
|
|
nsIChannel **result)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
|
|
|
nsHttpChannel *httpChannel = nsnull;
|
|
|
|
|
2001-09-13 02:21:05 +00:00
|
|
|
LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
|
|
|
|
proxyInfo));
|
2001-05-11 21:04:09 +00:00
|
|
|
|
|
|
|
NS_NEWXPCOM(httpChannel, nsHttpChannel);
|
|
|
|
if (!httpChannel)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(httpChannel);
|
|
|
|
|
2002-04-18 22:36:39 +00:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// select proxy caps if using a non-transparent proxy
|
|
|
|
PRInt8 caps = mCapabilities;
|
|
|
|
if (proxyInfo && !nsCRT::strcmp(proxyInfo->Type(), "http")) {
|
|
|
|
// SSL tunneling should not use proxy settings
|
|
|
|
PRBool isHTTPS;
|
|
|
|
rv = uri->SchemeIs("https", &isHTTPS);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
if (!isHTTPS)
|
|
|
|
caps = mProxyCapabilities;
|
|
|
|
}
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2002-04-18 22:36:39 +00:00
|
|
|
rv = httpChannel->Init(uri, caps, proxyInfo);
|
2001-05-11 21:04:09 +00:00
|
|
|
|
2002-04-18 22:36:39 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_RELEASE(httpChannel);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
*result = httpChannel;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
2001-09-13 02:21:05 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsHttpHandler::nsIHttpProtocolHandler
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetUserAgent(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = UserAgent();
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetAppName(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mAppName;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetAppVersion(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mAppVersion;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetVendor(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mVendor;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::SetVendor(const nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
mVendor = value;
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetVendorSub(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mVendorSub;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::SetVendorSub(const nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
mVendorSub = value;
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetVendorComment(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mVendorComment;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::SetVendorComment(const nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
mVendorComment = value;
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetProduct(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mProduct;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::SetProduct(const nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
mProduct = value;
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetProductSub(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mProductSub;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::SetProductSub(const nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
mProductSub = value;
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetProductComment(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-22 21:25:58 +00:00
|
|
|
value = mProductComment;
|
2002-03-20 22:50:33 +00:00
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::SetProductComment(const nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
mProductComment = value;
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetPlatform(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-22 21:25:58 +00:00
|
|
|
value = mPlatform;
|
2002-03-20 22:50:33 +00:00
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetOscpu(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mOscpu;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetLanguage(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mLanguage;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::SetLanguage(const nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
mLanguage = value;
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::GetMisc(nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
value = mMisc;
|
|
|
|
return NS_OK;
|
2001-05-11 21:04:09 +00:00
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
2002-03-20 22:50:33 +00:00
|
|
|
nsHttpHandler::SetMisc(const nsACString &value)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
2002-03-20 22:50:33 +00:00
|
|
|
mMisc = value;
|
2001-05-11 21:04:09 +00:00
|
|
|
mUserAgentIsDirty = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsHttpHandler::nsIObserver
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHttpHandler::Observe(nsISupports *subject,
|
2001-10-19 20:52:59 +00:00
|
|
|
const char *topic,
|
2001-05-11 21:04:09 +00:00
|
|
|
const PRUnichar *data)
|
|
|
|
{
|
2002-04-19 22:25:23 +00:00
|
|
|
LOG(("nsHttpHandler::Observe [topic=\"%s\")]\n", topic));
|
|
|
|
|
2001-10-22 20:54:48 +00:00
|
|
|
if (!nsCRT::strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
|
2001-10-02 23:04:49 +00:00
|
|
|
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
|
|
|
|
if (prefBranch)
|
|
|
|
PrefsChanged(prefBranch, NS_ConvertUCS2toUTF8(data).get());
|
|
|
|
}
|
2002-10-14 14:42:13 +00:00
|
|
|
else if (!nsCRT::strcmp(topic, "profile-change-net-teardown") ||
|
2001-10-19 20:52:59 +00:00
|
|
|
!nsCRT::strcmp(topic, "session-logout")) {
|
2001-05-11 21:04:09 +00:00
|
|
|
// clear cache of all authentication credentials.
|
|
|
|
if (mAuthCache)
|
|
|
|
mAuthCache->ClearAll();
|
|
|
|
|
2002-04-20 05:40:24 +00:00
|
|
|
// kill mIdleConnections - these sockets could be holding onto other resources
|
|
|
|
// that need to be freed.
|
|
|
|
{
|
|
|
|
nsAutoLock lock(mConnectionLock);
|
|
|
|
DropConnections(mIdleConnections);
|
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
// need to reset the session start time since cache validation may
|
|
|
|
// depend on this value.
|
|
|
|
mSessionStartTime = NowInSeconds();
|
|
|
|
}
|
2001-12-07 01:40:18 +00:00
|
|
|
else if (!nsCRT::strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
|
|
|
if (mTimer) {
|
|
|
|
mTimer->Cancel();
|
|
|
|
mTimer = 0;
|
|
|
|
}
|
2002-11-06 13:01:42 +00:00
|
|
|
|
|
|
|
// If we don't call DropConnections here, we'll never get
|
|
|
|
// destroyed, since we own a reference to the connections in
|
|
|
|
// these arrays and they own a reference back to us.
|
|
|
|
{
|
|
|
|
nsAutoLock lock(mConnectionLock);
|
|
|
|
|
|
|
|
LOG(("dropping active connections...\n"));
|
|
|
|
DropConnections(mActiveConnections);
|
|
|
|
|
|
|
|
LOG(("dropping idle connections...\n"));
|
|
|
|
DropConnections(mIdleConnections);
|
|
|
|
}
|
2001-12-07 01:40:18 +00:00
|
|
|
}
|
|
|
|
|
2001-05-11 21:04:09 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsHttpHandler::nsPendingTransaction
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
nsHttpHandler::
|
|
|
|
nsPendingTransaction::nsPendingTransaction(nsHttpTransaction *trans,
|
|
|
|
nsHttpConnectionInfo *ci)
|
|
|
|
: mTransaction(trans)
|
|
|
|
, mConnectionInfo(ci)
|
2001-09-04 23:02:26 +00:00
|
|
|
, mBusy(0)
|
2001-05-11 21:04:09 +00:00
|
|
|
{
|
|
|
|
LOG(("Creating nsPendingTransaction @%x\n", this));
|
|
|
|
|
|
|
|
NS_PRECONDITION(mTransaction, "null transaction");
|
|
|
|
NS_PRECONDITION(mConnectionInfo, "null connection info");
|
|
|
|
|
|
|
|
NS_ADDREF(mTransaction);
|
|
|
|
NS_ADDREF(mConnectionInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsHttpHandler::
|
|
|
|
nsPendingTransaction::~nsPendingTransaction()
|
|
|
|
{
|
|
|
|
LOG(("Destroying nsPendingTransaction @%x\n", this));
|
|
|
|
|
|
|
|
NS_RELEASE(mTransaction);
|
|
|
|
NS_RELEASE(mConnectionInfo);
|
|
|
|
}
|
2002-04-19 22:25:23 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// nsHttpHandler::nsPipelineEnqueueState
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
nsresult nsHttpHandler::
|
|
|
|
nsPipelineEnqueueState::Init(nsHttpTransaction *firstTrans)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mPipeline == nsnull, "already initialized");
|
|
|
|
|
|
|
|
mPipeline = new nsHttpPipeline;
|
|
|
|
if (!mPipeline)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
NS_ADDREF(mPipeline);
|
|
|
|
|
|
|
|
return mPipeline->Init(firstTrans);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsHttpHandler::
|
|
|
|
nsPipelineEnqueueState::AppendTransaction(nsPendingTransaction *pt)
|
|
|
|
{
|
|
|
|
nsresult rv = mPipeline->AppendTransaction(pt->Transaction());
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
// remember this pending transaction object
|
|
|
|
mAppendedTrans.AppendElement(pt);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsHttpHandler::
|
|
|
|
nsPipelineEnqueueState::Cleanup()
|
|
|
|
{
|
|
|
|
NS_IF_RELEASE(mPipeline);
|
|
|
|
|
|
|
|
// free any appended pending transaction objects
|
|
|
|
for (PRInt32 i=0; i < mAppendedTrans.Count(); i++)
|
|
|
|
delete GetAppendedTrans(i);
|
|
|
|
mAppendedTrans.Clear();
|
|
|
|
}
|
2002-08-13 20:33:45 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// 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 = NS_LITERAL_CSTRING("https");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHttpsHandler::GetDefaultPort(PRInt32 *aPort)
|
|
|
|
{
|
|
|
|
*aPort = 443;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHttpsHandler::GetProtocolFlags(PRUint32 *aProtocolFlags)
|
|
|
|
{
|
|
|
|
return nsHttpHandler::get()->GetProtocolFlags(aProtocolFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHttpsHandler::NewURI(const nsACString &aSpec,
|
|
|
|
const char *aOriginCharset,
|
|
|
|
nsIURI *aBaseURI,
|
|
|
|
nsIURI **_retval)
|
|
|
|
{
|
|
|
|
return nsHttpHandler::get()->NewURI(aSpec, aOriginCharset, aBaseURI, _retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHttpsHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
|
|
|
|
{
|
|
|
|
return nsHttpHandler::get()->NewChannel(aURI, _retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHttpsHandler::AllowPort(PRInt32 aPort, const char *aScheme, PRBool *_retval)
|
|
|
|
{
|
|
|
|
// don't override anything.
|
|
|
|
*_retval = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|