mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1910886 - Reduce duplicated code between CookieService and CookieServiceChild - part 1 - Unify nsICookieService.getCookieStringFromDocument implementations, r=edgul,cookie-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D218312
This commit is contained in:
parent
0be12ad573
commit
8cf7d4e9d4
@ -266,6 +266,8 @@
|
||||
#include "mozilla/ipc/IdleSchedulerChild.h"
|
||||
#include "mozilla/ipc/MessageChannel.h"
|
||||
#include "mozilla/net/ChannelEventQueue.h"
|
||||
#include "mozilla/net/Cookie.h"
|
||||
#include "mozilla/net/CookieCommons.h"
|
||||
#include "mozilla/net/CookieJarSettings.h"
|
||||
#include "mozilla/net/NeckoChannelParams.h"
|
||||
#include "mozilla/net/RequestContextService.h"
|
||||
@ -462,6 +464,9 @@ mozilla::LazyLogModule gTimeoutDeferralLog("TimeoutDefer");
|
||||
mozilla::LazyLogModule gUseCountersLog("UseCounters");
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace net;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class Document::HeaderData {
|
||||
@ -6623,13 +6628,157 @@ void Document::GetCookie(nsAString& aCookie, ErrorResult& aRv) {
|
||||
// not having a cookie service isn't an error
|
||||
nsCOMPtr<nsICookieService> service =
|
||||
do_GetService(NS_COOKIESERVICE_CONTRACTID);
|
||||
if (service) {
|
||||
nsAutoCString cookie;
|
||||
service->GetCookieStringFromDocument(this, cookie);
|
||||
// CopyUTF8toUTF16 doesn't handle error
|
||||
// because it assumes that the input is valid.
|
||||
UTF_8_ENCODING->DecodeWithoutBOMHandling(cookie, aCookie);
|
||||
if (!service) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool thirdParty = true;
|
||||
nsPIDOMWindowInner* innerWindow = GetInnerWindow();
|
||||
// in gtests we don't have a window, let's consider those requests as 3rd
|
||||
// party.
|
||||
if (innerWindow) {
|
||||
ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
|
||||
|
||||
if (thirdPartyUtil) {
|
||||
Unused << thirdPartyUtil->IsThirdPartyWindow(
|
||||
innerWindow->GetOuterWindow(), nullptr, &thirdParty);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> cookiePrincipal = EffectiveCookiePrincipal();
|
||||
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> principals;
|
||||
principals.AppendElement(cookiePrincipal);
|
||||
|
||||
// CHIPS - If CHIPS is enabled the partitioned cookie jar is always available
|
||||
// (and therefore the partitioned principal), the unpartitioned cookie jar is
|
||||
// only available in first-party or third-party with storageAccess contexts.
|
||||
// In both cases, the document will have storage access.
|
||||
bool isCHIPS = StaticPrefs::network_cookie_CHIPS_enabled() &&
|
||||
CookieJarSettings()->GetPartitionForeign();
|
||||
bool documentHasStorageAccess = false;
|
||||
nsresult rv = HasStorageAccessSync(documentHasStorageAccess);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isCHIPS && documentHasStorageAccess) {
|
||||
// Assert that the cookie principal is unpartitioned.
|
||||
MOZ_ASSERT(cookiePrincipal->OriginAttributesRef().mPartitionKey.IsEmpty());
|
||||
// Only append the partitioned originAttributes if the partitionKey is set.
|
||||
// The partitionKey could be empty for partitionKey in partitioned
|
||||
// originAttributes if the document is for privilege context, such as the
|
||||
// extension's background page.
|
||||
if (!PartitionedPrincipal()
|
||||
->OriginAttributesRef()
|
||||
.mPartitionKey.IsEmpty()) {
|
||||
principals.AppendElement(PartitionedPrincipal());
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<RefPtr<Cookie>> cookieList;
|
||||
bool stale = false;
|
||||
int64_t currentTimeInUsec = PR_Now();
|
||||
int64_t currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
|
||||
|
||||
for (auto& principal : principals) {
|
||||
if (!CookieCommons::IsSchemeSupported(principal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString baseDomain;
|
||||
rv = CookieCommons::GetBaseDomain(principal, baseDomain);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString hostFromURI;
|
||||
rv = nsContentUtils::GetHostOrIPv6WithBrackets(principal, hostFromURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString pathFromURI;
|
||||
rv = principal->GetFilePath(pathFromURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<RefPtr<Cookie>> cookies;
|
||||
service->GetCookiesFromHost(baseDomain, principal->OriginAttributesRef(),
|
||||
cookies);
|
||||
if (cookies.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the nsIPrincipal is using an https secure protocol.
|
||||
// if it isn't, then we can't send a secure cookie over the connection.
|
||||
bool potentiallyTrustworthy =
|
||||
principal->GetIsOriginPotentiallyTrustworthy();
|
||||
|
||||
// iterate the cookies!
|
||||
for (Cookie* cookie : cookies) {
|
||||
// check the host, since the base domain lookup is conservative.
|
||||
if (!CookieCommons::DomainMatches(cookie, hostFromURI)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the cookie is httpOnly and it's not going directly to the HTTP
|
||||
// connection, don't send it
|
||||
if (cookie->IsHttpOnly()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thirdParty && !CookieCommons::ShouldIncludeCrossSiteCookieForDocument(
|
||||
cookie, this)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the cookie is secure and the host scheme isn't, we can't send it
|
||||
if (cookie->IsSecure() && !potentiallyTrustworthy) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the nsIURI path doesn't match the cookie path, don't send it back
|
||||
if (!CookieCommons::PathMatches(cookie, pathFromURI)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the cookie has expired
|
||||
if (cookie->Expiry() <= currentTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// all checks passed - add to list and check if lastAccessed stamp needs
|
||||
// updating
|
||||
cookieList.AppendElement(cookie);
|
||||
if (cookie->IsStale()) {
|
||||
stale = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cookieList.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update lastAccessed timestamps. we only do this if the timestamp is stale
|
||||
// by a certain amount, to avoid thrashing the db during pageload.
|
||||
if (stale) {
|
||||
service->StaleCookies(cookieList, currentTimeInUsec);
|
||||
}
|
||||
|
||||
// return cookies in order of path length; longest to shortest.
|
||||
// this is required per RFC2109. if cookies match in length,
|
||||
// then sort by creation time (see bug 236772).
|
||||
cookieList.Sort(CompareCookiesForSending());
|
||||
|
||||
nsAutoCString cookieString;
|
||||
CookieCommons::ComposeCookieString(cookieList, cookieString);
|
||||
|
||||
// CopyUTF8toUTF16 doesn't handle error
|
||||
// because it assumes that the input is valid.
|
||||
UTF_8_ENCODING->DecodeWithoutBOMHandling(cookieString, aCookie);
|
||||
}
|
||||
|
||||
void Document::SetCookie(const nsAString& aCookie, ErrorResult& aRv) {
|
||||
|
@ -818,5 +818,27 @@ bool CookieCommons::ChipsLimitEnabledAndChipsCookie(
|
||||
cookie.IsPartitioned() && cookie.RawIsPartitioned() && tcpEnabled;
|
||||
}
|
||||
|
||||
void CookieCommons::ComposeCookieString(nsTArray<RefPtr<Cookie>>& aCookieList,
|
||||
nsACString& aCookieString) {
|
||||
for (Cookie* cookie : aCookieList) {
|
||||
// check if we have anything to write
|
||||
if (!cookie->Name().IsEmpty() || !cookie->Value().IsEmpty()) {
|
||||
// if we've already added a cookie to the return list, append a "; " so
|
||||
// that subsequent cookies are delimited in the final list.
|
||||
if (!aCookieString.IsEmpty()) {
|
||||
aCookieString.AppendLiteral("; ");
|
||||
}
|
||||
|
||||
if (!cookie->Name().IsEmpty()) {
|
||||
// we have a name and value - write both
|
||||
aCookieString += cookie->Name() + "="_ns + cookie->Value();
|
||||
} else {
|
||||
// just write value
|
||||
aCookieString += cookie->Value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -143,6 +143,9 @@ class CookieCommons final {
|
||||
|
||||
static bool ChipsLimitEnabledAndChipsCookie(
|
||||
const Cookie& cookie, dom::BrowsingContext* aBrowsingContext);
|
||||
|
||||
static void ComposeCookieString(nsTArray<RefPtr<Cookie>>& aCookieList,
|
||||
nsACString& aCookieString);
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
@ -138,28 +138,6 @@ constexpr auto CONSOLE_REJECTION_CATEGORY = "cookiesRejection"_ns;
|
||||
|
||||
namespace {
|
||||
|
||||
void ComposeCookieString(nsTArray<RefPtr<Cookie>>& aCookieList,
|
||||
nsACString& aCookieString) {
|
||||
for (Cookie* cookie : aCookieList) {
|
||||
// check if we have anything to write
|
||||
if (!cookie->Name().IsEmpty() || !cookie->Value().IsEmpty()) {
|
||||
// if we've already added a cookie to the return list, append a "; " so
|
||||
// that subsequent cookies are delimited in the final list.
|
||||
if (!aCookieString.IsEmpty()) {
|
||||
aCookieString.AppendLiteral("; ");
|
||||
}
|
||||
|
||||
if (!cookie->Name().IsEmpty()) {
|
||||
// we have a name and value - write both
|
||||
aCookieString += cookie->Name() + "="_ns + cookie->Value();
|
||||
} else {
|
||||
// just write value
|
||||
aCookieString += cookie->Value();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return false if the cookie should be ignored for the current channel.
|
||||
bool ProcessSameSiteCookieForForeignRequest(nsIChannel* aChannel,
|
||||
Cookie* aCookie,
|
||||
@ -365,170 +343,6 @@ CookieService::GetCookieBehavior(bool aIsPrivate, uint32_t* aCookieBehavior) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CookieService::GetCookieStringFromDocument(Document* aDocument,
|
||||
nsACString& aCookie) {
|
||||
NS_ENSURE_ARG(aDocument);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
aCookie.Truncate();
|
||||
|
||||
if (!IsInitialized()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool thirdParty = true;
|
||||
nsPIDOMWindowInner* innerWindow = aDocument->GetInnerWindow();
|
||||
// in gtests we don't have a window, let's consider those requests as 3rd
|
||||
// party.
|
||||
if (innerWindow) {
|
||||
ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
|
||||
|
||||
if (thirdPartyUtil) {
|
||||
Unused << thirdPartyUtil->IsThirdPartyWindow(
|
||||
innerWindow->GetOuterWindow(), nullptr, &thirdParty);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> cookiePrincipal =
|
||||
aDocument->EffectiveCookiePrincipal();
|
||||
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> principals;
|
||||
principals.AppendElement(cookiePrincipal);
|
||||
|
||||
// CHIPS - If CHIPS is enabled the partitioned cookie jar is always available
|
||||
// (and therefore the partitioned principal), the unpartitioned cookie jar is
|
||||
// only available in first-party or third-party with storageAccess contexts.
|
||||
// In both cases, the document will have storage access.
|
||||
bool isCHIPS = StaticPrefs::network_cookie_CHIPS_enabled() &&
|
||||
aDocument->CookieJarSettings()->GetPartitionForeign();
|
||||
bool documentHasStorageAccess = false;
|
||||
rv = aDocument->HasStorageAccessSync(documentHasStorageAccess);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isCHIPS && documentHasStorageAccess) {
|
||||
// Assert that the cookie principal is unpartitioned.
|
||||
MOZ_ASSERT(cookiePrincipal->OriginAttributesRef().mPartitionKey.IsEmpty());
|
||||
// Only append the partitioned originAttributes if the partitionKey is set.
|
||||
// The partitionKey could be empty for partitionKey in partitioned
|
||||
// originAttributes if the document is for privilege context, such as the
|
||||
// extension's background page.
|
||||
if (!aDocument->PartitionedPrincipal()
|
||||
->OriginAttributesRef()
|
||||
.mPartitionKey.IsEmpty()) {
|
||||
principals.AppendElement(aDocument->PartitionedPrincipal());
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<RefPtr<Cookie>> cookieList;
|
||||
|
||||
for (auto& principal : principals) {
|
||||
if (!CookieCommons::IsSchemeSupported(principal)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
CookieStorage* storage = PickStorage(principal->OriginAttributesRef());
|
||||
|
||||
nsAutoCString baseDomain;
|
||||
rv = CookieCommons::GetBaseDomain(principal, baseDomain);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString hostFromURI;
|
||||
rv = nsContentUtils::GetHostOrIPv6WithBrackets(principal, hostFromURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString pathFromURI;
|
||||
rv = principal->GetFilePath(pathFromURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int64_t currentTimeInUsec = PR_Now();
|
||||
int64_t currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
|
||||
|
||||
nsTArray<RefPtr<Cookie>> cookies;
|
||||
storage->GetCookiesFromHost(baseDomain, principal->OriginAttributesRef(),
|
||||
cookies);
|
||||
if (cookies.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the nsIPrincipal is using an https secure protocol.
|
||||
// if it isn't, then we can't send a secure cookie over the connection.
|
||||
bool potentiallyTrustworthy =
|
||||
principal->GetIsOriginPotentiallyTrustworthy();
|
||||
|
||||
bool stale = false;
|
||||
|
||||
// iterate the cookies!
|
||||
for (Cookie* cookie : cookies) {
|
||||
// check the host, since the base domain lookup is conservative.
|
||||
if (!CookieCommons::DomainMatches(cookie, hostFromURI)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the cookie is httpOnly and it's not going directly to the HTTP
|
||||
// connection, don't send it
|
||||
if (cookie->IsHttpOnly()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thirdParty && !CookieCommons::ShouldIncludeCrossSiteCookieForDocument(
|
||||
cookie, aDocument)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the cookie is secure and the host scheme isn't, we can't send it
|
||||
if (cookie->IsSecure() && !potentiallyTrustworthy) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the nsIURI path doesn't match the cookie path, don't send it back
|
||||
if (!CookieCommons::PathMatches(cookie, pathFromURI)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the cookie has expired
|
||||
if (cookie->Expiry() <= currentTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// all checks passed - add to list and check if lastAccessed stamp needs
|
||||
// updating
|
||||
cookieList.AppendElement(cookie);
|
||||
if (cookie->IsStale()) {
|
||||
stale = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (cookieList.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// update lastAccessed timestamps. we only do this if the timestamp is stale
|
||||
// by a certain amount, to avoid thrashing the db during pageload.
|
||||
if (stale) {
|
||||
storage->StaleCookies(cookieList, currentTimeInUsec);
|
||||
}
|
||||
}
|
||||
|
||||
if (cookieList.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// return cookies in order of path length; longest to shortest.
|
||||
// this is required per RFC2109. if cookies match in length,
|
||||
// then sort by creation time (see bug 236772).
|
||||
cookieList.Sort(CompareCookiesForSending());
|
||||
ComposeCookieString(cookieList, aCookie);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CookieService::GetCookieStringFromHttp(nsIURI* aHostURI, nsIChannel* aChannel,
|
||||
nsACString& aCookieString) {
|
||||
@ -597,7 +411,7 @@ CookieService::GetCookieStringFromHttp(nsIURI* aHostURI, nsIChannel* aChannel,
|
||||
hadCrossSiteRedirects, true, false, originAttributesList,
|
||||
foundCookieList);
|
||||
|
||||
ComposeCookieString(foundCookieList, aCookieString);
|
||||
CookieCommons::ComposeCookieString(foundCookieList, aCookieString);
|
||||
|
||||
if (!aCookieString.IsEmpty()) {
|
||||
COOKIE_LOGSUCCESS(GET_COOKIE, aHostURI, aCookieString, nullptr, false);
|
||||
@ -1879,5 +1693,39 @@ bool CookieService::SetCookiesFromIPC(const nsACString& aBaseDomain,
|
||||
return true;
|
||||
}
|
||||
|
||||
void CookieService::GetCookiesFromHost(
|
||||
const nsACString& aBaseDomain,
|
||||
const mozilla::OriginAttributes& aOriginAttributes,
|
||||
nsTArray<RefPtr<mozilla::net::Cookie>>& aCookies) {
|
||||
if (!IsInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CookieStorage* storage = PickStorage(aOriginAttributes);
|
||||
storage->GetCookiesFromHost(aBaseDomain, aOriginAttributes, aCookies);
|
||||
}
|
||||
|
||||
void CookieService::StaleCookies(
|
||||
const nsTArray<RefPtr<mozilla::net::Cookie>>& aCookies,
|
||||
int64_t aCurrentTimeInUsec) {
|
||||
if (!IsInitialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aCookies.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OriginAttributes originAttributes = aCookies[0]->OriginAttributesRef();
|
||||
#ifdef MOZ_DEBUG
|
||||
for (Cookie* cookie : aCookies) {
|
||||
MOZ_ASSERT(originAttributes == cookie->OriginAttributesRef());
|
||||
}
|
||||
#endif
|
||||
|
||||
CookieStorage* storage = PickStorage(originAttributes);
|
||||
storage->StaleCookies(aCookies, aCurrentTimeInUsec);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -345,139 +345,6 @@ void CookieServiceChild::RecordDocumentCookie(Cookie* aCookie,
|
||||
cookiesList->AppendElement(aCookie);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CookieServiceChild::GetCookieStringFromDocument(dom::Document* aDocument,
|
||||
nsACString& aCookieString) {
|
||||
NS_ENSURE_ARG(aDocument);
|
||||
|
||||
aCookieString.Truncate();
|
||||
|
||||
bool thirdParty = true;
|
||||
nsPIDOMWindowInner* innerWindow = aDocument->GetInnerWindow();
|
||||
// in gtests we don't have a window, let's consider those requests as 3rd
|
||||
// party.
|
||||
if (innerWindow) {
|
||||
ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
|
||||
|
||||
if (thirdPartyUtil) {
|
||||
Unused << thirdPartyUtil->IsThirdPartyWindow(
|
||||
innerWindow->GetOuterWindow(), nullptr, &thirdParty);
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> cookiePrincipal =
|
||||
aDocument->EffectiveCookiePrincipal();
|
||||
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> principals;
|
||||
principals.AppendElement(cookiePrincipal);
|
||||
|
||||
// CHIPS - If CHIPS is enabled the partitioned cookie jar is always available
|
||||
// (and therefore the partitioned principal), the unpartitioned cookie jar is
|
||||
// only available in first-party or third-party with storageAccess contexts.
|
||||
// In both cases, the document will have storage access.
|
||||
bool isCHIPS = aDocument->CookieJarSettings()->GetPartitionForeign() &&
|
||||
StaticPrefs::network_cookie_CHIPS_enabled();
|
||||
bool documentHasStorageAccess = false;
|
||||
nsresult rv = aDocument->HasStorageAccessSync(documentHasStorageAccess);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isCHIPS && documentHasStorageAccess) {
|
||||
/// Assert that the cookie principal is unpartitioned.
|
||||
MOZ_ASSERT(cookiePrincipal->OriginAttributesRef().mPartitionKey.IsEmpty());
|
||||
// Only append the partitioned originAttributes if the partitionKey is set.
|
||||
// The partitionKey could be empty for partitionKey in partitioned
|
||||
// originAttributes if the document is for privilege context, such as the
|
||||
// extension's background page.
|
||||
if (!aDocument->PartitionedPrincipal()
|
||||
->OriginAttributesRef()
|
||||
.mPartitionKey.IsEmpty()) {
|
||||
principals.AppendElement(aDocument->PartitionedPrincipal());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& principal : principals) {
|
||||
if (!CookieCommons::IsSchemeSupported(principal)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString baseDomain;
|
||||
rv = CookieCommons::GetBaseDomain(principal, baseDomain);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
CookieKey key(baseDomain, principal->OriginAttributesRef());
|
||||
CookiesList* cookiesList = nullptr;
|
||||
mCookiesMap.Get(key, &cookiesList);
|
||||
|
||||
if (!cookiesList) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoCString hostFromURI;
|
||||
rv = nsContentUtils::GetHostOrIPv6WithBrackets(principal, hostFromURI);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString pathFromURI;
|
||||
principal->GetFilePath(pathFromURI);
|
||||
|
||||
bool isPotentiallyTrustworthy =
|
||||
principal->GetIsOriginPotentiallyTrustworthy();
|
||||
int64_t currentTimeInUsec = PR_Now();
|
||||
int64_t currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
|
||||
|
||||
cookiesList->Sort(CompareCookiesForSending());
|
||||
for (uint32_t i = 0; i < cookiesList->Length(); i++) {
|
||||
Cookie* cookie = cookiesList->ElementAt(i);
|
||||
// check the host, since the base domain lookup is conservative.
|
||||
if (!CookieCommons::DomainMatches(cookie, hostFromURI)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We don't show HttpOnly cookies in content processes.
|
||||
if (cookie->IsHttpOnly()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (thirdParty && !CookieCommons::ShouldIncludeCrossSiteCookieForDocument(
|
||||
cookie, aDocument)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// do not display the cookie if it is secure and the host scheme isn't
|
||||
if (cookie->IsSecure() && !isPotentiallyTrustworthy) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the nsIURI path doesn't match the cookie path, don't send it back
|
||||
if (!CookieCommons::PathMatches(cookie, pathFromURI)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if the cookie has expired
|
||||
if (cookie->Expiry() <= currentTime) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cookie->Name().IsEmpty() || !cookie->Value().IsEmpty()) {
|
||||
if (!aCookieString.IsEmpty()) {
|
||||
aCookieString.AppendLiteral("; ");
|
||||
}
|
||||
if (!cookie->Name().IsEmpty()) {
|
||||
aCookieString.Append(cookie->Name().get());
|
||||
aCookieString.AppendLiteral("=");
|
||||
aCookieString.Append(cookie->Value().get());
|
||||
} else {
|
||||
aCookieString.Append(cookie->Value().get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CookieServiceChild::GetCookieStringFromHttp(nsIURI* /*aHostURI*/,
|
||||
nsIChannel* /*aChannel*/,
|
||||
@ -785,5 +652,25 @@ CookieServiceChild::RunInTransaction(
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void CookieServiceChild::GetCookiesFromHost(
|
||||
const nsACString& aBaseDomain,
|
||||
const mozilla::OriginAttributes& aOriginAttributes,
|
||||
nsTArray<RefPtr<mozilla::net::Cookie>>& aCookies) {
|
||||
CookieKey key(aBaseDomain, aOriginAttributes);
|
||||
|
||||
CookiesList* cookiesList = nullptr;
|
||||
mCookiesMap.Get(key, &cookiesList);
|
||||
|
||||
if (cookiesList) {
|
||||
aCookies.AppendElements(*cookiesList);
|
||||
}
|
||||
}
|
||||
|
||||
void CookieServiceChild::StaleCookies(
|
||||
const nsTArray<RefPtr<mozilla::net::Cookie>>& aCookies,
|
||||
int64_t aCurrentTimeInUsec) {
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -22,6 +22,7 @@ XPIDL_MODULE = "necko_cookie"
|
||||
|
||||
EXPORTS.mozilla.net = [
|
||||
"Cookie.h",
|
||||
"CookieCommons.h",
|
||||
"CookieJarSettings.h",
|
||||
"CookieKey.h",
|
||||
"CookieNotification.h",
|
||||
|
@ -5,10 +5,24 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIChannel;
|
||||
interface nsICookie;
|
||||
interface nsIURI;
|
||||
webidl Document;
|
||||
|
||||
%{C++
|
||||
namespace mozilla {
|
||||
class OriginAttributes;
|
||||
|
||||
namespace net {
|
||||
class Cookie;
|
||||
}
|
||||
}
|
||||
%}
|
||||
|
||||
[ref] native const_OriginAttributes(const mozilla::OriginAttributes);
|
||||
native CookiePtr(RefPtr<mozilla::net::Cookie>);
|
||||
|
||||
/**
|
||||
* @see nsICookieService::runInTransaction
|
||||
*/
|
||||
@ -50,7 +64,7 @@ interface nsICookieTransactionCallback : nsISupports
|
||||
* to set the cookie.
|
||||
* data : none.
|
||||
*/
|
||||
[scriptable, uuid(1e94e283-2811-4f43-b947-d22b1549d824)]
|
||||
[builtinclass, scriptable, uuid(1e94e283-2811-4f43-b947-d22b1549d824)]
|
||||
interface nsICookieService : nsISupports
|
||||
{
|
||||
/*
|
||||
@ -67,17 +81,18 @@ interface nsICookieService : nsISupports
|
||||
const uint32_t BEHAVIOR_LAST = 5;
|
||||
|
||||
/*
|
||||
* Get the complete cookie string associated with the document's principal.
|
||||
* Get the list of cookies associated with a base domain and an OriginAttributes.
|
||||
* This method is meant to be used for `document.cookie` only. Any security
|
||||
* check about storage-access permission and cookie behavior must be done by
|
||||
* the caller.
|
||||
*
|
||||
* @param aDocument
|
||||
* The document.
|
||||
*
|
||||
* @return the resulting cookie string
|
||||
*/
|
||||
ACString getCookieStringFromDocument(in Document aDocument);
|
||||
[noscript, notxpcom, nostdcall] void getCookiesFromHost(in ACString aBaseDomain,
|
||||
in const_OriginAttributes aOriginAttributes,
|
||||
out Array<CookiePtr> aCookies);
|
||||
|
||||
/* Update the last access to stale cookies */
|
||||
[noscript, notxpcom, nostdcall] void staleCookies(in Array<CookiePtr> aCookies,
|
||||
in int64_t aCurrentTimeInUsec);
|
||||
|
||||
/*
|
||||
* Get the complete cookie string associated with the URI.
|
||||
|
@ -300,7 +300,7 @@ add_task(
|
||||
// CookieService::SetCookieStringFromHttp() call.
|
||||
|
||||
// Get partitioned and unpartitioned cookies from document (child).
|
||||
// This calls CookieServiceChild::GetCookieStringFromDocument() internally.
|
||||
// This uses CookieServiceChild internally.
|
||||
add_task(
|
||||
async function test_chips_send_partitioned_and_unpartitioned_document_child() {
|
||||
const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
|
||||
|
@ -154,7 +154,12 @@ void GetACookieNoHttp(nsICookieService* aCookieService, const char* aSpec,
|
||||
DocumentFlavorHTML);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
|
||||
Unused << aCookieService->GetCookieStringFromDocument(document, aCookie);
|
||||
nsAutoString cookie;
|
||||
ErrorResult err;
|
||||
document->GetCookie(cookie, err);
|
||||
MOZ_ASSERT(!err.Failed());
|
||||
|
||||
CopyUTF16toUTF8(cookie, aCookie);
|
||||
}
|
||||
|
||||
// some #defines for comparison rules
|
||||
|
1
tools/@types/lib.gecko.xpcom.d.ts
vendored
1
tools/@types/lib.gecko.xpcom.d.ts
vendored
@ -7707,7 +7707,6 @@ interface nsICookieService extends nsISupports {
|
||||
readonly BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN: 5;
|
||||
readonly BEHAVIOR_LAST: 5;
|
||||
|
||||
getCookieStringFromDocument(aDocument: Document): string;
|
||||
getCookieStringFromHttp(aURI: nsIURI, aChannel: nsIChannel): string;
|
||||
setCookieStringFromDocument(aDocument: Document, aCookie: string): void;
|
||||
setCookieStringFromHttp(aURI: nsIURI, aCookie: string, aChannel: nsIChannel): void;
|
||||
|
Loading…
Reference in New Issue
Block a user