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"
11 #include "nsIURLParser.h"
12 #include "nsURLHelper.h"
15 /******************************************************************************
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
;
38 return ++gLastCreationTime
;
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() *
104 /******************************************************************************
107 ******************************************************************************/
110 NS_IMETHODIMP
nsCookie::GetName(nsACString
& aName
) {
114 NS_IMETHODIMP
nsCookie::GetValue(nsACString
& aValue
) {
118 NS_IMETHODIMP
nsCookie::GetHost(nsACString
& aHost
) {
122 NS_IMETHODIMP
nsCookie::GetRawHost(nsACString
& aHost
) {
126 NS_IMETHODIMP
nsCookie::GetPath(nsACString
& aPath
) {
130 NS_IMETHODIMP
nsCookie::GetExpiry(int64_t* aExpiry
) {
134 NS_IMETHODIMP
nsCookie::GetIsSession(bool* aIsSession
) {
135 *aIsSession
= IsSession();
138 NS_IMETHODIMP
nsCookie::GetIsDomain(bool* aIsDomain
) {
139 *aIsDomain
= IsDomain();
142 NS_IMETHODIMP
nsCookie::GetIsSecure(bool* aIsSecure
) {
143 *aIsSecure
= IsSecure();
146 NS_IMETHODIMP
nsCookie::GetIsHttpOnly(bool* aHttpOnly
) {
147 *aHttpOnly
= IsHttpOnly();
150 NS_IMETHODIMP
nsCookie::GetCreationTime(int64_t* aCreation
) {
151 *aCreation
= CreationTime();
154 NS_IMETHODIMP
nsCookie::GetLastAccessed(int64_t* aTime
) {
155 *aTime
= LastAccessed();
158 NS_IMETHODIMP
nsCookie::GetSameSite(int32_t* aSameSite
) {
159 if (mozilla::StaticPrefs::network_cookie_sameSite_laxByDefault()) {
160 *aSameSite
= SameSite();
162 *aSameSite
= RawSameSite();
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
;
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.
208 nsCookie::GetExpires(uint64_t* aExpires
) {
212 *aExpires
= Expiry() > 0 ? Expiry() : 1;
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
)