nsCookie.cpp 7.3 KB

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