diff --git a/netwerk/protocol/http/src/HttpChannelChild.cpp b/netwerk/protocol/http/src/HttpChannelChild.cpp index b232f125b123..a0e9958c8c59 100644 --- a/netwerk/protocol/http/src/HttpChannelChild.cpp +++ b/netwerk/protocol/http/src/HttpChannelChild.cpp @@ -263,9 +263,17 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) mDocumentURI->GetOriginCharset(docCharset); } + nsCAutoString referrerSpec; + nsCAutoString referrerCharset; + if (mReferrer) { + mReferrer->GetSpec(referrerSpec); + mReferrer->GetOriginCharset(referrerCharset); + } + if (!SendAsyncOpen(mSpec, charset, originalSpec, originalCharset, - docSpec, docCharset, mLoadFlags, mRequestHeaders, - mRequestHead.Method(), mRedirectionLimit, mAllowPipelining, + docSpec, docCharset, referrerSpec, referrerCharset, + mLoadFlags, mRequestHeaders, mRequestHead.Method(), + mRedirectionLimit, mAllowPipelining, mForceAllowThirdPartyCookie)) { // IPDL error: our destructor will be called automatically // -- TODO: verify that that's the case :) diff --git a/netwerk/protocol/http/src/HttpChannelParent.cpp b/netwerk/protocol/http/src/HttpChannelParent.cpp index 2bc49d2a086c..34ce87426486 100644 --- a/netwerk/protocol/http/src/HttpChannelParent.cpp +++ b/netwerk/protocol/http/src/HttpChannelParent.cpp @@ -80,6 +80,8 @@ HttpChannelParent::RecvAsyncOpen(const nsCString& uriSpec, const nsCString& originalCharset, const nsCString& docUriSpec, const nsCString& docCharset, + const nsCString& referrerSpec, + const nsCString& referrerCharset, const PRUint32& loadFlags, const RequestHeaderTuples& requestHeaders, const nsHttpAtom& requestMethod, @@ -106,26 +108,33 @@ HttpChannelParent::RecvAsyncOpen(const nsCString& uriSpec, if (NS_FAILED(rv)) return false; // TODO: send fail msg to child, return true - nsCOMPtr httpChan(do_QueryInterface(chan)); - nsCOMPtr httpChanInt(do_QueryInterface(chan)); + nsHttpChannel *httpChan = static_cast(chan.get()); if (!originalUriSpec.IsEmpty()) { nsCOMPtr originalUri; rv = NS_NewURI(getter_AddRefs(originalUri), originalUriSpec, originalCharset.get(), nsnull, ios); if (!NS_FAILED(rv)) - chan->SetOriginalURI(originalUri); + httpChan->SetOriginalURI(originalUri); } if (!docUriSpec.IsEmpty()) { nsCOMPtr docUri; rv = NS_NewURI(getter_AddRefs(docUri), docUriSpec, docCharset.get(), nsnull, ios); if (!NS_FAILED(rv)) { - httpChanInt->SetDocumentURI(docUri); + httpChan->SetDocumentURI(docUri); + } + } + if (!referrerSpec.IsEmpty()) { + nsCOMPtr referrerUri; + rv = NS_NewURI(getter_AddRefs(referrerUri), referrerSpec, + referrerCharset.get(), nsnull, ios); + if (!NS_FAILED(rv)) { + httpChan->SetReferrerInternal(referrerUri); } } if (loadFlags != nsIRequest::LOAD_NORMAL) - chan->SetLoadFlags(loadFlags); + httpChan->SetLoadFlags(loadFlags); for (PRUint32 i = 0; i < requestHeaders.Length(); i++) httpChan->SetRequestHeader(requestHeaders[i].mHeader, @@ -134,14 +143,14 @@ HttpChannelParent::RecvAsyncOpen(const nsCString& uriSpec, // TODO: implement needed interfaces, and either proxy calls back to child // process, or rig up appropriate hacks. -// chan->SetNotificationCallbacks(this); + // httpChan->SetNotificationCallbacks(this); httpChan->SetRequestMethod(nsDependentCString(requestMethod.get())); httpChan->SetRedirectionLimit(redirectionLimit); httpChan->SetAllowPipelining(allowPipelining); - httpChanInt->SetForceAllowThirdPartyCookie(forceAllowThirdPartyCookie); + httpChan->SetForceAllowThirdPartyCookie(forceAllowThirdPartyCookie); - rv = chan->AsyncOpen(this, nsnull); + rv = httpChan->AsyncOpen(this, nsnull); if (NS_FAILED(rv)) return false; // TODO: send fail msg to child, return true diff --git a/netwerk/protocol/http/src/HttpChannelParent.h b/netwerk/protocol/http/src/HttpChannelParent.h index c4332531c614..5e0e67495f4d 100644 --- a/netwerk/protocol/http/src/HttpChannelParent.h +++ b/netwerk/protocol/http/src/HttpChannelParent.h @@ -71,6 +71,8 @@ protected: const nsCString& originalCharset, const nsCString& docUriSpec, const nsCString& docCharset, + const nsCString& referrerSpec, + const nsCString& referrerCharset, const PRUint32& loadFlags, const RequestHeaderTuples& requestHeaders, const nsHttpAtom& requestMethod, diff --git a/netwerk/protocol/http/src/PHttpChannel.ipdl b/netwerk/protocol/http/src/PHttpChannel.ipdl index 644509231074..70d75f5513f8 100644 --- a/netwerk/protocol/http/src/PHttpChannel.ipdl +++ b/netwerk/protocol/http/src/PHttpChannel.ipdl @@ -67,6 +67,8 @@ parent: nsCString originalCharset, nsCString docUriSpec, nsCString docCharset, + nsCString referrerSpec, + nsCString referrerCharset, PRUint32 loadFlags, RequestHeaderTuples requestHeaders, nsHttpAtom requestMethod, diff --git a/netwerk/protocol/http/src/nsHttpChannel.h b/netwerk/protocol/http/src/nsHttpChannel.h index f1c903f80c51..8974020f889a 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.h +++ b/netwerk/protocol/http/src/nsHttpChannel.h @@ -129,13 +129,20 @@ public: // nsIHttpChannelInternal NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey); - - public: /* internal necko use only */ typedef void (nsHttpChannel:: *nsAsyncCallback)(void); nsHttpResponseHead * GetResponseHead() const { return mResponseHead; } -private: + nsresult SetReferrerInternal(nsIURI *referrer) { + nsCAutoString spec; + nsresult rv = referrer->GetAsciiSpec(spec); + if (NS_FAILED(rv)) return rv; + mReferrer = referrer; + mRequestHead.SetHeader(nsHttp::Referer, spec); + return NS_OK; + } + +private: // Helper function to simplify getting notification callbacks. template void GetCallback(nsCOMPtr &aResult) diff --git a/netwerk/test/unit/test_head.js b/netwerk/test/unit/test_head.js index 20c030e6bf38..0b0d609efa55 100644 --- a/netwerk/test/unit/test_head.js +++ b/netwerk/test/unit/test_head.js @@ -9,6 +9,7 @@ var httpserver = new nsHttpServer(); var testpath = "/simple"; var httpbody = "0123456789"; var channel; +var ios; var dbg=0 if (dbg) { print("============== START =========="); } @@ -39,6 +40,17 @@ function setup_test() { setOK = channel.getRequestHeader("MergeMe"); do_check_eq(setOK, "foo1, foo2, foo3"); + var uri = ios.newURI("http://foo1.invalid:80", null, null); + channel.referrer = uri; + do_check_true(channel.referrer.equals(uri)); + setOK = channel.getRequestHeader("Referer"); + do_check_eq(setOK, "http://foo1.invalid/"); + + uri = ios.newURI("http://foo2.invalid:90/bar", null, null); + channel.referrer = uri; + setOK = channel.getRequestHeader("Referer"); + do_check_eq(setOK, "http://foo2.invalid:90/bar"); + // ChannelListener defined in head_channels.js channel.asyncOpen(new ChannelListener(checkRequestResponse, channel), null); @@ -46,8 +58,7 @@ function setup_test() { } function setupChannel(path) { - var ios = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); + ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); var chan = ios.newChannel("http://localhost:4444" + path, "", null); chan.QueryInterface(Ci.nsIHttpChannel); chan.requestMethod = "GET"; @@ -61,6 +72,8 @@ function serverHandler(metadata, response) { do_check_eq(setOK, "replaced"); setOK = metadata.getHeader("MergeMe"); do_check_eq(setOK, "foo1, foo2, foo3"); + setOK = metadata.getHeader("Referer"); + do_check_eq(setOK, "http://foo2.invalid:90/bar"); response.setHeader("Content-Type", "text/plain", false); response.setStatusLine("1.1", 200, "OK");