1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef mozilla_net_CookieStorage_h
7 #define mozilla_net_CookieStorage_h
8 
9 #include "CookieKey.h"
10 
11 #include "nsIObserver.h"
12 #include "nsTHashtable.h"
13 #include "nsWeakReference.h"
14 #include <functional>
15 
16 class nsIArray;
17 class nsICookie;
18 class nsIPrefBranch;
19 
20 namespace mozilla {
21 namespace net {
22 
23 class Cookie;
24 
25 // Inherit from CookieKey so this can be stored in nsTHashTable
26 // TODO: why aren't we using nsClassHashTable<CookieKey, ArrayType>?
27 class CookieEntry : public CookieKey {
28  public:
29   // Hash methods
30   typedef nsTArray<RefPtr<Cookie>> ArrayType;
31   typedef ArrayType::index_type IndexType;
32 
CookieEntry(KeyTypePointer aKey)33   explicit CookieEntry(KeyTypePointer aKey) : CookieKey(aKey) {}
34 
CookieEntry(const CookieEntry & toCopy)35   CookieEntry(const CookieEntry& toCopy) {
36     // if we end up here, things will break. nsTHashtable shouldn't
37     // allow this, since we set ALLOW_MEMMOVE to true.
38     MOZ_ASSERT_UNREACHABLE("CookieEntry copy constructor is forbidden!");
39   }
40 
41   ~CookieEntry() = default;
42 
GetCookies()43   inline ArrayType& GetCookies() { return mCookies; }
44 
45   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
46 
47  private:
48   ArrayType mCookies;
49 };
50 
51 // stores the CookieEntry entryclass and an index into the cookie array within
52 // that entryclass, for purposes of storing an iteration state that points to a
53 // certain cookie.
54 struct CookieListIter {
55   // default (non-initializing) constructor.
56   CookieListIter() = default;
57 
58   // explicit constructor to a given iterator state with entryclass 'aEntry'
59   // and index 'aIndex'.
CookieListIterCookieListIter60   explicit CookieListIter(CookieEntry* aEntry, CookieEntry::IndexType aIndex)
61       : entry(aEntry), index(aIndex) {}
62 
63   // get the Cookie * the iterator currently points to.
CookieCookieListIter64   mozilla::net::Cookie* Cookie() const { return entry->GetCookies()[index]; }
65 
66   CookieEntry* entry;
67   CookieEntry::IndexType index;
68 };
69 
70 class CookieStorage : public nsIObserver, public nsSupportsWeakReference {
71  public:
72   NS_DECL_THREADSAFE_ISUPPORTS
73   NS_DECL_NSIOBSERVER
74 
75   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
76 
77   void GetCookies(nsTArray<RefPtr<nsICookie>>& aCookies) const;
78 
79   void GetSessionCookies(nsTArray<RefPtr<nsICookie>>& aCookies) const;
80 
81   bool FindCookie(const nsACString& aBaseDomain,
82                   const OriginAttributes& aOriginAttributes,
83                   const nsACString& aHost, const nsACString& aName,
84                   const nsACString& aPath, CookieListIter& aIter);
85 
86   uint32_t CountCookiesFromHost(const nsACString& aBaseDomain,
87                                 uint32_t aPrivateBrowsingId);
88 
89   void GetAll(nsTArray<RefPtr<nsICookie>>& aResult) const;
90 
91   const nsTArray<RefPtr<Cookie>>* GetCookiesFromHost(
92       const nsACString& aBaseDomain, const OriginAttributes& aOriginAttributes);
93 
94   void GetCookiesWithOriginAttributes(const OriginAttributesPattern& aPattern,
95                                       const nsACString& aBaseDomain,
96                                       nsTArray<RefPtr<nsICookie>>& aResult);
97 
98   void RemoveCookie(const nsACString& aBaseDomain,
99                     const OriginAttributes& aOriginAttributes,
100                     const nsACString& aHost, const nsACString& aName,
101                     const nsACString& aPath);
102 
103   virtual void RemoveCookiesWithOriginAttributes(
104       const OriginAttributesPattern& aPattern, const nsACString& aBaseDomain);
105 
106   virtual void RemoveCookiesFromExactHost(
107       const nsACString& aHost, const nsACString& aBaseDomain,
108       const OriginAttributesPattern& aPattern);
109 
110   void RemoveAll();
111 
112   void NotifyChanged(nsISupports* aSubject, const char16_t* aData,
113                      bool aOldCookieIsSession = false);
114 
115   void AddCookie(const nsACString& aBaseDomain,
116                  const OriginAttributes& aOriginAttributes, Cookie* aCookie,
117                  int64_t aCurrentTimeInUsec, nsIURI* aHostURI,
118                  const nsACString& aCookieHeader, bool aFromHttp);
119 
120   static void CreateOrUpdatePurgeList(nsIArray** aPurgedList,
121                                       nsICookie* aCookie);
122 
123   virtual void StaleCookies(const nsTArray<Cookie*>& aCookieList,
124                             int64_t aCurrentTimeInUsec) = 0;
125 
126   virtual void Close() = 0;
127 
128  protected:
129   CookieStorage();
130   virtual ~CookieStorage();
131 
132   void Init();
133 
134   void AddCookieToList(const nsACString& aBaseDomain,
135                        const OriginAttributes& aOriginAttributes,
136                        Cookie* aCookie);
137 
138   virtual void StoreCookie(const nsACString& aBaseDomain,
139                            const OriginAttributes& aOriginAttributes,
140                            Cookie* aCookie) = 0;
141 
142   virtual const char* NotificationTopic() const = 0;
143 
144   virtual void NotifyChangedInternal(nsISupports* aSubject,
145                                      const char16_t* aData,
146                                      bool aOldCookieIsSession) = 0;
147 
148   virtual void RemoveAllInternal() = 0;
149 
150   // This method calls RemoveCookieFromDB + RemoveCookieFromListInternal.
151   void RemoveCookieFromList(const CookieListIter& aIter);
152 
153   void RemoveCookieFromListInternal(const CookieListIter& aIter);
154 
155   virtual void RemoveCookieFromDB(const CookieListIter& aIter) = 0;
156 
157   already_AddRefed<nsIArray> PurgeCookiesWithCallbacks(
158       int64_t aCurrentTimeInUsec, uint16_t aMaxNumberOfCookies,
159       int64_t aCookiePurgeAge,
160       std::function<void(const CookieListIter&)>&& aRemoveCookieCallback,
161       std::function<void()>&& aFinalizeCallback);
162 
163   nsTHashtable<CookieEntry> mHostTable;
164 
165   uint32_t mCookieCount;
166 
167  private:
168   void PrefChanged(nsIPrefBranch* aPrefBranch);
169 
170   bool FindSecureCookie(const nsACString& aBaseDomain,
171                         const OriginAttributes& aOriginAttributes,
172                         Cookie* aCookie);
173 
174   static void FindStaleCookies(CookieEntry* aEntry, int64_t aCurrentTime,
175                                bool aIsSecure,
176                                nsTArray<CookieListIter>& aOutput,
177                                uint32_t aLimit);
178 
179   void UpdateCookieOldestTime(Cookie* aCookie);
180 
181   static already_AddRefed<nsIArray> CreatePurgeList(nsICookie* aCookie);
182 
183   virtual already_AddRefed<nsIArray> PurgeCookies(int64_t aCurrentTimeInUsec,
184                                                   uint16_t aMaxNumberOfCookies,
185                                                   int64_t aCookiePurgeAge) = 0;
186 
187   int64_t mCookieOldestTime;
188 
189   uint16_t mMaxNumberOfCookies;
190   uint16_t mMaxCookiesPerHost;
191   uint16_t mCookieQuotaPerHost;
192   int64_t mCookiePurgeAge;
193 };
194 
195 }  // namespace net
196 }  // namespace mozilla
197 
198 #endif  // mozilla_net_CookieStorage_h
199