Bug 546581: e10s HTTP: create common base class for HttpChannelChild and nsHttpChannel. a=dwitte, r=jae-seong, r=jduell

This commit is contained in:
Jason Duell 2010-04-07 01:43:09 -07:00
parent a3e35da054
commit 70617ee7a8
13 changed files with 1160 additions and 1570 deletions

View File

@ -0,0 +1,816 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Witte <dwitte@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/net/HttpBaseChannel.h"
#include "nsHttpHandler.h"
#include "nsMimeTypes.h"
#include "nsNetUtil.h"
#define DROP_DEAD() \
do { \
fprintf(stderr, \
"*&*&*&*&*&*&*&**&*&&*& FATAL ERROR: '%s' UNIMPLEMENTED: %s +%d", \
__FUNCTION__, __FILE__, __LINE__); \
NS_ABORT(); \
return NS_ERROR_NOT_IMPLEMENTED; \
} while (0)
namespace mozilla {
namespace net {
HttpBaseChannel::HttpBaseChannel()
: mStatus(NS_OK)
, mLoadFlags(LOAD_NORMAL)
, mCaps(0)
, mRedirectionLimit(gHttpHandler->RedirectionLimit())
, mIsPending(PR_FALSE)
, mWasOpened(PR_FALSE)
, mResponseHeadersModified(PR_FALSE)
, mAllowPipelining(PR_TRUE)
, mForceAllowThirdPartyCookie(PR_FALSE)
{
LOG(("Creating HttpBaseChannel @%x\n", this));
// grab a reference to the handler to ensure that it doesn't go away.
NS_ADDREF(gHttpHandler);
}
HttpBaseChannel::~HttpBaseChannel()
{
LOG(("Destroying HttpBaseChannel @%x\n", this));
nsHttpHandler* handler = gHttpHandler;
NS_RELEASE(handler);
}
nsresult
HttpBaseChannel::Init(nsIURI *aURI,
PRUint8 aCaps,
nsProxyInfo *aProxyInfo)
{
LOG(("HttpBaseChannel::Init [this=%p]\n", this));
NS_PRECONDITION(aURI, "null uri");
nsresult rv = nsHashPropertyBag::Init();
if (NS_FAILED(rv)) return rv;
mURI = aURI;
mOriginalURI = aURI;
mDocumentURI = nsnull;
mCaps = aCaps;
// Construct connection info object
nsCAutoString host;
PRInt32 port = -1;
PRBool usingSSL = PR_FALSE;
rv = mURI->SchemeIs("https", &usingSSL);
if (NS_FAILED(rv)) return rv;
rv = mURI->GetAsciiHost(host);
if (NS_FAILED(rv)) return rv;
// Reject the URL if it doesn't specify a host
if (host.IsEmpty())
return NS_ERROR_MALFORMED_URI;
rv = mURI->GetPort(&port);
if (NS_FAILED(rv)) return rv;
LOG(("host=%s port=%d\n", host.get(), port));
rv = mURI->GetAsciiSpec(mSpec);
if (NS_FAILED(rv)) return rv;
LOG(("uri=%s\n", mSpec.get()));
mConnectionInfo = new nsHttpConnectionInfo(host, port,
aProxyInfo, usingSSL);
if (!mConnectionInfo)
return NS_ERROR_OUT_OF_MEMORY;
// Set default request method
mRequestHead.SetMethod(nsHttp::Get);
// Set request headers
nsCAutoString hostLine;
rv = nsHttpHandler::GenerateHostPort(host, port, hostLine);
if (NS_FAILED(rv)) return rv;
rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
if (NS_FAILED(rv)) return rv;
rv = gHttpHandler->
AddStandardRequestHeaders(&mRequestHead.Headers(), aCaps,
!mConnectionInfo->UsingSSL() &&
mConnectionInfo->UsingHttpProxy());
return rv;
}
//-----------------------------------------------------------------------------
// HttpBaseChannel::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS_INHERITED4(HttpBaseChannel,
nsHashPropertyBag,
nsIRequest,
nsIChannel,
nsIHttpChannel,
nsIHttpChannelInternal)
//-----------------------------------------------------------------------------
// HttpBaseChannel::nsIRequest
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpBaseChannel::GetName(nsACString& aName)
{
aName = mSpec;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::IsPending(PRBool *aIsPending)
{
NS_ENSURE_ARG_POINTER(aIsPending);
*aIsPending = mIsPending;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetStatus(nsresult *aStatus)
{
NS_ENSURE_ARG_POINTER(aStatus);
*aStatus = mStatus;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetLoadGroup(nsILoadGroup **aLoadGroup)
{
NS_ENSURE_ARG_POINTER(aLoadGroup);
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
{
NS_ENSURE_ARG_POINTER(aLoadFlags);
*aLoadFlags = mLoadFlags;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
{
mLoadFlags = aLoadFlags;
return NS_OK;
}
//-----------------------------------------------------------------------------
// HttpBaseChannel::nsIChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpBaseChannel::GetOriginalURI(nsIURI **aOriginalURI)
{
NS_ENSURE_ARG_POINTER(aOriginalURI);
*aOriginalURI = mOriginalURI;
NS_ADDREF(*aOriginalURI);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetOriginalURI(nsIURI *aOriginalURI)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
NS_ENSURE_ARG_POINTER(aOriginalURI);
mOriginalURI = aOriginalURI;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetURI(nsIURI **aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
*aURI = mURI;
NS_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks)
{
*aCallbacks = mCallbacks;
NS_IF_ADDREF(*aCallbacks);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
{
mCallbacks = aCallbacks;
mProgressSink = nsnull;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetContentType(nsACString& aContentType)
{
if (!mResponseHead) {
aContentType.Truncate();
return NS_ERROR_NOT_AVAILABLE;
}
if (!mResponseHead->ContentType().IsEmpty()) {
aContentType = mResponseHead->ContentType();
return NS_OK;
}
aContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetContentType(const nsACString& aContentType)
{
if (mListener || mWasOpened) {
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
nsCAutoString contentTypeBuf, charsetBuf;
PRBool hadCharset;
net_ParseContentType(aContentType, contentTypeBuf, charsetBuf, &hadCharset);
mResponseHead->SetContentType(contentTypeBuf);
// take care not to stomp on an existing charset
if (hadCharset)
mResponseHead->SetContentCharset(charsetBuf);
} else {
// We are being given a content-type hint.
PRBool dummy;
net_ParseContentType(aContentType, mContentTypeHint, mContentCharsetHint,
&dummy);
}
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetContentCharset(nsACString& aContentCharset)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
aContentCharset = mResponseHead->ContentCharset();
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetContentCharset(const nsACString& aContentCharset)
{
if (mListener) {
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
mResponseHead->SetContentCharset(aContentCharset);
} else {
// Charset hint
mContentCharsetHint = aContentCharset;
}
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetContentLength(PRInt32 *aContentLength)
{
NS_ENSURE_ARG_POINTER(aContentLength);
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
// XXX truncates to 32 bit
*aContentLength = mResponseHead->ContentLength();
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetContentLength(PRInt32 value)
{
NS_NOTYETIMPLEMENTED("nsHttpChannel::SetContentLength");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
HttpBaseChannel::Open(nsIInputStream **aResult)
{
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
return NS_ImplementChannelOpen(this, aResult);
}
//-----------------------------------------------------------------------------
// HttpBaseChannel::nsIHttpChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpBaseChannel::GetRequestMethod(nsACString& aMethod)
{
aMethod = mRequestHead.Method();
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetRequestMethod(const nsACString& aMethod)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
const nsCString& flatMethod = PromiseFlatCString(aMethod);
// Method names are restricted to valid HTTP tokens.
if (!nsHttp::IsValidToken(flatMethod))
return NS_ERROR_INVALID_ARG;
nsHttpAtom atom = nsHttp::ResolveAtom(flatMethod.get());
if (!atom)
return NS_ERROR_FAILURE;
mRequestHead.SetMethod(atom);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetReferrer(nsIURI **referrer)
{
NS_ENSURE_ARG_POINTER(referrer);
*referrer = mReferrer;
NS_IF_ADDREF(*referrer);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetReferrer(nsIURI *referrer)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
// clear existing referrer, if any
mReferrer = nsnull;
mRequestHead.ClearHeader(nsHttp::Referer);
if (!referrer)
return NS_OK;
// check referrer blocking pref
PRUint32 referrerLevel;
if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)
referrerLevel = 1; // user action
else
referrerLevel = 2; // inline content
if (gHttpHandler->ReferrerLevel() < referrerLevel)
return NS_OK;
nsCOMPtr<nsIURI> referrerGrip;
nsresult rv;
PRBool match;
//
// Strip off "wyciwyg://123/" from wyciwyg referrers.
//
// XXX this really belongs elsewhere since wyciwyg URLs aren't part of necko.
// perhaps some sort of generic nsINestedURI could be used. then, if an URI
// fails the whitelist test, then we could check for an inner URI and try
// that instead. though, that might be too automatic.
//
rv = referrer->SchemeIs("wyciwyg", &match);
if (NS_FAILED(rv)) return rv;
if (match) {
nsCAutoString path;
rv = referrer->GetPath(path);
if (NS_FAILED(rv)) return rv;
PRUint32 pathLength = path.Length();
if (pathLength <= 2) return NS_ERROR_FAILURE;
// Path is of the form "//123/http://foo/bar", with a variable number of digits.
// To figure out where the "real" URL starts, search path for a '/', starting at
// the third character.
PRInt32 slashIndex = path.FindChar('/', 2);
if (slashIndex == kNotFound) return NS_ERROR_FAILURE;
// Get the charset of the original URI so we can pass it to our fixed up URI.
nsCAutoString charset;
referrer->GetOriginCharset(charset);
// Replace |referrer| with a URI without wyciwyg://123/.
rv = NS_NewURI(getter_AddRefs(referrerGrip),
Substring(path, slashIndex + 1, pathLength - slashIndex - 1),
charset.get());
if (NS_FAILED(rv)) return rv;
referrer = referrerGrip.get();
}
//
// block referrer if not on our white list...
//
static const char *const referrerWhiteList[] = {
"http",
"https",
"ftp",
"gopher",
nsnull
};
match = PR_FALSE;
const char *const *scheme = referrerWhiteList;
for (; *scheme && !match; ++scheme) {
rv = referrer->SchemeIs(*scheme, &match);
if (NS_FAILED(rv)) return rv;
}
if (!match)
return NS_OK; // kick out....
//
// Handle secure referrals.
//
// Support referrals from a secure server if this is a secure site
// and (optionally) if the host names are the same.
//
rv = referrer->SchemeIs("https", &match);
if (NS_FAILED(rv)) return rv;
if (match) {
rv = mURI->SchemeIs("https", &match);
if (NS_FAILED(rv)) return rv;
if (!match)
return NS_OK;
if (!gHttpHandler->SendSecureXSiteReferrer()) {
nsCAutoString referrerHost;
nsCAutoString host;
rv = referrer->GetAsciiHost(referrerHost);
if (NS_FAILED(rv)) return rv;
rv = mURI->GetAsciiHost(host);
if (NS_FAILED(rv)) return rv;
// GetAsciiHost returns lowercase hostname.
if (!referrerHost.Equals(host))
return NS_OK;
}
}
nsCOMPtr<nsIURI> clone;
//
// we need to clone the referrer, so we can:
// (1) modify it
// (2) keep a reference to it after returning from this function
//
rv = referrer->Clone(getter_AddRefs(clone));
if (NS_FAILED(rv)) return rv;
// strip away any userpass; we don't want to be giving out passwords ;-)
clone->SetUserPass(EmptyCString());
// strip away any fragment per RFC 2616 section 14.36
nsCOMPtr<nsIURL> url = do_QueryInterface(clone);
if (url)
url->SetRef(EmptyCString());
nsCAutoString spec;
rv = clone->GetAsciiSpec(spec);
if (NS_FAILED(rv)) return rv;
// finally, remember the referrer URI and set the Referer header.
mReferrer = clone;
mRequestHead.SetHeader(nsHttp::Referer, spec);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetRequestHeader(const nsACString& aHeader,
nsACString& aValue)
{
// XXX might be better to search the header list directly instead of
// hitting the http atom hash table.
nsHttpAtom atom = nsHttp::ResolveAtom(aHeader);
if (!atom)
return NS_ERROR_NOT_AVAILABLE;
return mRequestHead.GetHeader(atom, aValue);
}
NS_IMETHODIMP
HttpBaseChannel::SetRequestHeader(const nsACString& aHeader,
const nsACString& aValue,
PRBool aMerge)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
const nsCString &flatHeader = PromiseFlatCString(aHeader);
const nsCString &flatValue = PromiseFlatCString(aValue);
LOG(("HttpBaseChannel::SetRequestHeader [this=%p header=\"%s\" value=\"%s\" merge=%u]\n",
this, flatHeader.get(), flatValue.get(), aMerge));
// Header names are restricted to valid HTTP tokens.
if (!nsHttp::IsValidToken(flatHeader))
return NS_ERROR_INVALID_ARG;
// Header values MUST NOT contain line-breaks. RFC 2616 technically
// permits CTL characters, including CR and LF, in header values provided
// they are quoted. However, this can lead to problems if servers do not
// interpret quoted strings properly. Disallowing CR and LF here seems
// reasonable and keeps things simple. We also disallow a null byte.
if (flatValue.FindCharInSet("\r\n") != kNotFound ||
flatValue.Length() != strlen(flatValue.get()))
return NS_ERROR_INVALID_ARG;
nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get());
if (!atom) {
NS_WARNING("failed to resolve atom");
return NS_ERROR_NOT_AVAILABLE;
}
return mRequestHead.SetHeader(atom, flatValue, aMerge);
}
NS_IMETHODIMP
HttpBaseChannel::VisitRequestHeaders(nsIHttpHeaderVisitor *visitor)
{
return mRequestHead.Headers().VisitHeaders(visitor);
}
NS_IMETHODIMP
HttpBaseChannel::GetResponseHeader(const nsACString &header, nsACString &value)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
nsHttpAtom atom = nsHttp::ResolveAtom(header);
if (!atom)
return NS_ERROR_NOT_AVAILABLE;
return mResponseHead->GetHeader(atom, value);
}
NS_IMETHODIMP
HttpBaseChannel::SetResponseHeader(const nsACString& header,
const nsACString& value,
PRBool merge)
{
LOG(("HttpBaseChannel::SetResponseHeader [this=%p header=\"%s\" value=\"%s\" merge=%u]\n",
this, PromiseFlatCString(header).get(), PromiseFlatCString(value).get(), merge));
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
nsHttpAtom atom = nsHttp::ResolveAtom(header);
if (!atom)
return NS_ERROR_NOT_AVAILABLE;
// these response headers must not be changed
if (atom == nsHttp::Content_Type ||
atom == nsHttp::Content_Length ||
atom == nsHttp::Content_Encoding ||
atom == nsHttp::Trailer ||
atom == nsHttp::Transfer_Encoding)
return NS_ERROR_ILLEGAL_VALUE;
mResponseHeadersModified = PR_TRUE;
return mResponseHead->SetHeader(atom, value, merge);
}
NS_IMETHODIMP
HttpBaseChannel::VisitResponseHeaders(nsIHttpHeaderVisitor *visitor)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
return mResponseHead->Headers().VisitHeaders(visitor);
}
NS_IMETHODIMP
HttpBaseChannel::GetAllowPipelining(PRBool *value)
{
NS_ENSURE_ARG_POINTER(value);
*value = mAllowPipelining;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetAllowPipelining(PRBool value)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
mAllowPipelining = value;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetRedirectionLimit(PRUint32 *value)
{
NS_ENSURE_ARG_POINTER(value);
*value = mRedirectionLimit;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetRedirectionLimit(PRUint32 value)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
mRedirectionLimit = PR_MIN(value, 0xff);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::IsNoStoreResponse(PRBool *value)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
*value = mResponseHead->NoStore();
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::IsNoCacheResponse(PRBool *value)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
*value = mResponseHead->NoCache();
if (!*value)
*value = mResponseHead->ExpiresInPast();
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetResponseStatus(PRUint32 *aValue)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
*aValue = mResponseHead->Status();
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetResponseStatusText(nsACString& aValue)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
aValue = mResponseHead->StatusText();
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetRequestSucceeded(PRBool *aValue)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
PRUint32 status = mResponseHead->Status();
*aValue = (status / 100 == 2);
return NS_OK;
}
//-----------------------------------------------------------------------------
// HttpBaseChannel::nsIHttpChannelInternal
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpBaseChannel::GetDocumentURI(nsIURI **aDocumentURI)
{
NS_ENSURE_ARG_POINTER(aDocumentURI);
*aDocumentURI = mDocumentURI;
NS_IF_ADDREF(*aDocumentURI);
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetDocumentURI(nsIURI *aDocumentURI)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
mDocumentURI = aDocumentURI;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetRequestVersion(PRUint32 *major, PRUint32 *minor)
{
nsHttpVersion version = mRequestHead.Version();
if (major) { *major = version / 10; }
if (minor) { *minor = version % 10; }
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetResponseVersion(PRUint32 *major, PRUint32 *minor)
{
if (!mResponseHead)
{
*major = *minor = 0; // we should at least be kind about it
return NS_ERROR_NOT_AVAILABLE;
}
nsHttpVersion version = mResponseHead->Version();
if (major) { *major = version / 10; }
if (minor) { *minor = version % 10; }
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetCookie(const char *aCookieHeader)
{
if (mLoadFlags & LOAD_ANONYMOUS)
return NS_OK;
// empty header isn't an error
if (!(aCookieHeader && *aCookieHeader))
return NS_OK;
nsICookieService *cs = gHttpHandler->GetCookieService();
NS_ENSURE_TRUE(cs, NS_ERROR_FAILURE);
return cs->SetCookieStringFromHttp(mURI,
nsnull,
nsnull,
aCookieHeader,
mResponseHead->PeekHeader(nsHttp::Date),
this);
}
NS_IMETHODIMP
HttpBaseChannel::GetForceAllowThirdPartyCookie(PRBool *aForce)
{
*aForce = mForceAllowThirdPartyCookie;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetForceAllowThirdPartyCookie(PRBool aForce)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
mForceAllowThirdPartyCookie = aForce;
return NS_OK;
}
//------------------------------------------------------------------------------
}
}

View File

@ -0,0 +1,186 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Daniel Witte <dwitte@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_net_HttpBaseChannel_h
#define mozilla_net_HttpBaseChannel_h
#include "nsHttp.h"
#include "nsAutoPtr.h"
#include "nsHashPropertyBag.h"
#include "nsProxyInfo.h"
#include "nsHttpRequestHead.h"
#include "nsHttpResponseHead.h"
#include "nsHttpConnectionInfo.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIProgressEventSink.h"
#include "nsIURI.h"
#define DIE_WITH_ASYNC_OPEN_MSG() \
do { \
fprintf(stderr, \
"*&*&*&*&*&*&*&**&*&&*& FATAL ERROR: '%s' " \
"called after AsyncOpen: %s +%d", \
__FUNCTION__, __FILE__, __LINE__); \
NS_ABORT(); \
return NS_ERROR_NOT_IMPLEMENTED; \
} while (0)
#define ENSURE_CALLED_BEFORE_ASYNC_OPEN() \
if (mIsPending) \
DIE_WITH_ASYNC_OPEN_MSG(); \
if (mWasOpened) \
DIE_WITH_ASYNC_OPEN_MSG(); \
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); \
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
namespace mozilla {
namespace net {
/*
* This class is a partial implementation of nsIHttpChannel. It contains code
* shared by nsHttpChannel and HttpChannelChild.
* - Note that this class has nothing to do with nsBaseChannel, which is an
* earlier effort at a base class for channels that somehow never made it all
* the way to the HTTP channel.
*/
class HttpBaseChannel : public nsHashPropertyBag
, public nsIHttpChannel
, public nsIHttpChannelInternal
{
public:
NS_DECL_ISUPPORTS_INHERITED
HttpBaseChannel();
virtual ~HttpBaseChannel();
nsresult Init(nsIURI *aURI, PRUint8 aCaps, nsProxyInfo *aProxyInfo);
// nsIRequest
NS_IMETHOD GetName(nsACString& aName);
NS_IMETHOD IsPending(PRBool *aIsPending);
NS_IMETHOD GetStatus(nsresult *aStatus);
NS_IMETHOD GetLoadGroup(nsILoadGroup **aLoadGroup);
NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup);
NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags);
NS_IMETHOD SetLoadFlags(nsLoadFlags aLoadFlags);
// nsIChannel
NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI);
NS_IMETHOD SetOriginalURI(nsIURI *aOriginalURI);
NS_IMETHOD GetURI(nsIURI **aURI);
NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks);
NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks);
NS_IMETHOD GetContentType(nsACString& aContentType);
NS_IMETHOD SetContentType(const nsACString& aContentType);
NS_IMETHOD GetContentCharset(nsACString& aContentCharset);
NS_IMETHOD SetContentCharset(const nsACString& aContentCharset);
NS_IMETHOD GetContentLength(PRInt32 *aContentLength);
NS_IMETHOD SetContentLength(PRInt32 aContentLength);
NS_IMETHOD Open(nsIInputStream **aResult);
// HttpBaseChannel::nsIHttpChannel
NS_IMETHOD GetRequestMethod(nsACString& aMethod);
NS_IMETHOD SetRequestMethod(const nsACString& aMethod);
NS_IMETHOD GetReferrer(nsIURI **referrer);
NS_IMETHOD SetReferrer(nsIURI *referrer);
NS_IMETHOD GetRequestHeader(const nsACString& aHeader, nsACString& aValue);
NS_IMETHOD SetRequestHeader(const nsACString& aHeader,
const nsACString& aValue, PRBool aMerge);
NS_IMETHOD VisitRequestHeaders(nsIHttpHeaderVisitor *visitor);
NS_IMETHOD GetResponseHeader(const nsACString &header, nsACString &value);
NS_IMETHOD SetResponseHeader(const nsACString& header,
const nsACString& value, PRBool merge);
NS_IMETHOD VisitResponseHeaders(nsIHttpHeaderVisitor *visitor);
NS_IMETHOD GetAllowPipelining(PRBool *value);
NS_IMETHOD SetAllowPipelining(PRBool value);
NS_IMETHOD GetRedirectionLimit(PRUint32 *value);
NS_IMETHOD SetRedirectionLimit(PRUint32 value);
NS_IMETHOD IsNoStoreResponse(PRBool *value);
NS_IMETHOD IsNoCacheResponse(PRBool *value);
NS_IMETHOD GetResponseStatus(PRUint32 *aValue);
NS_IMETHOD GetResponseStatusText(nsACString& aValue);
NS_IMETHOD GetRequestSucceeded(PRBool *aValue);
// nsIHttpChannelInternal
NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI);
NS_IMETHOD SetDocumentURI(nsIURI *aDocumentURI);
NS_IMETHOD GetRequestVersion(PRUint32 *major, PRUint32 *minor);
NS_IMETHOD GetResponseVersion(PRUint32 *major, PRUint32 *minor);
NS_IMETHOD SetCookie(const char *aCookieHeader);
NS_IMETHOD GetForceAllowThirdPartyCookie(PRBool *aForce);
NS_IMETHOD SetForceAllowThirdPartyCookie(PRBool aForce);
protected:
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mListenerContext;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIURI> mReferrer;
nsHttpRequestHead mRequestHead;
nsAutoPtr<nsHttpResponseHead> mResponseHead;
nsRefPtr<nsHttpConnectionInfo> mConnectionInfo;
nsCString mSpec; // ASCII encoded URL spec
nsCString mContentTypeHint;
nsCString mContentCharsetHint;
nsresult mStatus;
PRUint32 mLoadFlags;
PRUint8 mCaps;
PRUint8 mRedirectionLimit;
PRUint8 mIsPending : 1;
PRUint8 mWasOpened : 1;
PRUint8 mResponseHeadersModified : 1;
PRUint8 mAllowPipelining : 1;
PRUint8 mForceAllowThirdPartyCookie : 1;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_HttpBaseChannel_h

View File

@ -23,6 +23,7 @@
*
* Contributor(s):
* Jason Duell <jduell.mcbugs@gmail.com>
* Daniel Witte <dwitte@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -47,146 +48,27 @@
#include "nsMimeTypes.h"
#include "nsNetUtil.h"
// - TODO: Can we add these checks to nsHttpChannel.cpp too?
#define ENSURE_CALLED_BEFORE_ASYNC_OPEN() \
if (mIsPending) \
DROP_DEAD(); \
if (mWasOpened) \
DROP_DEAD(); \
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); \
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
namespace mozilla {
namespace net {
// C++ file contents
HttpChannelChild::HttpChannelChild()
: mState(HCC_NEW)
// FIELDS COPIED FROM nsHttpChannel.h
, mLoadFlags(LOAD_NORMAL)
, mStatus(NS_OK)
, mIsPending(PR_FALSE)
, mWasOpened(PR_FALSE)
{
LOG(("Creating HttpChannelChild @%x\n", this));
// grab a reference to the handler to ensure that it doesn't go away.
NS_ADDREF(gHttpHandler);
}
HttpChannelChild::~HttpChannelChild()
{
LOG(("Destroying HttpChannelChild @%x\n", this));
// release our reference to the handler
NS_RELEASE(gHttpHandler);
}
nsresult
HttpChannelChild::Init(nsIURI *uri)
{
/**
* COPIED from nsHttpChannel and tweaked: merge into base class?
*/
LOG(("HttpChannelChild::Init [this=%x]\n", this));
NS_PRECONDITION(uri, "null uri");
nsresult rv = nsHashPropertyBag::Init();
if (NS_FAILED(rv))
return rv;
mURI = uri;
mOriginalURI = uri;
mDocumentURI = nsnull;
// mCaps = caps;
//
// Construct connection info object
//
nsCAutoString host;
PRInt32 port = -1;
PRBool usingSSL = PR_FALSE;
rv = mURI->SchemeIs("https", &usingSSL);
if (NS_FAILED(rv)) return rv;
rv = mURI->GetAsciiHost(host);
if (NS_FAILED(rv)) return rv;
// reject the URL if it doesn't specify a host
if (host.IsEmpty())
return NS_ERROR_MALFORMED_URI;
rv = mURI->GetPort(&port);
if (NS_FAILED(rv)) return rv;
LOG(("host=%s port=%d\n", host.get(), port));
rv = mURI->GetAsciiSpec(mSpec);
if (NS_FAILED(rv)) return rv;
LOG(("uri=%s\n", mSpec.get()));
#if 0
// Not yet clear that we need this in child
mConnectionInfo = new nsHttpConnectionInfo(host, port,
proxyInfo, usingSSL);
if (!mConnectionInfo)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mConnectionInfo);
#endif
// Set default request method
mRequestHead.SetMethod(nsHttp::Get);
#if 0
// FIXME (bug 541017): split this out into a separate function so we can share
// with nsHttpChannel.
// - Make sure not to set any headers twice on parent.
//
// Set request headers
//
nsCAutoString hostLine;
if (strchr(host.get(), ':')) {
// host is an IPv6 address literal and must be encapsulated in []'s
hostLine.Assign('[');
// scope id is not needed for Host header.
int scopeIdPos = host.FindChar('%');
if (scopeIdPos == kNotFound)
hostLine.Append(host);
else if (scopeIdPos > 0)
hostLine.Append(Substring(host, 0, scopeIdPos));
else
return NS_ERROR_MALFORMED_URI;
hostLine.Append(']');
}
else
hostLine.Assign(host);
if (port != -1) {
hostLine.Append(':');
hostLine.AppendInt(port);
}
rv = mRequestHead.SetHeader(nsHttp::Host, hostLine);
if (NS_FAILED(rv)) return rv;
rv = gHttpHandler->
AddStandardRequestHeaders(&mRequestHead.Headers(), caps,
!mConnectionInfo->UsingSSL() &&
mConnectionInfo->UsingHttpProxy());
#endif /* 0 */
return rv;
}
//-----------------------------------------------------------------------------
// HttpChannelChild::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ADDREF_INHERITED(HttpChannelChild, nsHashPropertyBag)
NS_IMPL_RELEASE_INHERITED(HttpChannelChild, nsHashPropertyBag)
NS_IMPL_ADDREF_INHERITED(HttpChannelChild, HttpBaseChannel)
NS_IMPL_RELEASE_INHERITED(HttpChannelChild, HttpBaseChannel)
NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
NS_INTERFACE_MAP_ENTRY(nsIRequest)
@ -203,7 +85,7 @@ NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
//-----------------------------------------------------------------------------
// HttpChannelChild::PHttpChannelChild
@ -218,7 +100,7 @@ HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead)
mResponseHead = new nsHttpResponseHead(responseHead);
nsresult rv = mChildListener->OnStartRequest(this, mChildListenerContext);
nsresult rv = mListener->OnStartRequest(this, mListenerContext);
if (!NS_SUCCEEDED(rv)) {
// TODO: Cancel request:
// - Send Cancel msg to parent
@ -253,8 +135,8 @@ HttpChannelChild::RecvOnDataAvailable(const nsCString& data,
// TODO: what to do here? Cancel request? Very unlikely to fail.
return false;
}
rv = mChildListener->OnDataAvailable(this, mChildListenerContext,
stringStream, offset, count);
rv = mListener->OnDataAvailable(this, mListenerContext,
stringStream, offset, count);
stringStream->Close();
if (!NS_SUCCEEDED(rv)) {
// TODO: Cancel request: see notes in OnStartRequest
@ -273,10 +155,9 @@ HttpChannelChild::RecvOnStopRequest(const nsresult& statusCode)
mIsPending = PR_FALSE;
mStatus = statusCode;
nsresult rv = mChildListener->OnStopRequest(this, mChildListenerContext,
statusCode);
mChildListener = 0;
mChildListenerContext = 0;
nsresult rv = mListener->OnStopRequest(this, mListenerContext, statusCode);
mListener = 0;
mListenerContext = 0;
if (!NS_SUCCEEDED(rv)) {
// TODO: Cancel request: see notes in OnStartRequest
return false;
@ -289,35 +170,7 @@ HttpChannelChild::RecvOnStopRequest(const nsresult& statusCode)
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpChannelChild::GetName(nsACString& aName)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::IsPending(PRBool *retval)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
NS_ENSURE_ARG_POINTER(retval);
*retval = mIsPending;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetStatus(nsresult *aStatus)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
NS_ENSURE_ARG_POINTER(aStatus);
*aStatus = mStatus;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::Cancel(nsresult aStatus)
HttpChannelChild::Cancel(nsresult status)
{
DROP_DEAD();
}
@ -334,211 +187,27 @@ HttpChannelChild::Resume()
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetLoadGroup(nsILoadGroup **aLoadGroup)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::SetLoadGroup(nsILoadGroup *aLoadGroup)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetLoadFlags(nsLoadFlags *aLoadFlags)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
NS_ENSURE_ARG_POINTER(aLoadFlags);
*aLoadFlags = mLoadFlags;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetLoadFlags(nsLoadFlags aLoadFlags)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
mLoadFlags = aLoadFlags;
return NS_OK;
}
//-----------------------------------------------------------------------------
// HttpChannelChild::nsIChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpChannelChild::GetOriginalURI(nsIURI **originalURI)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
NS_ENSURE_ARG_POINTER(originalURI);
*originalURI = mOriginalURI;
NS_ADDREF(*originalURI);
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetOriginalURI(nsIURI *originalURI)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
NS_ENSURE_ARG_POINTER(originalURI);
mOriginalURI = originalURI;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetURI(nsIURI **URI)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
NS_ENSURE_ARG_POINTER(URI);
*URI = mURI;
NS_IF_ADDREF(*URI);
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetOwner(nsISupports **aOwner)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::SetOwner(nsISupports *aOwner)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetNotificationCallbacks(nsIInterfaceRequestor **callbacks)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
NS_IF_ADDREF(*callbacks = mCallbacks);
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetNotificationCallbacks(nsIInterfaceRequestor *callbacks)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
mCallbacks = callbacks;
mProgressSink = nsnull;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetSecurityInfo(nsISupports **aSecurityInfo)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetContentType(nsACString& value)
{
if (!mResponseHead) {
value.Truncate();
return NS_ERROR_NOT_AVAILABLE;
}
if (mResponseHead->ContentType().IsEmpty()) {
value.AssignLiteral(UNKNOWN_CONTENT_TYPE);
} else {
value = mResponseHead->ContentType();
}
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetContentType(const nsACString& aContentType)
{
return BaseClassSetContentType_HACK(aContentType);
}
nsresult
HttpChannelChild::BaseClassSetContentType_HACK(const nsACString &value)
{
if (mChildListener || mWasOpened) {
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
nsCAutoString contentTypeBuf, charsetBuf;
PRBool hadCharset;
net_ParseContentType(value, contentTypeBuf, charsetBuf, &hadCharset);
mResponseHead->SetContentType(contentTypeBuf);
// take care not to stomp on an existing charset
if (hadCharset)
mResponseHead->SetContentCharset(charsetBuf);
}
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetContentCharset(nsACString& aContentCharset)
{
return BaseClassGetContentCharset_HACK(aContentCharset);
}
nsresult
HttpChannelChild::BaseClassGetContentCharset_HACK(nsACString &value)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
value = mResponseHead->ContentCharset();
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetContentCharset(const nsACString& aContentCharset)
{
return BaseClassSetContentCharset_HACK(aContentCharset);
}
nsresult
HttpChannelChild::BaseClassSetContentCharset_HACK(const nsACString &value)
{
if (mChildListener) {
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
mResponseHead->SetContentCharset(value);
}
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetContentLength(PRInt32 *aContentLength)
{
*aContentLength = mResponseHead->ContentLength();
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetContentLength(PRInt32 aContentLength)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::Open(nsIInputStream **retval)
{
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_IN_PROGRESS);
return NS_ImplementChannelOpen(this, retval);
}
NS_IMETHODIMP
HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
{
@ -564,8 +233,14 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
// TODO: currently means "this" has been deleted! bug 529693
DROP_DEAD();
}
mChildListener = listener;
mChildListenerContext = aContext;
mListener = listener;
mListenerContext = aContext;
// TODO: serialize mConnectionInfo across to the parent, and set it on
// the new channel somehow?
// TODO: serialize mCaps across to the parent, and set it on
// the new channel somehow?
// TODO: need to dupe cookies logic from nsHttpChannel.cpp?
@ -589,11 +264,13 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
}
if (!SendAsyncOpen(mSpec, charset, originalSpec, originalCharset,
docSpec, docCharset, mLoadFlags, mRequestHeaders)) {
docSpec, docCharset, mLoadFlags, mRequestHeaders,
mRequestHead.Method(), mRedirectionLimit, mAllowPipelining,
mForceAllowThirdPartyCookie)) {
// IPDL error: our destructor will be called automatically
// -- TODO: verify that that's the case :)
mChildListener = 0;
mChildListenerContext = 0;
mListener = 0;
mListenerContext = 0;
return NS_ERROR_FAILURE;
}
@ -608,77 +285,12 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
// HttpChannelChild::nsIHttpChannel
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpChannelChild::GetRequestMethod(nsACString& method)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
method = mRequestHead.Method();
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetRequestMethod(const nsACString& method)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
* - TODO: pass along to parent in AsyncOpen
*/
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
const nsCString& flatMethod = PromiseFlatCString(method);
// Method names are restricted to valid HTTP tokens.
if (!nsHttp::IsValidToken(flatMethod))
return NS_ERROR_INVALID_ARG;
nsHttpAtom atom = nsHttp::ResolveAtom(flatMethod.get());
if (!atom)
return NS_ERROR_FAILURE;
mRequestHead.SetMethod(atom);
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetReferrer(nsIURI **aReferrer)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::SetReferrer(nsIURI *aReferrer)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetRequestHeader(const nsACString& hdr, nsACString& val)
{
return BaseClassGetRequestHeader_HACK(hdr, val);
}
nsresult
HttpChannelChild::BaseClassGetRequestHeader_HACK(const nsACString &header,
nsACString &value)
{
// XXX might be better to search the header list directly instead of
// hitting the http atom hash table.
nsHttpAtom atom = nsHttp::ResolveAtom(header);
if (!atom)
return NS_ERROR_NOT_AVAILABLE;
return mRequestHead.GetHeader(atom, value);
}
NS_IMETHODIMP
HttpChannelChild::SetRequestHeader(const nsACString& aHeader,
const nsACString& aValue,
PRBool aMerge)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
nsresult rv = BaseClassSetRequestHeader_HACK(aHeader, aValue, aMerge);
nsresult rv = HttpBaseChannel::SetRequestHeader(aHeader, aValue, aMerge);
if (NS_FAILED(rv))
return rv;
@ -692,229 +304,16 @@ HttpChannelChild::SetRequestHeader(const nsACString& aHeader,
return NS_OK;
}
nsresult
HttpChannelChild::BaseClassSetRequestHeader_HACK(const nsACString &header,
const nsACString &value,
PRBool merge)
{
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
const nsCString &flatHeader = PromiseFlatCString(header);
const nsCString &flatValue = PromiseFlatCString(value);
LOG(("nsHttpChannel::SetRequestHeader [this=%x header=\"%s\" value=\"%s\" merge=%u]\n",
this, flatHeader.get(), flatValue.get(), merge));
// Header names are restricted to valid HTTP tokens.
if (!nsHttp::IsValidToken(flatHeader))
return NS_ERROR_INVALID_ARG;
// Header values MUST NOT contain line-breaks. RFC 2616 technically
// permits CTL characters, including CR and LF, in header values provided
// they are quoted. However, this can lead to problems if servers do not
// interpret quoted strings properly. Disallowing CR and LF here seems
// reasonable and keeps things simple. We also disallow a null byte.
if (flatValue.FindCharInSet("\r\n") != kNotFound ||
flatValue.Length() != strlen(flatValue.get()))
return NS_ERROR_INVALID_ARG;
nsHttpAtom atom = nsHttp::ResolveAtom(flatHeader.get());
if (!atom) {
NS_WARNING("failed to resolve atom");
return NS_ERROR_NOT_AVAILABLE;
}
return mRequestHead.SetHeader(atom, flatValue, merge);
}
NS_IMETHODIMP
HttpChannelChild::VisitRequestHeaders(nsIHttpHeaderVisitor *aVisitor)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetAllowPipelining(PRBool *aAllowPipelining)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::SetAllowPipelining(PRBool aAllowPipelining)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetRedirectionLimit(PRUint32 *aRedirectionLimit)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::SetRedirectionLimit(PRUint32 aRedirectionLimit)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetResponseStatus(PRUint32 *value)
{
NS_ENSURE_ARG_POINTER(value);
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
*value = mResponseHead->Status();
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetResponseStatusText(nsACString& value)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
value = mResponseHead->StatusText();
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetRequestSucceeded(PRBool *value)
{
NS_PRECONDITION(value, "Don't ever pass a null arg to this function");
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
PRUint32 status = mResponseHead->Status();
*value = (status / 100 == 2);
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetResponseHeader(const nsACString& header, nsACString& val)
{
return BaseClassGetResponseHeader_HACK(header, val);
}
nsresult
HttpChannelChild::BaseClassGetResponseHeader_HACK(const nsACString &header,
nsACString &value)
{
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
nsHttpAtom atom = nsHttp::ResolveAtom(header);
if (!atom)
return NS_ERROR_NOT_AVAILABLE;
return mResponseHead->GetHeader(atom, value);
}
NS_IMETHODIMP
HttpChannelChild::SetResponseHeader(const nsACString& header,
const nsACString& value,
PRBool merge)
{
return BaseClassSetResponseHeader_HACK(header, value, merge);
}
nsresult
HttpChannelChild::BaseClassSetResponseHeader_HACK(const nsACString &header,
const nsACString &value,
PRBool merge)
{
LOG(("nsHttpChannel::SetResponseHeader [this=%x header=\"%s\" value=\"%s\" merge=%u]\n",
this, PromiseFlatCString(header).get(), PromiseFlatCString(value).get(), merge));
if (!mResponseHead)
return NS_ERROR_NOT_AVAILABLE;
nsHttpAtom atom = nsHttp::ResolveAtom(header);
if (!atom)
return NS_ERROR_NOT_AVAILABLE;
// these response headers must not be changed
if (atom == nsHttp::Content_Type ||
atom == nsHttp::Content_Length ||
atom == nsHttp::Content_Encoding ||
atom == nsHttp::Trailer ||
atom == nsHttp::Transfer_Encoding)
return NS_ERROR_ILLEGAL_VALUE;
return mResponseHead->SetHeader(atom, value, merge);
}
NS_IMETHODIMP
HttpChannelChild::VisitResponseHeaders(nsIHttpHeaderVisitor *aVisitor)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::IsNoStoreResponse(PRBool *retval)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::IsNoCacheResponse(PRBool *retval)
{
DROP_DEAD();
}
//-----------------------------------------------------------------------------
// HttpChannelChild::nsIHttpChannelInternal
//-----------------------------------------------------------------------------
NS_IMETHODIMP
HttpChannelChild::GetDocumentURI(nsIURI **aDocumentURI)
{
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
NS_ENSURE_ARG_POINTER(aDocumentURI);
*aDocumentURI = mDocumentURI;
NS_IF_ADDREF(*aDocumentURI);
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::SetDocumentURI(nsIURI *aDocumentURI)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
/**
* COPIED from nsHttpChannel.cpp: move to shared base class?
*/
mDocumentURI = aDocumentURI;
return NS_OK;
}
NS_IMETHODIMP
HttpChannelChild::GetRequestVersion(PRUint32 *major, PRUint32 *minor)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetResponseVersion(PRUint32 *major, PRUint32 *minor)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::SetCookie(const char *aCookieHeader)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::GetForceAllowThirdPartyCookie(PRBool *force)
{
DROP_DEAD();
}
NS_IMETHODIMP
HttpChannelChild::SetForceAllowThirdPartyCookie(PRBool force)
{
DROP_DEAD();
}
//-----------------------------------------------------------------------------
// HttpChannelChild::nsICachingChannel

View File

@ -23,6 +23,7 @@
*
* Contributor(s):
* Jason Duell <jduell.mcbugs@gmail.com>
* Daniel Witte <dwitte@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -41,15 +42,10 @@
#ifndef mozilla_net_HttpChannelChild_h
#define mozilla_net_HttpChannelChild_h
#include "mozilla/net/HttpBaseChannel.h"
#include "mozilla/net/PHttpChannelChild.h"
#include "mozilla/net/NeckoCommon.h"
#include "nsHttpRequestHead.h"
#include "nsHashPropertyBag.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIStreamListener.h"
#include "nsIURI.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
@ -65,7 +61,6 @@
#include "nsIProxiedChannel.h"
#include "nsITraceableChannel.h"
namespace mozilla {
namespace net {
@ -80,9 +75,7 @@ enum HttpChannelChildState {
// Header file contents
class HttpChannelChild : public PHttpChannelChild
, public nsIHttpChannel
, public nsHashPropertyBag
, public nsIHttpChannelInternal
, public HttpBaseChannel
, public nsICachingChannel
, public nsIUploadChannel
, public nsIUploadChannel2
@ -95,10 +88,6 @@ class HttpChannelChild : public PHttpChannelChild
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
NS_DECL_NSIHTTPCHANNEL
NS_DECL_NSIHTTPCHANNELINTERNAL
NS_DECL_NSICACHINGCHANNEL
NS_DECL_NSIUPLOADCHANNEL
NS_DECL_NSIUPLOADCHANNEL2
@ -115,6 +104,24 @@ public:
nsresult Init(nsIURI *uri);
// Methods HttpBaseChannel didn't implement for us or that we override.
//
// nsIRequest
NS_IMETHOD Cancel(nsresult status);
NS_IMETHOD Suspend();
NS_IMETHOD Resume();
// nsIChannel
NS_IMETHOD GetOwner(nsISupports **aOwner);
NS_IMETHOD SetOwner(nsISupports *aOwner);
NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext);
// HttpBaseChannel::nsIHttpChannel
NS_IMETHOD SetRequestHeader(const nsACString& aHeader,
const nsACString& aValue,
PRBool aMerge);
// nsIHttpChannelInternal
NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey);
protected:
bool RecvOnStartRequest(const nsHttpResponseHead& responseHead);
bool RecvOnDataAvailable(const nsCString& data,
@ -123,54 +130,12 @@ protected:
bool RecvOnStopRequest(const nsresult& statusCode);
private:
nsresult BaseClassSetContentType_HACK(const nsACString &value);
nsresult BaseClassGetContentCharset_HACK(nsACString &value);
nsresult BaseClassSetContentCharset_HACK(const nsACString &value);
nsresult BaseClassSetRequestHeader_HACK(const nsACString &header,
const nsACString &value,
PRBool merge);
nsresult BaseClassGetRequestHeader_HACK(const nsACString &header,
nsACString &value);
nsresult BaseClassGetResponseHeader_HACK(const nsACString &header,
nsACString &value);
nsresult BaseClassSetResponseHeader_HACK(const nsACString &header,
const nsACString &value,
PRBool merge);
nsCOMPtr<nsIStreamListener> mChildListener;
nsCOMPtr<nsISupports> mChildListenerContext;
RequestHeaderTuples mRequestHeaders;
nsAutoPtr<nsHttpResponseHead> mResponseHead;
RequestHeaderTuples mRequestHeaders;
// FIXME: replace with IPDL states (bug 536319)
enum HttpChannelChildState mState;
/**
* fields copied from nsHttpChannel.h
*/
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsHttpRequestHead mRequestHead;
nsCString mSpec; // ASCII encoded URL spec
PRUint32 mLoadFlags;
PRUint32 mStatus;
// state flags
PRUint32 mIsPending : 1;
PRUint32 mWasOpened : 1;
};
} // namespace net
} // namespace mozilla

View File

@ -38,9 +38,9 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsHttp.h"
#include "mozilla/net/HttpChannelParent.h"
#include "nsHttpChannel.h"
#include "nsHttpHandler.h"
#include "nsNetUtil.h"
namespace mozilla {
@ -49,10 +49,15 @@ namespace net {
// C++ file contents
HttpChannelParent::HttpChannelParent()
{
// Ensure gHttpHandler is initialized: we need the atom table up and running.
nsIHttpProtocolHandler* handler;
CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &handler);
NS_ASSERTION(handler, "no http handler");
}
HttpChannelParent::~HttpChannelParent()
{
NS_RELEASE(gHttpHandler);
}
//-----------------------------------------------------------------------------
@ -76,8 +81,15 @@ HttpChannelParent::RecvAsyncOpen(const nsCString& uriSpec,
const nsCString& docUriSpec,
const nsCString& docCharset,
const PRUint32& loadFlags,
const RequestHeaderTuples& requestHeaders)
const RequestHeaderTuples& requestHeaders,
const nsHttpAtom& requestMethod,
const PRUint8& redirectionLimit,
const PRBool& allowPipelining,
const PRBool& forceAllowThirdPartyCookie)
{
LOG(("HttpChannelParent RecvAsyncOpen [this=%x uri=%s (%s)]\n",
this, uriSpec.get(), charset.get()));
nsresult rv;
nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
@ -89,16 +101,14 @@ HttpChannelParent::RecvAsyncOpen(const nsCString& uriSpec,
if (NS_FAILED(rv))
return false; // TODO: send fail msg to child, return true
// Delay log to here, as gHttpLog may not exist in parent until we init
// gHttpHandler via above call to NS_NewURI. Avoids segfault :)
LOG(("HttpChannelParent RecvAsyncOpen [this=%x uri=%s (%s)]\n",
this, uriSpec.get(), charset.get()));
nsCOMPtr<nsIChannel> chan;
rv = NS_NewChannel(getter_AddRefs(chan), uri, ios, nsnull, nsnull, loadFlags);
if (NS_FAILED(rv))
return false; // TODO: send fail msg to child, return true
nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
nsCOMPtr<nsIHttpChannelInternal> httpChanInt(do_QueryInterface(chan));
if (!originalUriSpec.IsEmpty()) {
nsCOMPtr<nsIURI> originalUri;
rv = NS_NewURI(getter_AddRefs(originalUri), originalUriSpec,
@ -111,15 +121,12 @@ HttpChannelParent::RecvAsyncOpen(const nsCString& uriSpec,
rv = NS_NewURI(getter_AddRefs(docUri), docUriSpec,
docCharset.get(), nsnull, ios);
if (!NS_FAILED(rv)) {
nsCOMPtr<nsIHttpChannelInternal> iChan(do_QueryInterface(chan));
if (iChan)
iChan->SetDocumentURI(docUri);
httpChanInt->SetDocumentURI(docUri);
}
}
if (loadFlags != nsIRequest::LOAD_NORMAL)
chan->SetLoadFlags(loadFlags);
nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
for (PRUint32 i = 0; i < requestHeaders.Length(); i++)
httpChan->SetRequestHeader(requestHeaders[i].mHeader,
requestHeaders[i].mValue,
@ -129,6 +136,11 @@ HttpChannelParent::RecvAsyncOpen(const nsCString& uriSpec,
// process, or rig up appropriate hacks.
// chan->SetNotificationCallbacks(this);
httpChan->SetRequestMethod(nsDependentCString(requestMethod.get()));
httpChan->SetRedirectionLimit(redirectionLimit);
httpChan->SetAllowPipelining(allowPipelining);
httpChanInt->SetForceAllowThirdPartyCookie(forceAllowThirdPartyCookie);
rv = chan->AsyncOpen(this, nsnull);
if (NS_FAILED(rv))
return false; // TODO: send fail msg to child, return true

View File

@ -72,7 +72,11 @@ protected:
const nsCString& docUriSpec,
const nsCString& docCharset,
const PRUint32& loadFlags,
const RequestHeaderTuples& requestHeaders);
const RequestHeaderTuples& requestHeaders,
const nsHttpAtom& requestMethod,
const PRUint8& redirectionLimit,
const PRBool& allowPipelining,
const PRBool& forceAllowThirdPartyCookie);
};
} // namespace net

View File

@ -46,10 +46,14 @@ MODULE = necko
LIBRARY_NAME = nkhttp_s
LIBXUL_LIBRARY = 1
ifdef MOZ_IPC
EXPORTS_NAMESPACES = mozilla/net
EXPORTS_mozilla/net = \
HttpBaseChannel.h \
$(NULL)
ifdef MOZ_IPC
EXPORTS_mozilla/net += \
HttpChannelParent.h \
HttpChannelChild.h \
PHttpChannelParams.h \
@ -79,6 +83,7 @@ CPPSRCS = \
nsHttpNTLMAuth.cpp \
nsHttpTransaction.cpp \
nsHttpHandler.cpp \
HttpBaseChannel.cpp \
nsHttpChannel.cpp \
nsHttpPipeline.cpp \
nsHttpActivityDistributor.cpp \

View File

@ -44,6 +44,7 @@ include "mozilla/net/PHttpChannelParams.h";
using RequestHeaderTuples;
using nsHttpResponseHead;
using nsHttpAtom;
namespace mozilla {
namespace net {
@ -67,7 +68,11 @@ parent:
nsCString docUriSpec,
nsCString docCharset,
PRUint32 loadFlags,
RequestHeaderTuples requestHeaders);
RequestHeaderTuples requestHeaders,
nsHttpAtom requestMethod,
PRUint8 redirectionLimit,
PRBool allowPipelining,
PRBool forceAllowThirdPartyCookie);
child:
OnStartRequest(nsHttpResponseHead responseHead);

View File

@ -108,6 +108,7 @@ struct ParamTraits<nsHttpAtom>
return false;
*aResult = nsHttp::ResolveAtom(value.get());
NS_ASSERTION(aResult->get(), "atom table not initialized");
return true;
}
};

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@
* Contributor(s):
* Darin Fisher <darin@netscape.com> (original author)
* Christian Biesinger <cbiesinger@web.de>
* Daniel Witte <dwitte@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -41,43 +42,23 @@
#ifndef nsHttpChannel_h__
#define nsHttpChannel_h__
#include "HttpBaseChannel.h"
#include "nsHttpTransaction.h"
#include "nsHttpRequestHead.h"
#include "nsHttpAuthCache.h"
#include "nsHashPropertyBag.h"
#include "nsInputStreamPump.h"
#include "nsThreadUtils.h"
#include "nsString.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsInt64.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIHttpHeaderVisitor.h"
#include "nsIHttpEventSink.h"
#include "nsIChannelEventSink.h"
#include "nsIStreamListener.h"
#include "nsIIOService.h"
#include "nsIURI.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIInputStream.h"
#include "nsIProgressEventSink.h"
#include "nsICachingChannel.h"
#include "nsICacheSession.h"
#include "nsICacheEntryDescriptor.h"
#include "nsICacheListener.h"
#include "nsIApplicationCache.h"
#include "nsIApplicationCacheChannel.h"
#include "nsIEncodedChannel.h"
#include "nsITransport.h"
#include "nsIUploadChannel.h"
#include "nsIUploadChannel2.h"
#include "nsIStringEnumerator.h"
#include "nsIOutputStream.h"
#include "nsIAsyncInputStream.h"
#include "nsIPrompt.h"
#include "nsIResumableChannel.h"
#include "nsISupportsPriority.h"
@ -87,18 +68,16 @@
#include "nsITraceableChannel.h"
#include "nsIAuthPromptCallback.h"
class nsHttpResponseHead;
class nsAHttpConnection;
class nsIHttpAuthenticator;
class nsProxyInfo;
using namespace mozilla::net;
//-----------------------------------------------------------------------------
// nsHttpChannel
//-----------------------------------------------------------------------------
class nsHttpChannel : public nsHashPropertyBag
, public nsIHttpChannel
, public nsIHttpChannelInternal
class nsHttpChannel : public HttpBaseChannel
, public nsIStreamListener
, public nsICachingChannel
, public nsIUploadChannel
@ -116,9 +95,6 @@ class nsHttpChannel : public nsHashPropertyBag
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
NS_DECL_NSIHTTPCHANNEL
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSICACHINGCHANNEL
@ -126,7 +102,6 @@ public:
NS_DECL_NSIUPLOADCHANNEL2
NS_DECL_NSICACHELISTENER
NS_DECL_NSIENCODEDCHANNEL
NS_DECL_NSIHTTPCHANNELINTERNAL
NS_DECL_NSITRANSPORTEVENTSINK
NS_DECL_NSIRESUMABLECHANNEL
NS_DECL_NSISUPPORTSPRIORITY
@ -140,11 +115,23 @@ public:
nsHttpChannel();
virtual ~nsHttpChannel();
nsresult Init(nsIURI *uri,
PRUint8 capabilities,
nsProxyInfo* proxyInfo);
// Methods HttpBaseChannel didn't implement for us or that we override.
//
// nsIRequest
NS_IMETHOD Cancel(nsresult status);
NS_IMETHOD Suspend();
NS_IMETHOD Resume();
// nsIChannel
NS_IMETHOD GetOwner(nsISupports **aOwner);
NS_IMETHOD SetOwner(nsISupports *aOwner);
NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext);
// nsIHttpChannelInternal
NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey);
public: /* internal; workaround lame compilers */
public: /* internal necko use only */
typedef void (nsHttpChannel:: *nsAsyncCallback)(void);
nsHttpResponseHead * GetResponseHead() const { return mResponseHead; }
private:
@ -263,43 +250,23 @@ private:
nsresult ContinueOnAuthAvailable(const nsCSubstring& creds);
private:
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mListenerContext;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIInputStream> mUploadStream;
nsCOMPtr<nsIURI> mReferrer;
nsCOMPtr<nsISupports> mSecurityInfo;
nsCOMPtr<nsICancelable> mProxyRequest;
nsHttpRequestHead mRequestHead;
nsHttpResponseHead *mResponseHead;
nsRefPtr<nsInputStreamPump> mTransactionPump;
nsHttpTransaction *mTransaction; // hard ref
nsHttpConnectionInfo *mConnectionInfo; // hard ref
nsRefPtr<nsHttpTransaction> mTransaction;
nsCString mSpec; // ASCII encoded URL spec
PRUint32 mLoadFlags;
PRUint32 mStatus;
PRUint64 mLogicalOffset;
PRUint8 mCaps;
PRInt16 mPriority;
nsCString mContentTypeHint;
nsCString mContentCharsetHint;
nsCString mUserSetCookieHeader;
// cache specific data
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
nsRefPtr<nsInputStreamPump> mCachePump;
nsHttpResponseHead *mCachedResponseHead;
nsAutoPtr<nsHttpResponseHead> mCachedResponseHead;
nsCacheAccessMode mCacheAccess;
PRUint32 mPostID;
PRUint32 mRequestTime;
@ -347,22 +314,15 @@ private:
// before we have either a cache pump or a transaction pump.
PRUint32 mSuspendCount;
// redirection specific data.
PRUint8 mRedirectionLimit;
// If the channel is associated with a cache, and the URI matched
// a fallback namespace, this will hold the key for the fallback
// cache entry.
nsCString mFallbackKey;
// state flags
PRUint32 mIsPending : 1;
PRUint32 mWasOpened : 1;
PRUint32 mApplyConversion : 1;
PRUint32 mAllowPipelining : 1;
PRUint32 mCachedContentIsValid : 1;
PRUint32 mCachedContentIsPartial : 1;
PRUint32 mResponseHeadersModified : 1;
PRUint32 mCanceled : 1;
PRUint32 mTransactionReplaced : 1;
PRUint32 mUploadStreamHasHeaders : 1;
@ -386,7 +346,6 @@ private:
PRUint32 mChooseApplicationCache : 1;
PRUint32 mLoadedFromApplicationCache : 1;
PRUint32 mTracingEnabled : 1;
PRUint32 mForceAllowThirdPartyCookie : 1;
// True if consumer added its own If-None-Match or If-Modified-Since
// headers. In such a case we must not override them in the cache code
// and also we want to pass possible 304 code response through.

View File

@ -99,8 +99,8 @@
#endif
//-----------------------------------------------------------------------------
#ifdef MOZ_IPC
using namespace mozilla::net;
#ifdef MOZ_IPC
#include "mozilla/net/HttpChannelChild.h"
#endif
@ -1524,7 +1524,7 @@ nsHttpHandler::NewProxiedChannel(nsIURI *uri,
nsIProxyInfo* givenProxyInfo,
nsIChannel **result)
{
nsHttpChannel *httpChannel = nsnull;
nsRefPtr<HttpBaseChannel> httpChannel;
LOG(("nsHttpHandler::NewProxiedChannel [proxyInfo=%p]\n",
givenProxyInfo));
@ -1540,36 +1540,22 @@ nsHttpHandler::NewProxiedChannel(nsIURI *uri,
if (NS_FAILED(rv))
return rv;
#if MOZ_IPC
#ifdef MOZ_IPC
if (IsNeckoChild()) {
LOG(("NECKO_E10S_HTTP set: using experimental interprocess HTTP\n"));
// TODO_JCD:
// - Create a common BaseHttpChannel so can share logic?
HttpChannelChild *childChannel = nsnull;
NS_NEWXPCOM(childChannel, HttpChannelChild);
if (!childChannel)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(childChannel);
// TODO: Just ignore HTTPS and proxying for now
if (https)
DROP_DEAD();
if (givenProxyInfo)
DROP_DEAD();
// TODO: Init caps, etc, as below?
rv = childChannel->Init(uri);
if (NS_FAILED(rv)) {
NS_RELEASE(childChannel);
return rv;
}
*result = childChannel;
return NS_OK;
}
#endif
NS_NEWXPCOM(httpChannel, nsHttpChannel);
if (!httpChannel)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(httpChannel);
httpChannel = new HttpChannelChild();
} else
#endif
{
httpChannel = new nsHttpChannel();
}
// select proxy caps if using a non-transparent proxy. SSL tunneling
// should not use proxy settings.
@ -1594,13 +1580,10 @@ nsHttpHandler::NewProxiedChannel(nsIURI *uri,
}
rv = httpChannel->Init(uri, caps, proxyInfo);
if (NS_FAILED(rv)) {
NS_RELEASE(httpChannel);
if (NS_FAILED(rv))
return rv;
}
*result = httpChannel;
httpChannel.forget(result);
return NS_OK;
}

View File

@ -0,0 +1,3 @@
function run_test() {
run_test_in_child("../unit/test_bug528292.js");
}