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