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