/src/mozilla-central/netwerk/cookie/nsCookie.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
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 | | #include "mozilla/Encoding.h" |
7 | | #include "mozilla/dom/ToJSValue.h" |
8 | | #include "nsAutoPtr.h" |
9 | | #include "nsCookie.h" |
10 | | #include <stdlib.h> |
11 | | |
12 | | /****************************************************************************** |
13 | | * nsCookie: |
14 | | * string helper impl |
15 | | ******************************************************************************/ |
16 | | |
17 | | // copy aSource strings into contiguous storage provided in aDest1, |
18 | | // providing terminating nulls for each destination string. |
19 | | static inline void |
20 | | StrBlockCopy(const nsACString &aSource1, |
21 | | const nsACString &aSource2, |
22 | | const nsACString &aSource3, |
23 | | const nsACString &aSource4, |
24 | | char *&aDest1, |
25 | | char *&aDest2, |
26 | | char *&aDest3, |
27 | | char *&aDest4, |
28 | | char *&aDestEnd) |
29 | 0 | { |
30 | 0 | size_t len1 = aSource1.Length(); |
31 | 0 | memcpy(aDest1, aSource1.BeginReading(), len1); |
32 | 0 | aDest1[len1] = 0; |
33 | 0 |
|
34 | 0 | aDest2 = aDest1 + len1 + 1; |
35 | 0 |
|
36 | 0 | size_t len2 = aSource2.Length(); |
37 | 0 | memcpy(aDest2, aSource2.BeginReading(), len2); |
38 | 0 | aDest2[len2] = 0; |
39 | 0 |
|
40 | 0 | aDest3 = aDest2 + len2 + 1; |
41 | 0 |
|
42 | 0 | size_t len3 = aSource3.Length(); |
43 | 0 | memcpy(aDest3, aSource3.BeginReading(), len3); |
44 | 0 | aDest3[len3] = 0; |
45 | 0 |
|
46 | 0 | aDest4 = aDest3 + len3 + 1; |
47 | 0 |
|
48 | 0 | size_t len4 = aSource4.Length(); |
49 | 0 | memcpy(aDest4, aSource4.BeginReading(), len4); |
50 | 0 | aDest4[len4] = 0; |
51 | 0 |
|
52 | 0 | // Intentionally no + 1 here! |
53 | 0 | aDestEnd = aDest4 + len4; |
54 | 0 | } |
55 | | |
56 | | /****************************************************************************** |
57 | | * nsCookie: |
58 | | * creation helper |
59 | | ******************************************************************************/ |
60 | | |
61 | | // This is a counter that keeps track of the last used creation time, each time |
62 | | // we create a new nsCookie. This is nominally the time (in microseconds) the |
63 | | // cookie was created, but is guaranteed to be monotonically increasing for |
64 | | // cookies added at runtime after the database has been read in. This is |
65 | | // necessary to enforce ordering among cookies whose creation times would |
66 | | // otherwise overlap, since it's possible two cookies may be created at the same |
67 | | // time, or that the system clock isn't monotonic. |
68 | | static int64_t gLastCreationTime; |
69 | | |
70 | | int64_t |
71 | | nsCookie::GenerateUniqueCreationTime(int64_t aCreationTime) |
72 | 0 | { |
73 | 0 | // Check if the creation time given to us is greater than the running maximum |
74 | 0 | // (it should always be monotonically increasing). |
75 | 0 | if (aCreationTime > gLastCreationTime) { |
76 | 0 | gLastCreationTime = aCreationTime; |
77 | 0 | return aCreationTime; |
78 | 0 | } |
79 | 0 | |
80 | 0 | // Make up our own. |
81 | 0 | return ++gLastCreationTime; |
82 | 0 | } |
83 | | |
84 | | nsCookie * |
85 | | nsCookie::Create(const nsACString &aName, |
86 | | const nsACString &aValue, |
87 | | const nsACString &aHost, |
88 | | const nsACString &aPath, |
89 | | int64_t aExpiry, |
90 | | int64_t aLastAccessed, |
91 | | int64_t aCreationTime, |
92 | | bool aIsSession, |
93 | | bool aIsSecure, |
94 | | bool aIsHttpOnly, |
95 | | const OriginAttributes& aOriginAttributes, |
96 | | int32_t aSameSite) |
97 | 0 | { |
98 | 0 | // Ensure mValue contains a valid UTF-8 sequence. Otherwise XPConnect will |
99 | 0 | // truncate the string after the first invalid octet. |
100 | 0 | nsAutoCString aUTF8Value; |
101 | 0 | UTF_8_ENCODING->DecodeWithoutBOMHandling(aValue, aUTF8Value); |
102 | 0 |
|
103 | 0 | // find the required string buffer size, adding 4 for the terminating nulls |
104 | 0 | const uint32_t stringLength = aName.Length() + aUTF8Value.Length() + |
105 | 0 | aHost.Length() + aPath.Length() + 4; |
106 | 0 |
|
107 | 0 | // allocate contiguous space for the nsCookie and its strings - |
108 | 0 | // we store the strings in-line with the nsCookie to save allocations |
109 | 0 | void *place = ::operator new(sizeof(nsCookie) + stringLength); |
110 | 0 | if (!place) |
111 | 0 | return nullptr; |
112 | 0 | |
113 | 0 | // assign string members |
114 | 0 | char *name, *value, *host, *path, *end; |
115 | 0 | name = static_cast<char *>(place) + sizeof(nsCookie); |
116 | 0 | StrBlockCopy(aName, aUTF8Value, aHost, aPath, |
117 | 0 | name, value, host, path, end); |
118 | 0 |
|
119 | 0 | // If the creationTime given to us is higher than the running maximum, update |
120 | 0 | // our maximum. |
121 | 0 | if (aCreationTime > gLastCreationTime) |
122 | 0 | gLastCreationTime = aCreationTime; |
123 | 0 |
|
124 | 0 | // If aSameSite is not a sensible value, assume strict |
125 | 0 | if (aSameSite < 0 || aSameSite > nsICookie2::SAMESITE_STRICT) { |
126 | 0 | aSameSite = nsICookie2::SAMESITE_STRICT; |
127 | 0 | } |
128 | 0 |
|
129 | 0 | // construct the cookie. placement new, oh yeah! |
130 | 0 | return new (place) nsCookie(name, value, host, path, end, |
131 | 0 | aExpiry, aLastAccessed, aCreationTime, |
132 | 0 | aIsSession, aIsSecure, aIsHttpOnly, |
133 | 0 | aOriginAttributes, aSameSite); |
134 | 0 | } |
135 | | |
136 | | size_t |
137 | | nsCookie::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const |
138 | 0 | { |
139 | 0 | // There is no need to measure the sizes of the individual string |
140 | 0 | // members, since the strings are stored in-line with the nsCookie. |
141 | 0 | return aMallocSizeOf(this); |
142 | 0 | } |
143 | | |
144 | | bool |
145 | | nsCookie::IsStale() const |
146 | 0 | { |
147 | 0 | int64_t currentTimeInUsec = PR_Now(); |
148 | 0 |
|
149 | 0 | return currentTimeInUsec - LastAccessed() > CookieStaleThreshold() * PR_USEC_PER_SEC; |
150 | 0 | } |
151 | | |
152 | | /****************************************************************************** |
153 | | * nsCookie: |
154 | | * xpcom impl |
155 | | ******************************************************************************/ |
156 | | |
157 | | // xpcom getters |
158 | 0 | NS_IMETHODIMP nsCookie::GetName(nsACString &aName) { aName = Name(); return NS_OK; } |
159 | 0 | NS_IMETHODIMP nsCookie::GetValue(nsACString &aValue) { aValue = Value(); return NS_OK; } |
160 | 0 | NS_IMETHODIMP nsCookie::GetHost(nsACString &aHost) { aHost = Host(); return NS_OK; } |
161 | 0 | NS_IMETHODIMP nsCookie::GetRawHost(nsACString &aHost) { aHost = RawHost(); return NS_OK; } |
162 | 0 | NS_IMETHODIMP nsCookie::GetPath(nsACString &aPath) { aPath = Path(); return NS_OK; } |
163 | 0 | NS_IMETHODIMP nsCookie::GetExpiry(int64_t *aExpiry) { *aExpiry = Expiry(); return NS_OK; } |
164 | 0 | NS_IMETHODIMP nsCookie::GetIsSession(bool *aIsSession) { *aIsSession = IsSession(); return NS_OK; } |
165 | 0 | NS_IMETHODIMP nsCookie::GetIsDomain(bool *aIsDomain) { *aIsDomain = IsDomain(); return NS_OK; } |
166 | 0 | NS_IMETHODIMP nsCookie::GetIsSecure(bool *aIsSecure) { *aIsSecure = IsSecure(); return NS_OK; } |
167 | 0 | NS_IMETHODIMP nsCookie::GetIsHttpOnly(bool *aHttpOnly) { *aHttpOnly = IsHttpOnly(); return NS_OK; } |
168 | 0 | NS_IMETHODIMP nsCookie::GetCreationTime(int64_t *aCreation){ *aCreation = CreationTime(); return NS_OK; } |
169 | 0 | NS_IMETHODIMP nsCookie::GetLastAccessed(int64_t *aTime) { *aTime = LastAccessed(); return NS_OK; } |
170 | 0 | NS_IMETHODIMP nsCookie::GetSameSite(int32_t *aSameSite) { *aSameSite = SameSite(); return NS_OK; } |
171 | | |
172 | | NS_IMETHODIMP |
173 | | nsCookie::GetOriginAttributes(JSContext *aCx, JS::MutableHandle<JS::Value> aVal) |
174 | 0 | { |
175 | 0 | if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) { |
176 | 0 | return NS_ERROR_FAILURE; |
177 | 0 | } |
178 | 0 | return NS_OK; |
179 | 0 | } |
180 | | |
181 | | // compatibility method, for use with the legacy nsICookie interface. |
182 | | // here, expires == 0 denotes a session cookie. |
183 | | NS_IMETHODIMP |
184 | | nsCookie::GetExpires(uint64_t *aExpires) |
185 | 0 | { |
186 | 0 | if (IsSession()) { |
187 | 0 | *aExpires = 0; |
188 | 0 | } else { |
189 | 0 | *aExpires = Expiry() > 0 ? Expiry() : 1; |
190 | 0 | } |
191 | 0 | return NS_OK; |
192 | 0 | } |
193 | | |
194 | | NS_IMPL_ISUPPORTS(nsCookie, nsICookie2, nsICookie) |