зеркало из https://github.com/mozilla/pjs.git
Bug 295994 part 1 - add cookieservice accessors for individual cookies by name, obeying privacy preferences r=dwitte+darin
This commit is contained in:
Родитель
b642130d40
Коммит
57c9ba936e
|
@ -53,6 +53,7 @@ SDK_XPIDLSRCS = \
|
|||
|
||||
XPIDLSRCS = \
|
||||
nsICookieService.idl \
|
||||
nsICookieServiceInternal.idl \
|
||||
nsICookie2.idl \
|
||||
nsICookieConsent.idl \
|
||||
nsICookieManager2.idl \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// vim:ts=2:sw=2:et:
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -371,8 +371,9 @@ nsCookieService::GetSingleton()
|
|||
* public methods
|
||||
******************************************************************************/
|
||||
|
||||
NS_IMPL_ISUPPORTS5(nsCookieService,
|
||||
NS_IMPL_ISUPPORTS6(nsCookieService,
|
||||
nsICookieService,
|
||||
nsICookieServiceInternal,
|
||||
nsICookieManager,
|
||||
nsICookieManager2,
|
||||
nsIObserver,
|
||||
|
@ -481,36 +482,19 @@ nsCookieService::Observe(nsISupports *aSubject,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::GetCookieString(nsIURI *aHostURI,
|
||||
nsIChannel *aChannel,
|
||||
char **aCookie)
|
||||
{
|
||||
// try to determine first party URI
|
||||
nsCOMPtr<nsIURI> firstURI;
|
||||
if (aChannel) {
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(aChannel);
|
||||
if (httpInternal)
|
||||
httpInternal->GetDocumentURI(getter_AddRefs(firstURI));
|
||||
}
|
||||
|
||||
return GetCookieStringFromHttp(aHostURI, firstURI, aChannel, aCookie);
|
||||
}
|
||||
|
||||
// helper function for GetCookieStringFromHttp
|
||||
static inline PRBool ispathdelimiter(char c) { return c == '/' || c == '?' || c == '#' || c == ';'; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
||||
nsIURI *aFirstURI,
|
||||
nsIChannel *aChannel,
|
||||
char **aCookie)
|
||||
void
|
||||
nsCookieService::GetCookieList(nsIURI *aHostURI,
|
||||
nsIURI *aFirstURI,
|
||||
nsIChannel *aChannel,
|
||||
const nsACString *aName,
|
||||
nsAutoVoidArray &aResult)
|
||||
{
|
||||
*aCookie = nsnull;
|
||||
|
||||
if (!aHostURI) {
|
||||
COOKIE_LOGFAILURE(GET_COOKIE, nsnull, nsnull, "host URI is null");
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
// check default prefs
|
||||
|
@ -520,7 +504,7 @@ nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
|||
switch (cookieStatus) {
|
||||
case nsICookie::STATUS_REJECTED:
|
||||
case STATUS_REJECTED_WITH_ERROR:
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
// get host and path from the nsIURI
|
||||
|
@ -530,7 +514,7 @@ nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
|||
if (NS_FAILED(aHostURI->GetAsciiHost(hostFromURI)) ||
|
||||
NS_FAILED(aHostURI->GetPath(pathFromURI))) {
|
||||
COOKIE_LOGFAILURE(GET_COOKIE, aHostURI, nsnull, "couldn't get host/path from URI");
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
// trim trailing dots
|
||||
hostFromURI.Trim(".");
|
||||
|
@ -548,7 +532,6 @@ nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
|||
}
|
||||
|
||||
nsCookie *cookie;
|
||||
nsAutoVoidArray foundCookieList;
|
||||
nsInt64 currentTime = NOW_IN_SECONDS;
|
||||
const char *currentDot = hostFromURI.get();
|
||||
const char *nextDot = currentDot + 1;
|
||||
|
@ -559,6 +542,11 @@ nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
|||
nsCookieEntry *entry = mHostTable.GetEntry(currentDot);
|
||||
cookie = entry ? entry->Head() : nsnull;
|
||||
for (; cookie; cookie = cookie->Next()) {
|
||||
// check the cookie name, if appropriate
|
||||
if (aName && !aName->Equals(cookie->Name())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the cookie is secure and the host scheme isn't, we can't send it
|
||||
if (cookie->IsSecure() && !isSecure) {
|
||||
continue;
|
||||
|
@ -594,7 +582,7 @@ nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
|||
}
|
||||
|
||||
// all checks passed - add to list and update lastAccessed stamp of cookie
|
||||
foundCookieList.AppendElement(cookie);
|
||||
aResult.AppendElement(cookie);
|
||||
cookie->SetLastAccessed(currentTime);
|
||||
}
|
||||
|
||||
|
@ -607,12 +595,70 @@ nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
|||
// 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).
|
||||
foundCookieList.Sort(compareCookiesForSending, nsnull);
|
||||
aResult.Sort(compareCookiesForSending, nsnull);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::GetCookieValue(nsIURI *aHostURI,
|
||||
nsIChannel *aChannel,
|
||||
const nsACString& aName,
|
||||
nsACString& aResult)
|
||||
{
|
||||
aResult.Truncate();
|
||||
|
||||
// try to determine first party URI
|
||||
nsCOMPtr<nsIURI> firstURI;
|
||||
if (aChannel) {
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(aChannel);
|
||||
if (httpInternal)
|
||||
httpInternal->GetDocumentURI(getter_AddRefs(firstURI));
|
||||
}
|
||||
|
||||
nsAutoVoidArray foundCookieList;
|
||||
GetCookieList(aHostURI, firstURI, aChannel, &aName,
|
||||
foundCookieList);
|
||||
|
||||
if (!foundCookieList.Count())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
nsCookie *cookie = NS_STATIC_CAST(nsCookie*, foundCookieList[0]);
|
||||
|
||||
aResult.Assign(cookie->Value());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::GetCookieString(nsIURI *aHostURI,
|
||||
nsIChannel *aChannel,
|
||||
char **aCookie)
|
||||
{
|
||||
// try to determine first party URI
|
||||
nsCOMPtr<nsIURI> firstURI;
|
||||
if (aChannel) {
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(aChannel);
|
||||
if (httpInternal)
|
||||
httpInternal->GetDocumentURI(getter_AddRefs(firstURI));
|
||||
}
|
||||
|
||||
return GetCookieStringFromHttp(aHostURI, firstURI, aChannel, aCookie);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
||||
nsIURI *aFirstURI,
|
||||
nsIChannel *aChannel,
|
||||
char **aCookie)
|
||||
{
|
||||
*aCookie = nsnull;
|
||||
|
||||
nsAutoVoidArray foundCookieList;
|
||||
GetCookieList(aHostURI, aFirstURI, aChannel, nsnull,
|
||||
foundCookieList);
|
||||
|
||||
nsCAutoString cookieData;
|
||||
PRInt32 count = foundCookieList.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
cookie = NS_STATIC_CAST(nsCookie*, foundCookieList.ElementAt(i));
|
||||
nsCookie *cookie = NS_STATIC_CAST(nsCookie*, foundCookieList.ElementAt(i));
|
||||
|
||||
// check if we have anything to write
|
||||
if (!cookie->Name().IsEmpty() || !cookie->Value().IsEmpty()) {
|
||||
|
@ -642,6 +688,52 @@ nsCookieService::GetCookieStringFromHttp(nsIURI *aHostURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::SetCookieValue(nsIURI *aHostURI,
|
||||
nsIChannel *aChannel,
|
||||
const nsACString& aDomain,
|
||||
const nsACString& aPath,
|
||||
const nsACString& aName,
|
||||
const nsACString& aValue,
|
||||
PRBool aIsSession,
|
||||
PRInt64 aExpiry)
|
||||
{
|
||||
// try to determine first party URI
|
||||
nsCOMPtr<nsIURI> firstURI;
|
||||
|
||||
if (aChannel) {
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(aChannel);
|
||||
if (httpInternal)
|
||||
httpInternal->GetDocumentURI(getter_AddRefs(firstURI));
|
||||
}
|
||||
|
||||
// check default prefs
|
||||
nsCookiePolicy cookiePolicy = nsICookie::POLICY_UNKNOWN;
|
||||
nsCookieStatus cookieStatus = CheckPrefs(aHostURI, firstURI, aChannel, "", cookiePolicy);
|
||||
// fire a notification if cookie was rejected (but not if there was an error)
|
||||
switch (cookieStatus) {
|
||||
case nsICookie::STATUS_REJECTED:
|
||||
NotifyRejected(aHostURI);
|
||||
case STATUS_REJECTED_WITH_ERROR:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCookieAttributes attributes;
|
||||
attributes.name = aName;
|
||||
attributes.value = aValue;
|
||||
attributes.host = aDomain;
|
||||
attributes.path = aPath;
|
||||
attributes.expiryTime = aExpiry;
|
||||
attributes.isSession = aIsSession;
|
||||
|
||||
attributes.isSecure = PR_FALSE;
|
||||
aHostURI->SchemeIs("https", &attributes.isSecure);
|
||||
|
||||
CheckAndAdd(aHostURI, aChannel, attributes,
|
||||
cookieStatus, cookiePolicy, EmptyCString());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsCookieService::SetCookieString(nsIURI *aHostURI,
|
||||
nsIPrompt *aPrompt,
|
||||
|
@ -1141,14 +1233,10 @@ PRBool
|
|||
nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
||||
nsIChannel *aChannel,
|
||||
nsDependentCString &aCookieHeader,
|
||||
nsInt64 aServerTime,
|
||||
nsCookieStatus aStatus,
|
||||
nsCookiePolicy aPolicy)
|
||||
nsInt64 aServerTime,
|
||||
nsCookieStatus aStatus,
|
||||
nsCookiePolicy aPolicy)
|
||||
{
|
||||
// keep a |const char*| version of the unmodified aCookieHeader,
|
||||
// for logging purposes
|
||||
const char *cookieHeader = aCookieHeader.get();
|
||||
|
||||
// create a stack-based nsCookieAttributes, to store all the
|
||||
// attributes parsed from the cookie
|
||||
nsCookieAttributes cookieAttributes;
|
||||
|
@ -1156,16 +1244,12 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
|||
// init expiryTime such that session cookies won't prematurely expire
|
||||
cookieAttributes.expiryTime = LL_MAXINT;
|
||||
|
||||
// newCookie says whether there are multiple cookies in the header; so we can handle them separately.
|
||||
// after this function, we don't need the cookieHeader string for processing this cookie anymore;
|
||||
// so this function uses it as an outparam to point to the next cookie, if there is one.
|
||||
const PRBool newCookie = ParseAttributes(aCookieHeader, cookieAttributes);
|
||||
|
||||
// reject cookie if it's over the size limit, per RFC2109
|
||||
if ((cookieAttributes.name.Length() + cookieAttributes.value.Length()) > kMaxBytesPerCookie) {
|
||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, cookieHeader, "cookie too big (> 4kb)");
|
||||
return newCookie;
|
||||
}
|
||||
// newCookie says whether there are multiple cookies in the header;
|
||||
// so we can handle them separately. This function uses
|
||||
// "thisCookieHaeder" as an in/out param to point to the next
|
||||
// cookie, if there is one.
|
||||
nsDependentCString thisCookieHeader(aCookieHeader);
|
||||
const PRBool newCookie = ParseAttributes(thisCookieHeader, cookieAttributes);
|
||||
|
||||
// calculate expiry time of cookie. we need to pass in cookieStatus, since
|
||||
// the cookie may have been downgraded to a session cookie by p3p.
|
||||
|
@ -1173,30 +1257,52 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
|||
cookieAttributes.isSession = GetExpiry(cookieAttributes, aServerTime,
|
||||
currentTime, aStatus);
|
||||
|
||||
CheckAndAdd(aHostURI, aChannel, cookieAttributes,
|
||||
aStatus, aPolicy, aCookieHeader);
|
||||
|
||||
return newCookie;
|
||||
}
|
||||
|
||||
void
|
||||
nsCookieService::CheckAndAdd(nsIURI *aHostURI,
|
||||
nsIChannel *aChannel,
|
||||
nsCookieAttributes &aAttributes,
|
||||
nsCookieStatus aStatus,
|
||||
const nsCookiePolicy aPolicy,
|
||||
const nsAFlatCString &aCookieHeader)
|
||||
{
|
||||
// reject cookie if it's over the size limit, per RFC2109
|
||||
if ((aAttributes.name.Length() + aAttributes.value.Length()) > kMaxBytesPerCookie) {
|
||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "cookie too big (> 4kb)");
|
||||
return;
|
||||
}
|
||||
|
||||
// domain & path checks
|
||||
if (!CheckDomain(cookieAttributes, aHostURI)) {
|
||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, cookieHeader, "failed the domain tests");
|
||||
return newCookie;
|
||||
if (!CheckDomain(aAttributes, aHostURI)) {
|
||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "failed the domain tests");
|
||||
return;
|
||||
}
|
||||
if (!CheckPath(cookieAttributes, aHostURI)) {
|
||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, cookieHeader, "failed the path tests");
|
||||
return newCookie;
|
||||
if (!CheckPath(aAttributes, aHostURI)) {
|
||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "failed the path tests");
|
||||
return;
|
||||
}
|
||||
|
||||
const nsInt64 currentTime = NOW_IN_SECONDS;
|
||||
|
||||
// create a new nsCookie and copy attributes
|
||||
nsRefPtr<nsCookie> cookie =
|
||||
nsCookie::Create(cookieAttributes.name,
|
||||
cookieAttributes.value,
|
||||
cookieAttributes.host,
|
||||
cookieAttributes.path,
|
||||
cookieAttributes.expiryTime,
|
||||
nsCookie::Create(aAttributes.name,
|
||||
aAttributes.value,
|
||||
aAttributes.host,
|
||||
aAttributes.path,
|
||||
aAttributes.expiryTime,
|
||||
currentTime,
|
||||
cookieAttributes.isSession,
|
||||
cookieAttributes.isSecure,
|
||||
aAttributes.isSession,
|
||||
aAttributes.isSecure,
|
||||
aStatus,
|
||||
aPolicy);
|
||||
if (!cookie) {
|
||||
return newCookie;
|
||||
return;
|
||||
}
|
||||
|
||||
// check permissions from site permission list, or ask the user,
|
||||
|
@ -1208,23 +1314,22 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
|||
mPermissionService->CanSetCookie(aHostURI,
|
||||
aChannel,
|
||||
NS_STATIC_CAST(nsICookie2*, NS_STATIC_CAST(nsCookie*, cookie)),
|
||||
&cookieAttributes.isSession,
|
||||
&cookieAttributes.expiryTime.mValue,
|
||||
&aAttributes.isSession,
|
||||
&aAttributes.expiryTime.mValue,
|
||||
&permission);
|
||||
if (!permission) {
|
||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, cookieHeader, "cookie rejected by permission manager");
|
||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "cookie rejected by permission manager");
|
||||
NotifyRejected(aHostURI);
|
||||
return newCookie;
|
||||
return;
|
||||
}
|
||||
|
||||
// update isSession and expiry attributes, in case they changed
|
||||
cookie->SetIsSession(cookieAttributes.isSession);
|
||||
cookie->SetExpiry(cookieAttributes.expiryTime);
|
||||
cookie->SetIsSession(aAttributes.isSession);
|
||||
cookie->SetExpiry(aAttributes.expiryTime);
|
||||
}
|
||||
|
||||
// add the cookie to the list. AddInternal() takes care of logging.
|
||||
AddInternal(cookie, NOW_IN_SECONDS, aHostURI, cookieHeader);
|
||||
return newCookie;
|
||||
AddInternal(cookie, NOW_IN_SECONDS, aHostURI, aCookieHeader.get());
|
||||
}
|
||||
|
||||
// this is a backend function for adding a cookie to the list, via SetCookie.
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#ifndef nsCookieService_h__
|
||||
#define nsCookieService_h__
|
||||
|
||||
#include "nsICookieService.h"
|
||||
#include "nsICookieServiceInternal.h"
|
||||
#include "nsICookieManager.h"
|
||||
#include "nsICookieManager2.h"
|
||||
#include "nsIObserver.h"
|
||||
|
@ -55,6 +55,9 @@
|
|||
struct nsCookieAttributes;
|
||||
struct nsListIter;
|
||||
struct nsEnumerationData;
|
||||
|
||||
class nsAutoVoidArray;
|
||||
|
||||
class nsIPrefBranch;
|
||||
class nsICookieConsent;
|
||||
class nsICookiePermission;
|
||||
|
@ -149,7 +152,7 @@ class nsCookieEntry : public PLDHashEntryHdr
|
|||
* class declaration
|
||||
******************************************************************************/
|
||||
|
||||
class nsCookieService : public nsICookieService
|
||||
class nsCookieService : public nsICookieServiceInternal
|
||||
, public nsICookieManager2
|
||||
, public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
|
@ -159,6 +162,7 @@ class nsCookieService : public nsICookieService
|
|||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSICOOKIESERVICE
|
||||
NS_DECL_NSICOOKIESERVICEINTERNAL
|
||||
NS_DECL_NSICOOKIEMANAGER
|
||||
NS_DECL_NSICOOKIEMANAGER2
|
||||
|
||||
|
@ -171,7 +175,9 @@ class nsCookieService : public nsICookieService
|
|||
void PrefChanged(nsIPrefBranch *aPrefBranch);
|
||||
nsresult Read();
|
||||
nsresult Write();
|
||||
void GetCookieList(nsIURI *aHostURI, nsIURI *aFirstURI, nsIChannel *aChannel, const nsACString *aName, nsAutoVoidArray &aResult);
|
||||
PRBool SetCookieInternal(nsIURI *aHostURI, nsIChannel *aChannel, nsDependentCString &aCookieHeader, nsInt64 aServerTime, nsCookieStatus aStatus, nsCookiePolicy aPolicy);
|
||||
void CheckAndAdd(nsIURI *aHostURI, nsIChannel *aChannel, nsCookieAttributes &aAttributes, nsCookieStatus aStatus, nsCookiePolicy aPolicy, const nsAFlatCString &aCookieHeader);
|
||||
void AddInternal(nsCookie *aCookie, nsInt64 aCurrentTime, nsIURI *aHostURI, const char *aCookieHeader);
|
||||
void RemoveCookieFromList(nsListIter &aIter);
|
||||
PRBool AddCookieToList(nsCookie *aCookie);
|
||||
|
|
Загрузка…
Ссылка в новой задаче