Bug 1588538 - Add missing file.
[gecko.git] / netwerk / cookie / nsCookie.cpp
blobbfbe97ee1d169c812b82bd3e14b01c997d37abe9
1 /* -*- Mode: C++; tab-width: 4; 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/. */
6 #include "mozilla/Encoding.h"
7 #include "mozilla/dom/ToJSValue.h"
8 #include "mozilla/StaticPrefs_network.h"
9 #include "nsAutoPtr.h"
10 #include "nsCookie.h"
11 #include "nsIURLParser.h"
12 #include "nsURLHelper.h"
13 #include <stdlib.h>
15 /******************************************************************************
16 * nsCookie:
17 * creation helper
18 ******************************************************************************/
20 // This is a counter that keeps track of the last used creation time, each time
21 // we create a new nsCookie. This is nominally the time (in microseconds) the
22 // cookie was created, but is guaranteed to be monotonically increasing for
23 // cookies added at runtime after the database has been read in. This is
24 // necessary to enforce ordering among cookies whose creation times would
25 // otherwise overlap, since it's possible two cookies may be created at the same
26 // time, or that the system clock isn't monotonic.
27 static int64_t gLastCreationTime;
29 int64_t nsCookie::GenerateUniqueCreationTime(int64_t aCreationTime) {
30 // Check if the creation time given to us is greater than the running maximum
31 // (it should always be monotonically increasing).
32 if (aCreationTime > gLastCreationTime) {
33 gLastCreationTime = aCreationTime;
34 return aCreationTime;
37 // Make up our own.
38 return ++gLastCreationTime;
41 // static
42 already_AddRefed<nsCookie> nsCookie::Create(
43 const nsACString& aName, const nsACString& aValue, const nsACString& aHost,
44 const nsACString& aPath, int64_t aExpiry, int64_t aLastAccessed,
45 int64_t aCreationTime, bool aIsSession, bool aIsSecure, bool aIsHttpOnly,
46 const OriginAttributes& aOriginAttributes, int32_t aSameSite,
47 int32_t aRawSameSite) {
48 mozilla::net::CookieStruct cookieData(
49 nsCString(aName), nsCString(aValue), nsCString(aHost), nsCString(aPath),
50 aExpiry, aLastAccessed, aCreationTime, aIsHttpOnly, aIsSession, aIsSecure,
51 aSameSite, aRawSameSite);
53 return Create(cookieData, aOriginAttributes);
56 already_AddRefed<nsCookie> nsCookie::Create(
57 const mozilla::net::CookieStruct& aCookieData,
58 const OriginAttributes& aOriginAttributes) {
59 RefPtr<nsCookie> cookie = new nsCookie(aCookieData, aOriginAttributes);
61 // Ensure mValue contains a valid UTF-8 sequence. Otherwise XPConnect will
62 // truncate the string after the first invalid octet.
63 UTF_8_ENCODING->DecodeWithoutBOMHandling(aCookieData.value(),
64 cookie->mData.value());
66 // If the creationTime given to us is higher than the running maximum,
67 // update our maximum.
68 if (cookie->mData.creationTime() > gLastCreationTime) {
69 gLastCreationTime = cookie->mData.creationTime();
72 // If sameSite is not a sensible value, assume strict
73 if (cookie->mData.sameSite() < 0 ||
74 cookie->mData.sameSite() > nsICookie::SAMESITE_STRICT) {
75 cookie->mData.sameSite() = nsICookie::SAMESITE_STRICT;
78 // If rawSameSite is not a sensible value, assume equal to sameSite.
79 if (!nsCookie::ValidateRawSame(cookie->mData)) {
80 cookie->mData.rawSameSite() = nsICookie::SAMESITE_NONE;
83 return cookie.forget();
86 size_t nsCookie::SizeOfIncludingThis(
87 mozilla::MallocSizeOf aMallocSizeOf) const {
88 return aMallocSizeOf(this) +
89 mData.name().SizeOfExcludingThisIfUnshared(MallocSizeOf) +
90 mData.value().SizeOfExcludingThisIfUnshared(MallocSizeOf) +
91 mData.host().SizeOfExcludingThisIfUnshared(MallocSizeOf) +
92 mData.path().SizeOfExcludingThisIfUnshared(MallocSizeOf) +
93 mFilePathCache.SizeOfExcludingThisIfUnshared(MallocSizeOf);
96 bool nsCookie::IsStale() const {
97 int64_t currentTimeInUsec = PR_Now();
99 return currentTimeInUsec - LastAccessed() >
100 mozilla::StaticPrefs::network_cookie_staleThreshold() *
101 PR_USEC_PER_SEC;
104 /******************************************************************************
105 * nsCookie:
106 * xpcom impl
107 ******************************************************************************/
109 // xpcom getters
110 NS_IMETHODIMP nsCookie::GetName(nsACString& aName) {
111 aName = Name();
112 return NS_OK;
114 NS_IMETHODIMP nsCookie::GetValue(nsACString& aValue) {
115 aValue = Value();
116 return NS_OK;
118 NS_IMETHODIMP nsCookie::GetHost(nsACString& aHost) {
119 aHost = Host();
120 return NS_OK;
122 NS_IMETHODIMP nsCookie::GetRawHost(nsACString& aHost) {
123 aHost = RawHost();
124 return NS_OK;
126 NS_IMETHODIMP nsCookie::GetPath(nsACString& aPath) {
127 aPath = Path();
128 return NS_OK;
130 NS_IMETHODIMP nsCookie::GetExpiry(int64_t* aExpiry) {
131 *aExpiry = Expiry();
132 return NS_OK;
134 NS_IMETHODIMP nsCookie::GetIsSession(bool* aIsSession) {
135 *aIsSession = IsSession();
136 return NS_OK;
138 NS_IMETHODIMP nsCookie::GetIsDomain(bool* aIsDomain) {
139 *aIsDomain = IsDomain();
140 return NS_OK;
142 NS_IMETHODIMP nsCookie::GetIsSecure(bool* aIsSecure) {
143 *aIsSecure = IsSecure();
144 return NS_OK;
146 NS_IMETHODIMP nsCookie::GetIsHttpOnly(bool* aHttpOnly) {
147 *aHttpOnly = IsHttpOnly();
148 return NS_OK;
150 NS_IMETHODIMP nsCookie::GetCreationTime(int64_t* aCreation) {
151 *aCreation = CreationTime();
152 return NS_OK;
154 NS_IMETHODIMP nsCookie::GetLastAccessed(int64_t* aTime) {
155 *aTime = LastAccessed();
156 return NS_OK;
158 NS_IMETHODIMP nsCookie::GetSameSite(int32_t* aSameSite) {
159 if (mozilla::StaticPrefs::network_cookie_sameSite_laxByDefault()) {
160 *aSameSite = SameSite();
161 } else {
162 *aSameSite = RawSameSite();
164 return NS_OK;
167 NS_IMETHODIMP
168 nsCookie::GetOriginAttributes(JSContext* aCx,
169 JS::MutableHandle<JS::Value> aVal) {
170 if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
171 return NS_ERROR_FAILURE;
173 return NS_OK;
176 const nsCString& nsCookie::GetFilePath() {
177 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
179 if (Path().IsEmpty()) {
180 // If we don't have a path, just return the (empty) file path cache.
181 return mFilePathCache;
183 if (!mFilePathCache.IsEmpty()) {
184 // If we've computed the answer before, just return it.
185 return mFilePathCache;
188 nsIURLParser* parser = net_GetStdURLParser();
189 NS_ENSURE_TRUE(parser, mFilePathCache);
191 int32_t pathLen = Path().Length(), filepathLen = 0;
192 uint32_t filepathPos = 0;
194 nsresult rv = parser->ParsePath(PromiseFlatCString(Path()).get(), pathLen,
195 &filepathPos, &filepathLen, nullptr,
196 nullptr, // don't care about query
197 nullptr, nullptr); // don't care about ref
198 NS_ENSURE_SUCCESS(rv, mFilePathCache);
200 mFilePathCache = Substring(Path(), filepathPos, filepathLen);
202 return mFilePathCache;
205 // compatibility method, for use with the legacy nsICookie interface.
206 // here, expires == 0 denotes a session cookie.
207 NS_IMETHODIMP
208 nsCookie::GetExpires(uint64_t* aExpires) {
209 if (IsSession()) {
210 *aExpires = 0;
211 } else {
212 *aExpires = Expiry() > 0 ? Expiry() : 1;
214 return NS_OK;
217 // static
218 bool nsCookie::ValidateRawSame(const mozilla::net::CookieStruct& aCookieData) {
219 return aCookieData.rawSameSite() == aCookieData.sameSite() ||
220 aCookieData.rawSameSite() == nsICookie::SAMESITE_NONE;
223 NS_IMPL_ISUPPORTS(nsCookie, nsICookie)