Bug 1049299 - Correctly calculate 3rd-party cookie status for content-process HTTP channels. r=jduell

This commit is contained in:
Blake Kaplan 2014-10-28 14:23:00 +01:00
parent 7ff2a511e8
commit d17edccb32
11 changed files with 128 additions and 25 deletions

View File

@ -10378,8 +10378,8 @@ nsDocShell::DoURILoad(nsIURI * aURI,
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(do_QueryInterface(channel));
if (httpChannelInternal) {
if (aForceAllowCookies) {
httpChannelInternal->SetForceAllowThirdPartyCookie(true);
}
httpChannelInternal->SetThirdPartyFlags(nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
}
if (aFirstParty) {
httpChannelInternal->SetDocumentURI(aURI);
} else {

View File

@ -1093,7 +1093,10 @@ Navigator::SendBeacon(const nsAString& aUrl,
}
bool isForeign = true;
thirdPartyUtil->IsThirdPartyWindow(mWindow, uri, &isForeign);
httpChannelInternal->SetForceAllowThirdPartyCookie(!isForeign);
uint32_t thirdPartyFlags = isForeign ?
0 :
nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
httpChannelInternal->SetThirdPartyFlags(thirdPartyFlags);
nsCString mimeType;
if (!aData.IsNull()) {

View File

@ -1,3 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 sts=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -166,12 +168,17 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
nsresult rv;
bool doForce = false;
bool checkWindowChain = true;
bool parentIsThird = false;
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
do_QueryInterface(aChannel);
if (httpChannelInternal) {
rv = httpChannelInternal->GetForceAllowThirdPartyCookie(&doForce);
uint32_t flags;
rv = httpChannelInternal->GetThirdPartyFlags(&flags);
NS_ENSURE_SUCCESS(rv, rv);
doForce = (flags & nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
// If aURI was not supplied, and we're forcing, then we're by definition
// not foreign. If aURI was supplied, we still want to check whether it's
// foreign with respect to the channel URI. (The forcing only applies to
@ -180,6 +187,28 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
*aResult = false;
return NS_OK;
}
if (flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_THIRD_PARTY) {
// Check that the two PARENT_IS_{THIRD,SAME}_PARTY are mutually exclusive.
MOZ_ASSERT(!(flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY));
// If we're not forcing and we know that the window chain of the channel
// is third party, then we know now that we're third party.
if (!doForce) {
*aResult = true;
return NS_OK;
}
checkWindowChain = false;
parentIsThird = true;
} else {
// In e10s, we can't check the parent chain in the parent, so we do so
// in the child and send the result to the parent.
// Note that we only check the window chain if neither
// THIRD_PARTY_PARENT_IS_* flag is set.
checkWindowChain = !(flags & nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY);
parentIsThird = false;
}
}
// Obtain the URI from the channel, and its base domain.
@ -206,6 +235,12 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel,
}
}
// If we've already computed this in the child process, we're done.
if (!checkWindowChain) {
*aResult = parentIsThird;
return NS_OK;
}
// Find the associated window and its parent window.
nsCOMPtr<nsILoadContext> ctx;
NS_QueryNotificationCallbacks(aChannel, ctx);

View File

@ -1236,7 +1236,7 @@ nsresult nsWebBrowserPersist::SaveURIInternal(
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
do_QueryInterface(inputChannel);
if (httpChannelInternal)
httpChannelInternal->SetForceAllowThirdPartyCookie(true);
httpChannelInternal->SetThirdPartyFlags(nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
}
// Set the referrer, post data and headers if any

View File

@ -42,7 +42,7 @@ struct HttpChannelOpenArgs
uint8_t redirectionLimit;
bool allowPipelining;
bool allowSTS;
bool forceAllowThirdPartyCookie;
uint32_t thirdPartyFlags;
bool resumeAt;
uint64_t startPos;
nsCString entityID;

View File

@ -56,7 +56,7 @@ HttpBaseChannel::HttpBaseChannel()
, mResponseHeadersModified(false)
, mAllowPipelining(true)
, mAllowSTS(true)
, mForceAllowThirdPartyCookie(false)
, mThirdPartyFlags(0)
, mUploadStreamHasHeaders(false)
, mInheritApplicationCache(true)
, mChooseApplicationCache(false)
@ -1428,10 +1428,26 @@ HttpBaseChannel::SetCookie(const char *aCookieHeader)
return rv;
}
NS_IMETHODIMP
HttpBaseChannel::GetThirdPartyFlags(uint32_t *aFlags)
{
*aFlags = mThirdPartyFlags;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetThirdPartyFlags(uint32_t aFlags)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
mThirdPartyFlags = aFlags;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetForceAllowThirdPartyCookie(bool *aForce)
{
*aForce = mForceAllowThirdPartyCookie;
*aForce = !!(mThirdPartyFlags & nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
return NS_OK;
}
@ -1440,7 +1456,11 @@ HttpBaseChannel::SetForceAllowThirdPartyCookie(bool aForce)
{
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
mForceAllowThirdPartyCookie = aForce;
if (aForce)
mThirdPartyFlags |= nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
else
mThirdPartyFlags &= ~nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW;
return NS_OK;
}
@ -2040,9 +2060,8 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
if (httpInternal) {
// convey the mForceAllowThirdPartyCookie flag
httpInternal->SetForceAllowThirdPartyCookie(mForceAllowThirdPartyCookie);
// convey the spdy flag
// Convey third party cookie and spdy flags.
httpInternal->SetThirdPartyFlags(mThirdPartyFlags);
httpInternal->SetAllowSpdy(mAllowSpdy);
// update the DocumentURI indicator since we are being redirected.

View File

@ -160,6 +160,8 @@ public:
NS_IMETHOD GetRequestVersion(uint32_t *major, uint32_t *minor);
NS_IMETHOD GetResponseVersion(uint32_t *major, uint32_t *minor);
NS_IMETHOD SetCookie(const char *aCookieHeader);
NS_IMETHOD GetThirdPartyFlags(uint32_t *aForce);
NS_IMETHOD SetThirdPartyFlags(uint32_t aForce);
NS_IMETHOD GetForceAllowThirdPartyCookie(bool *aForce);
NS_IMETHOD SetForceAllowThirdPartyCookie(bool aForce);
NS_IMETHOD GetCanceled(bool *aCanceled);
@ -341,7 +343,7 @@ protected:
uint32_t mResponseHeadersModified : 1;
uint32_t mAllowPipelining : 1;
uint32_t mAllowSTS : 1;
uint32_t mForceAllowThirdPartyCookie : 1;
uint32_t mThirdPartyFlags : 3;
uint32_t mUploadStreamHasHeaders : 1;
uint32_t mInheritApplicationCache : 1;
uint32_t mChooseApplicationCache : 1;

View File

@ -31,6 +31,7 @@
#include "nsInputStreamPump.h"
#include "InterceptedChannel.h"
#include "nsPerformance.h"
#include "mozIThirdPartyUtil.h"
using namespace mozilla::dom;
using namespace mozilla::ipc;
@ -1484,6 +1485,21 @@ HttpChannelChild::ContinueAsyncOpen()
optionalFDs = mozilla::void_t();
}
nsCOMPtr<mozIThirdPartyUtil> util(do_GetService(THIRDPARTYUTIL_CONTRACTID));
if (util) {
bool thirdParty;
nsresult rv = util->IsThirdPartyChannel(this, nullptr, &thirdParty);
if (NS_FAILED(rv)) {
// If we couldn't compute whether this is a third-party load, assume that
// it is.
thirdParty = true;
}
mThirdPartyFlags |= thirdParty ?
nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_THIRD_PARTY :
nsIHttpChannelInternal::THIRD_PARTY_PARENT_IS_SAME_PARTY;
}
openArgs.fds() = optionalFDs;
openArgs.uploadStreamHasHeaders() = mUploadStreamHasHeaders;
@ -1491,7 +1507,7 @@ HttpChannelChild::ContinueAsyncOpen()
openArgs.redirectionLimit() = mRedirectionLimit;
openArgs.allowPipelining() = mAllowPipelining;
openArgs.allowSTS() = mAllowSTS;
openArgs.forceAllowThirdPartyCookie() = mForceAllowThirdPartyCookie;
openArgs.thirdPartyFlags() = mThirdPartyFlags;
openArgs.resumeAt() = mSendResumeAt;
openArgs.startPos() = mStartPos;
openArgs.entityID() = mEntityID;

View File

@ -101,8 +101,8 @@ HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs)
a.requestMethod(), a.uploadStream(),
a.uploadStreamHasHeaders(), a.priority(),
a.redirectionLimit(), a.allowPipelining(), a.allowSTS(),
a.forceAllowThirdPartyCookie(), a.resumeAt(),
a.startPos(), a.entityID(), a.chooseApplicationCache(),
a.thirdPartyFlags(), a.resumeAt(), a.startPos(),
a.entityID(), a.chooseApplicationCache(),
a.appCacheClientID(), a.allowSpdy(), a.fds(),
a.requestingPrincipalInfo(), a.securityFlags(),
a.contentPolicyType());
@ -176,12 +176,12 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
const RequestHeaderTuples& requestHeaders,
const nsCString& requestMethod,
const OptionalInputStreamParams& uploadStream,
const bool& uploadStreamHasHeaders,
const bool& uploadStreamHasHeaders,
const uint16_t& priority,
const uint8_t& redirectionLimit,
const bool& allowPipelining,
const bool& allowSTS,
const bool& forceAllowThirdPartyCookie,
const bool& allowPipelining,
const bool& allowSTS,
const uint32_t& thirdPartyFlags,
const bool& doResumeAt,
const uint64_t& startPos,
const nsCString& entityID,
@ -304,7 +304,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
mChannel->SetRedirectionLimit(redirectionLimit);
mChannel->SetAllowPipelining(allowPipelining);
mChannel->SetAllowSTS(allowSTS);
mChannel->SetForceAllowThirdPartyCookie(forceAllowThirdPartyCookie);
mChannel->SetThirdPartyFlags(thirdPartyFlags);
mChannel->SetAllowSpdy(allowSpdy);
nsCOMPtr<nsIApplicationCacheChannel> appCacheChan =

View File

@ -99,7 +99,7 @@ protected:
const uint8_t& redirectionLimit,
const bool& allowPipelining,
const bool& allowSTS,
const bool& forceAllowThirdPartyCookie,
const uint32_t& thirdPartyFlags,
const bool& doResumeAt,
const uint64_t& startPos,
const nsCString& entityID,

View File

@ -38,7 +38,7 @@ interface nsIHttpUpgradeListener : nsISupports
* using any feature exposed by this interface, be aware that this interface
* will change and you will be broken. You have been warned.
*/
[scriptable, uuid(a95e45c1-b145-487c-b2a9-4e96e814a1b5)]
[scriptable, uuid(2677e555-8c48-4147-b883-5c2a673f65d5)]
interface nsIHttpChannelInternal : nsISupports
{
/**
@ -78,8 +78,36 @@ interface nsIHttpChannelInternal : nsISupports
void setupFallbackChannel(in string aFallbackKey);
/**
* Force relevant cookies to be sent with this load even if normally they
* wouldn't be.
* This flag is set to force relevant cookies to be sent with this load
* even if normally they wouldn't be.
*/
const unsigned long THIRD_PARTY_FORCE_ALLOW = 1 << 0;
/**
* This flag is set in the parent if the child has already computed that
* it originates from a 3rd party frame (i.e. a 3rd party iframe).
*/
const unsigned long THIRD_PARTY_PARENT_IS_THIRD_PARTY = 1 << 1;
/**
* This flag is set in the parent if the child has already computed that
* it is not a 3rd party request due to iframe parentage. However, if
* someone calls mozIThirdPartyUtil::IsThirdPartyChannel with a 3rd-party
* URI, the result would be true if the URI is third-party from this
* channel's URI.
*/
const unsigned long THIRD_PARTY_PARENT_IS_SAME_PARTY = 1 << 2;
/**
* When set, these flags modify the algorithm used to decide whether to
* send 3rd party cookies for a given channel.
*/
attribute unsigned long thirdPartyFlags;
/**
* This attribute was added before the "flags" above and is retained here
* for compatibility. When set to true, has the same effect as
* THIRD_PARTY_FORCE_ALLOW, described above.
*/
attribute boolean forceAllowThirdPartyCookie;