Bug 1204596 - Part 1: Avoid overriding the channel final URI when it gets intercepted; r=nsm,bkelly

This commit is contained in:
Ehsan Akhgari 2015-09-14 17:06:26 -04:00
parent 841bdc99ad
commit 69e3accaae
11 changed files with 22 additions and 111 deletions

View File

@ -1603,8 +1603,6 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
"response_body_id, "
"response_security_info_id, "
"response_principal_info, "
"response_redirected, "
"response_redirected_url, "
"cache_id "
") VALUES ("
":request_method, "
@ -1628,8 +1626,6 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
":response_body_id, "
":response_security_info_id, "
":response_principal_info, "
":response_redirected, "
":response_redirected_url, "
":cache_id "
");"
), getter_AddRefs(state));
@ -1746,14 +1742,6 @@ InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
serializedInfo);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt32ByName(NS_LITERAL_CSTRING("response_redirected"),
aResponse.channelInfo().redirected() ? 1 : 0);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindUTF8StringByName(NS_LITERAL_CSTRING("response_redirected_url"),
aResponse.channelInfo().redirectedURI());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->BindInt64ByName(NS_LITERAL_CSTRING("cache_id"), aCacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@ -1846,8 +1834,6 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
"entries.response_headers_guard, "
"entries.response_body_id, "
"entries.response_principal_info, "
"entries.response_redirected, "
"entries.response_redirected_url, "
"security_info.data "
"FROM entries "
"LEFT OUTER JOIN security_info "
@ -1912,14 +1898,7 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
mozilla::ipc::ContentPrincipalInfo(attrs.mAppId, attrs.mInBrowser, originNoSuffix);
}
int32_t redirected;
rv = state->GetInt32(7, &redirected);
aSavedResponseOut->mValue.channelInfo().redirected() = !!redirected;
rv = state->GetUTF8String(8, aSavedResponseOut->mValue.channelInfo().redirectedURI());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = state->GetBlobAsUTF8String(9, aSavedResponseOut->mValue.channelInfo().securityInfo());
rv = state->GetBlobAsUTF8String(7, aSavedResponseOut->mValue.channelInfo().securityInfo());
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = aConn->CreateStatement(NS_LITERAL_CSTRING(

View File

@ -31,12 +31,6 @@ ChannelInfo::InitFromDocument(nsIDocument* aDoc)
SetSecurityInfo(securityInfo);
}
// mRedirected flag and mRedirectedURISpec are only important for maintaining
// the channel's redirected status. If the ChannelInfo is initialized from
// a document, that document has already asked the channel from which it was
// loaded about the current channel URI, so it won't matter if a future
// ResurrectInfoOnChannel() call misses whether the channel was redirected.
mRedirected = false;
mInited = true;
}
@ -52,20 +46,6 @@ ChannelInfo::InitFromChannel(nsIChannel* aChannel)
SetSecurityInfo(securityInfo);
}
nsLoadFlags loadFlags = 0;
aChannel->GetLoadFlags(&loadFlags);
mRedirected = (loadFlags & nsIChannel::LOAD_REPLACE);
if (mRedirected) {
// Save the spec and not the nsIURI object itself, since those objects are
// not thread-safe, and releasing them somewhere other than the main thread
// is not possible.
nsCOMPtr<nsIURI> redirectedURI;
aChannel->GetURI(getter_AddRefs(redirectedURI));
if (redirectedURI) {
redirectedURI->GetSpec(mRedirectedURISpec);
}
}
mInited = true;
}
@ -79,7 +59,6 @@ ChannelInfo::InitFromChromeGlobal(nsIGlobalObject* aGlobal)
nsContentUtils::IsSystemPrincipal(aGlobal->PrincipalOrNull()));
mSecurityInfo.Truncate();
mRedirected = false;
mInited = true;
}
@ -89,8 +68,6 @@ ChannelInfo::InitFromIPCChannelInfo(const mozilla::ipc::IPCChannelInfo& aChannel
MOZ_ASSERT(!mInited, "Cannot initialize the object twice");
mSecurityInfo = aChannelInfo.securityInfo();
mRedirectedURISpec = aChannelInfo.redirectedURI();
mRedirected = aChannelInfo.redirected();
mInited = true;
}
@ -142,33 +119,6 @@ ChannelInfo::ResurrectInfoOnChannel(nsIChannel* aChannel)
}
}
if (mRedirected) {
nsLoadFlags flags = 0;
aChannel->GetLoadFlags(&flags);
flags |= nsIChannel::LOAD_REPLACE;
aChannel->SetLoadFlags(flags);
nsCOMPtr<nsIURI> redirectedURI;
nsresult rv = NS_NewURI(getter_AddRefs(redirectedURI),
mRedirectedURISpec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (httpChannel) {
net::HttpBaseChannel* httpBaseChannel =
static_cast<net::HttpBaseChannel*>(httpChannel.get());
rv = httpBaseChannel->OverrideURI(redirectedURI);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
if (NS_WARN_IF(!jarChannel)) {
return NS_ERROR_FAILURE;
}
static_cast<nsJARChannel*>(jarChannel.get())->OverrideURI(redirectedURI);
}
}
return NS_OK;
}
@ -183,8 +133,6 @@ ChannelInfo::AsIPCChannelInfo() const
IPCChannelInfo ipcInfo;
ipcInfo.securityInfo() = mSecurityInfo;
ipcInfo.redirectedURI() = mRedirectedURISpec;
ipcInfo.redirected() = mRedirected;
return ipcInfo;
}

View File

@ -46,15 +46,12 @@ public:
ChannelInfo()
: mInited(false)
, mRedirected(false)
{
}
ChannelInfo(const ChannelInfo& aRHS)
: mSecurityInfo(aRHS.mSecurityInfo)
, mRedirectedURISpec(aRHS.mRedirectedURISpec)
, mInited(aRHS.mInited)
, mRedirected(aRHS.mRedirected)
{
}
@ -62,9 +59,7 @@ public:
operator=(const ChannelInfo& aRHS)
{
mSecurityInfo = aRHS.mSecurityInfo;
mRedirectedURISpec = aRHS.mRedirectedURISpec;
mInited = aRHS.mInited;
mRedirected = aRHS.mRedirected;
return *this;
}
@ -89,9 +84,7 @@ private:
private:
nsCString mSecurityInfo;
nsCString mRedirectedURISpec;
bool mInited;
bool mRedirected;
};
} // namespace dom

View File

@ -8,8 +8,6 @@ namespace ipc {
struct IPCChannelInfo
{
nsCString securityInfo;
nsCString redirectedURI;
bool redirected;
};
} // namespace ipc

View File

@ -1,4 +1,9 @@
function testScript(script) {
// reroute.html should have set this variable if a service worker is present!
if (!("isSWPresent" in window)) {
window.isSWPresent = false;
}
function setupPrefs() {
return new Promise(function(resolve, reject) {
SpecialPowers.pushPrefEnv({

View File

@ -6,5 +6,6 @@
<script type="text/javascript" src="utils.js"> </script>
<script type="text/javascript" src="fetch_test_framework.js"> </script>
<script>
window.isSWPresent = true;
testScript(location.search.substring(1) + ".js");
</script>

View File

@ -8,7 +8,6 @@ onfetch = function(e) {
e.respondWith(fetch(url, {
method: e.request.method,
headers: e.request.headers,
body: e.request.body,
mode: e.request.mode,
credentials: e.request.credentials,
cache: e.request.cache,

View File

@ -12,8 +12,8 @@ function testURL() {
ok(res.type !== "error", "Response should not be an error for " + entry[0]);
is(res.status, entry[2], "Status should match expected for " + entry[0]);
is(res.statusText, entry[3], "Status text should match expected for " + entry[0]);
// This file redirects to pass2
if (entry[0] != "file_XHR_pass3.txt")
// This file redirects to pass2, but that is invisible if a SW is present.
if (entry[0] != "file_XHR_pass3.txt" || isSWPresent)
ok(res.url.endsWith(path + entry[0]), "Response url should match request for simple fetch for " + entry[0]);
else
ok(res.url.endsWith(path + "file_XHR_pass2.txt"), "Response url should match request for simple fetch for " + entry[0]);
@ -49,7 +49,8 @@ function testRequestGET() {
ok(res.type !== "error", "Response should not be an error for " + entry[0]);
is(res.status, entry[2], "Status should match expected for " + entry[0]);
is(res.statusText, entry[3], "Status text should match expected for " + entry[0]);
if (entry[0] != "file_XHR_pass3.txt")
// This file redirects to pass2, but that is invisible if a SW is present.
if (entry[0] != "file_XHR_pass3.txt" || isSWPresent)
ok(res.url.endsWith(path + entry[0]), "Response url should match request for simple fetch for " + entry[0]);
else
ok(res.url.endsWith(path + "file_XHR_pass2.txt"), "Response url should match request for simple fetch for " + entry[0]);

View File

@ -1277,7 +1277,17 @@ function testRedirects() {
ok(test.pass, "Expected test to pass for " + test.toSource());
is(res.status, 200, "wrong status in test for " + test.toSource());
is(res.statusText, "OK", "wrong status text for " + test.toSource());
is((new URL(res.url)).host, (new URL(test.hops[test.hops.length-1].server)).host, "Response URL should be redirected URL");
var reqHost = (new URL(req.url)).host;
// If there is a service worker present, the redirections will be
// transparent, assuming that the original request is to the current
// site and would be intercepted.
if (isSWPresent) {
if (reqHost === location.host) {
is((new URL(res.url)).host, reqHost, "Response URL should be original URL with a SW present");
}
} else {
is((new URL(res.url)).host, (new URL(test.hops[test.hops.length-1].server)).host, "Response URL should be redirected URL");
}
return res.text().then(function(v) {
is(v, "<res>hello pass</res>\n",
"wrong responseText in test for " + test.toSource());

View File

@ -1561,28 +1561,6 @@ HttpBaseChannel::OverrideSecurityInfo(nsISupports* aSecurityInfo)
return NS_OK;
}
nsresult
HttpBaseChannel::OverrideURI(nsIURI* aRedirectedURI)
{
MOZ_ASSERT(mLoadFlags & LOAD_REPLACE,
"This can only happen if the LOAD_REPLACE flag is set");
MOZ_ASSERT(ShouldIntercept(),
"This can only be called on channels that can be intercepted");
if (!(mLoadFlags & LOAD_REPLACE)) {
LOG(("HttpBaseChannel::OverrideURI LOAD_REPLACE flag not set! [this=%p]\n",
this));
return NS_ERROR_UNEXPECTED;
}
if (!mResponseCouldBeSynthesized) {
LOG(("HttpBaseChannel::OverrideURI channel cannot be intercepted! "
"[this=%p]\n", this));
return NS_ERROR_UNEXPECTED;
}
mURI = aRedirectedURI;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::IsNoStoreResponse(bool *value)
{

View File

@ -256,7 +256,6 @@ public:
const NetAddr& GetPeerAddr() { return mPeerAddr; }
nsresult OverrideSecurityInfo(nsISupports* aSecurityInfo);
nsresult OverrideURI(nsIURI* aRedirectedURI);
public: /* Necko internal use only... */
bool IsNavigation();