Bug 811669 - nsICachingChannel.cacheKey may not be set on http-on-modify-request anymore. r=mcmanus

This commit is contained in:
Jason Duell 2012-12-03 22:24:36 -08:00
parent a244dd198f
commit 2d10c31403
6 changed files with 83 additions and 22 deletions

View File

@ -48,13 +48,31 @@
} while (0)
#define ENSURE_CALLED_BEFORE_ASYNC_OPEN() \
if (mIsPending || mWasOpened) { \
nsPrintfCString msg("'%s' called after AsyncOpen: %s +%d", \
__FUNCTION__, __FILE__, __LINE__); \
NECKO_MAYBE_ABORT(msg); \
} \
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); \
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
do { \
if (mIsPending || mWasOpened) { \
nsPrintfCString msg("'%s' called after AsyncOpen: %s +%d", \
__FUNCTION__, __FILE__, __LINE__); \
NECKO_MAYBE_ABORT(msg); \
} \
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); \
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); \
} while (0)
// Fails call if made after request observers (on-modify-request, etc) have been
// called
#define ENSURE_CALLED_BEFORE_CONNECT() \
do { \
if (mRequestObserversCalled) { \
nsPrintfCString msg("'%s' called too late: %s +%d", \
__FUNCTION__, __FILE__, __LINE__); \
NECKO_MAYBE_ABORT(msg); \
if (mIsPending) \
return NS_ERROR_IN_PROGRESS; \
MOZ_ASSERT(mWasOpened); \
return NS_ERROR_ALREADY_OPENED; \
} \
} while (0)
namespace mozilla {
namespace net {

View File

@ -37,6 +37,7 @@ HttpBaseChannel::HttpBaseChannel()
, mCanceled(false)
, mIsPending(false)
, mWasOpened(false)
, mRequestObserversCalled(false)
, mResponseHeadersModified(false)
, mAllowPipelining(true)
, mForceAllowThirdPartyCookie(false)
@ -236,7 +237,7 @@ HttpBaseChannel::GetOriginalURI(nsIURI **aOriginalURI)
NS_IMETHODIMP
HttpBaseChannel::SetOriginalURI(nsIURI *aOriginalURI)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
NS_ENSURE_ARG_POINTER(aOriginalURI);
mOriginalURI = aOriginalURI;
@ -810,7 +811,7 @@ HttpBaseChannel::GetRequestMethod(nsACString& aMethod)
NS_IMETHODIMP
HttpBaseChannel::SetRequestMethod(const nsACString& aMethod)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
const nsCString& flatMethod = PromiseFlatCString(aMethod);
@ -838,7 +839,7 @@ HttpBaseChannel::GetReferrer(nsIURI **referrer)
NS_IMETHODIMP
HttpBaseChannel::SetReferrer(nsIURI *referrer)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
// clear existing referrer, if any
mReferrer = nullptr;
@ -1082,7 +1083,7 @@ HttpBaseChannel::GetAllowPipelining(bool *value)
NS_IMETHODIMP
HttpBaseChannel::SetAllowPipelining(bool value)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
mAllowPipelining = value;
return NS_OK;
@ -1099,7 +1100,7 @@ HttpBaseChannel::GetRedirectionLimit(uint32_t *value)
NS_IMETHODIMP
HttpBaseChannel::SetRedirectionLimit(uint32_t value)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
mRedirectionLimit = NS_MIN<uint32_t>(value, 0xff);
return NS_OK;
@ -1169,7 +1170,7 @@ HttpBaseChannel::GetDocumentURI(nsIURI **aDocumentURI)
NS_IMETHODIMP
HttpBaseChannel::SetDocumentURI(nsIURI *aDocumentURI)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
mDocumentURI = aDocumentURI;
return NS_OK;

View File

@ -260,6 +260,8 @@ protected:
uint32_t mCanceled : 1;
uint32_t mIsPending : 1;
uint32_t mWasOpened : 1;
// if 1 all "http-on-{opening|modify|etc}-request" observers have been called
uint32_t mRequestObserversCalled : 1;
uint32_t mResponseHeadersModified : 1;
uint32_t mAllowPipelining : 1;
uint32_t mForceAllowThirdPartyCookie : 1;

View File

@ -1189,7 +1189,7 @@ HttpChannelChild::IsFromCache(bool *value)
NS_IMETHODIMP
HttpChannelChild::ResumeAt(uint64_t startPos, const nsACString& entityID)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
mStartPos = startPos;
mEntityID = entityID;
mSendResumeAt = true;

View File

@ -4337,6 +4337,8 @@ nsHttpChannel::BeginConnect()
// notify "http-on-modify-request" observers
gHttpHandler->OnModifyRequest(this);
mRequestObserversCalled = true;
// If mTimingEnabled flag is not set after OnModifyRequest() then
// clear the already recorded AsyncOpen value for consistency.
if (!mTimingEnabled)
@ -4455,7 +4457,7 @@ nsHttpChannel::BeginConnect()
NS_IMETHODIMP
nsHttpChannel::SetupFallbackChannel(const char *aFallbackKey)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
LOG(("nsHttpChannel::SetupFallbackChannel [this=%x, key=%s]",
this, aFallbackKey));
@ -5337,7 +5339,7 @@ nsHttpChannel::SetCacheKey(nsISupports *key)
LOG(("nsHttpChannel::SetCacheKey [this=%p key=%p]\n", this, key));
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
if (!key)
mPostID = 0;
@ -5586,7 +5588,7 @@ nsHttpChannel::GetApplicationCache(nsIApplicationCache **out)
NS_IMETHODIMP
nsHttpChannel::SetApplicationCache(nsIApplicationCache *appCache)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
mApplicationCache = appCache;
return NS_OK;
@ -5602,7 +5604,7 @@ nsHttpChannel::GetApplicationCacheForWrite(nsIApplicationCache **out)
NS_IMETHODIMP
nsHttpChannel::SetApplicationCacheForWrite(nsIApplicationCache *appCache)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
mApplicationCacheForWrite = appCache;
return NS_OK;
@ -5625,7 +5627,7 @@ nsHttpChannel::GetInheritApplicationCache(bool *aInherit)
NS_IMETHODIMP
nsHttpChannel::SetInheritApplicationCache(bool aInherit)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
mInheritApplicationCache = aInherit;
return NS_OK;
@ -5641,7 +5643,7 @@ nsHttpChannel::GetChooseApplicationCache(bool *aChoose)
NS_IMETHODIMP
nsHttpChannel::SetChooseApplicationCache(bool aChoose)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
ENSURE_CALLED_BEFORE_CONNECT();
mChooseApplicationCache = aChoose;
return NS_OK;

View File

@ -1,5 +1,8 @@
// This file ensures that canceling a channel early does not
// send the request to the server (bug 350790)
//
// I've also shoehorned in a test that ENSURE_CALLED_BEFORE_CONNECT works as
// expected: see comments that start with ENSURE_CALLED_BEFORE_CONNECT:
const Cc = Components.classes;
const Ci = Components.interfaces;
@ -8,6 +11,8 @@ const Cr = Components.results;
Cu.import("resource://testing-common/httpd.js");
var ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var observer = {
QueryInterface: function eventsink_qi(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
@ -20,6 +25,17 @@ var observer = {
subject = subject.QueryInterface(Components.interfaces.nsIRequest);
subject.cancel(Components.results.NS_BINDING_ABORTED);
// ENSURE_CALLED_BEFORE_CONNECT: setting values should still work
try {
subject.QueryInterface(Components.interfaces.nsIHttpChannel);
currentReferrer = subject.getRequestHeader("Referer");
do_check_eq(currentReferrer, "http://site1.com/");
var uri = ios.newURI("http://site2.com", null, null);
subject.referrer = uri;
} catch (ex) {
do_throw("Exception: " + ex);
}
var obs = Components.classes["@mozilla.org/observer-service;1"].getService();
obs = obs.QueryInterface(Components.interfaces.nsIObserverService);
obs.removeObserver(observer, "http-on-modify-request");
@ -29,6 +45,26 @@ var observer = {
var listener = {
onStartRequest: function test_onStartR(request, ctx) {
do_check_eq(request.status, Components.results.NS_BINDING_ABORTED);
// ENSURE_CALLED_BEFORE_CONNECT: setting referrer should now fail
try {
request.QueryInterface(Components.interfaces.nsIHttpChannel);
currentReferrer = request.getRequestHeader("Referer");
do_check_eq(currentReferrer, "http://site2.com/");
var uri = ios.newURI("http://site3.com/", null, null);
// Need to set NECKO_ERRORS_ARE_FATAL=0 else we'll abort process
var env = Components.classes["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
env.set("NECKO_ERRORS_ARE_FATAL", "0");
// we expect setting referrer to fail
try {
request.referrer = uri;
do_throw("Error should have been thrown before getting here");
} catch (ex) { }
} catch (ex) {
do_throw("Exception: " + ex);
}
},
onDataAvailable: function test_ODA() {
@ -41,11 +77,13 @@ var listener = {
};
function makeChan(url) {
var ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var chan = ios.newChannel(url, null, null)
.QueryInterface(Components.interfaces.nsIHttpChannel);
// ENSURE_CALLED_BEFORE_CONNECT: set original value
var uri = ios.newURI("http://site1.com", null, null);
chan.referrer = uri;
return chan;
}