Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_net_CookieStorage_h
#define mozilla_net_CookieStorage_h
#include "CookieKey.h"
#include "nsICookieNotification.h"
#include "nsIObserver.h"
#include "nsTHashtable.h"
#include "nsWeakReference.h"
#include <functional>
#include "CookieCommons.h"
class nsIArray;
class nsICookie;
class nsICookieTransactionCallback;
class nsIPrefBranch;
namespace mozilla {
namespace net {
class Cookie;
// Inherit from CookieKey so this can be stored in nsTHashTable
// TODO: why aren't we using nsClassHashTable<CookieKey, ArrayType>?
class CookieEntry : public CookieKey {
public:
// Hash methods
using ArrayType = nsTArray<RefPtr<Cookie>>;
using IndexType = ArrayType::index_type;
explicit CookieEntry(KeyTypePointer aKey) : CookieKey(aKey) {}
CookieEntry(const CookieEntry& toCopy) {
// if we end up here, things will break. nsTHashtable shouldn't
// allow this, since we set ALLOW_MEMMOVE to true.
MOZ_ASSERT_UNREACHABLE("CookieEntry copy constructor is forbidden!");
}
~CookieEntry() = default;
inline ArrayType& GetCookies() { return mCookies; }
inline const ArrayType& GetCookies() const { return mCookies; }
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
bool IsPartitioned() const;
private:
ArrayType mCookies;
};
// stores the CookieEntry entryclass and an index into the cookie array within
// that entryclass, for purposes of storing an iteration state that points to a
// certain cookie.
struct CookieListIter {
// default (non-initializing) constructor.
CookieListIter() = default;
// explicit constructor to a given iterator state with entryclass 'aEntry'
// and index 'aIndex'.
explicit CookieListIter(CookieEntry* aEntry, CookieEntry::IndexType aIndex)
: entry(aEntry), index(aIndex) {}
// get the Cookie * the iterator currently points to.
mozilla::net::Cookie* Cookie() const { return entry->GetCookies()[index]; }
CookieEntry* entry;
CookieEntry::IndexType index;
};
class CookieStorage : public nsIObserver, public nsSupportsWeakReference {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
void GetCookies(nsTArray<RefPtr<nsICookie>>& aCookies) const;
void GetSessionCookies(nsTArray<RefPtr<nsICookie>>& aCookies) const;
bool FindCookie(const nsACString& aBaseDomain,
const OriginAttributes& aOriginAttributes,
const nsACString& aHost, const nsACString& aName,
const nsACString& aPath, CookieListIter& aIter);
uint32_t CountCookiesFromHost(const nsACString& aBaseDomain,
uint32_t aPrivateBrowsingId);
void GetAll(nsTArray<RefPtr<nsICookie>>& aResult) const;
const nsTArray<RefPtr<Cookie>>* GetCookiesFromHost(
const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes);
void GetCookiesWithOriginAttributes(const OriginAttributesPattern& aPattern,
const nsACString& aBaseDomain,
nsTArray<RefPtr<nsICookie>>& aResult);
void RemoveCookie(const nsACString& aBaseDomain,
const OriginAttributes& aOriginAttributes,
const nsACString& aHost, const nsACString& aName,
const nsACString& aPath);
virtual void RemoveCookiesWithOriginAttributes(
const OriginAttributesPattern& aPattern, const nsACString& aBaseDomain);
virtual void RemoveCookiesFromExactHost(
const nsACString& aHost, const nsACString& aBaseDomain,
const OriginAttributesPattern& aPattern);
void RemoveAll();
void NotifyChanged(nsISupports* aSubject,
nsICookieNotification::Action aAction,
const nsACString& aBaseDomain,
dom::BrowsingContext* aBrowsingContext = nullptr,
bool aOldCookieIsSession = false);
void AddCookie(nsIConsoleReportCollector* aCRC, const nsACString& aBaseDomain,
const OriginAttributes& aOriginAttributes, Cookie* aCookie,
int64_t aCurrentTimeInUsec, nsIURI* aHostURI,
const nsACString& aCookieHeader, bool aFromHttp,
dom::BrowsingContext* aBrowsingContext);
static void CreateOrUpdatePurgeList(nsCOMPtr<nsIArray>& aPurgedList,
nsICookie* aCookie);
virtual void StaleCookies(const nsTArray<Cookie*>& aCookieList,
int64_t aCurrentTimeInUsec) = 0;
virtual void Close() = 0;
virtual void EnsureInitialized() = 0;
virtual nsresult RunInTransaction(
nsICookieTransactionCallback* aCallback) = 0;
protected:
CookieStorage() = default;
virtual ~CookieStorage() = default;
void Init();
void AddCookieToList(const nsACString& aBaseDomain,
const OriginAttributes& aOriginAttributes,
Cookie* aCookie);
virtual void StoreCookie(const nsACString& aBaseDomain,
const OriginAttributes& aOriginAttributes,
Cookie* aCookie) = 0;
virtual const char* NotificationTopic() const = 0;
virtual void NotifyChangedInternal(nsICookieNotification* aSubject,
bool aOldCookieIsSession) = 0;
virtual void RemoveAllInternal() = 0;
// This method calls RemoveCookieFromDB + RemoveCookieFromListInternal.
void RemoveCookieFromList(const CookieListIter& aIter);
void RemoveCookieFromListInternal(const CookieListIter& aIter);
virtual void RemoveCookieFromDB(const Cookie& aCookie) = 0;
already_AddRefed<nsIArray> PurgeCookiesWithCallbacks(
int64_t aCurrentTimeInUsec, uint16_t aMaxNumberOfCookies,
int64_t aCookiePurgeAge,
std::function<void(const CookieListIter&)>&& aRemoveCookieCallback,
std::function<void()>&& aFinalizeCallback);
nsTHashtable<CookieEntry> mHostTable;
uint32_t mCookieCount{0};
private:
void PrefChanged(nsIPrefBranch* aPrefBranch);
bool FindSecureCookie(const nsACString& aBaseDomain,
const OriginAttributes& aOriginAttributes,
Cookie* aCookie);
static void FindStaleCookies(CookieEntry* aEntry, int64_t aCurrentTime,
bool aIsSecure,
nsTArray<CookieListIter>& aOutput,
uint32_t aLimit);
void UpdateCookieOldestTime(Cookie* aCookie);
void MergeCookieSchemeMap(Cookie* aOldCookie, Cookie* aNewCookie);
static already_AddRefed<nsIArray> CreatePurgeList(nsICookie* aCookie);
virtual already_AddRefed<nsIArray> PurgeCookies(int64_t aCurrentTimeInUsec,
uint16_t aMaxNumberOfCookies,
int64_t aCookiePurgeAge) = 0;
// This method returns true if aBaseDomain contains any colons since only
// IPv6 baseDomains may contain colons.
static bool isIPv6BaseDomain(const nsACString& aBaseDomain);
// Serialize aBaseDomain e.g. apply "zero abbreveation" (::), use single
// zeros and remove brackets to match principal base domain representation.
static bool SerializeIPv6BaseDomain(nsACString& aBaseDomain);
virtual void CollectCookieJarSizeData() = 0;
int64_t mCookieOldestTime{INT64_MAX};
uint16_t mMaxNumberOfCookies{kMaxNumberOfCookies};
uint16_t mMaxCookiesPerHost{kMaxCookiesPerHost};
uint16_t mCookieQuotaPerHost{kCookieQuotaPerHost};
int64_t mCookiePurgeAge{kCookiePurgeAge};
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_CookieStorage_h