XMLHttpRequestString.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /* -*- Mode: C++; tab-width: 8; 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/. */
  5. #ifndef mozilla_dom_XMLHttpRequestString_h
  6. #define mozilla_dom_XMLHttpRequestString_h
  7. #include "mozilla/Mutex.h"
  8. #include "mozilla/RefPtr.h"
  9. #include "mozilla/dom/DOMString.h"
  10. #include "nsString.h"
  11. namespace mozilla {
  12. class Mutex;
  13. namespace dom {
  14. class DOMString;
  15. class XMLHttpRequestStringBuffer;
  16. class XMLHttpRequestStringSnapshot;
  17. class XMLHttpRequestStringWriterHelper;
  18. class XMLHttpRequestStringSnapshotReaderHelper;
  19. // We want to avoid the dup of strings when XHR in workers has access to
  20. // responseText for events dispatched during the loading state. For this reason
  21. // we use this class, able to create snapshots of the current size of itself
  22. // without making extra copies.
  23. class XMLHttpRequestString final
  24. {
  25. friend class XMLHttpRequestStringWriterHelper;
  26. public:
  27. XMLHttpRequestString();
  28. ~XMLHttpRequestString();
  29. void Truncate();
  30. uint32_t Length() const;
  31. void Append(const nsAString& aString);
  32. // This method should be called only when the string is really needed because
  33. // it can cause the duplication of the strings in case the loading of the XHR
  34. // is not completed yet.
  35. MOZ_MUST_USE bool GetAsString(nsAString& aString) const;
  36. size_t SizeOfThis(MallocSizeOf aMallocSizeOf) const;
  37. const char16_t* Data() const;
  38. bool IsEmpty() const;
  39. void CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot);
  40. private:
  41. XMLHttpRequestString(const XMLHttpRequestString&) = delete;
  42. XMLHttpRequestString& operator=(const XMLHttpRequestString&) = delete;
  43. XMLHttpRequestString& operator=(const XMLHttpRequestString&&) = delete;
  44. RefPtr<XMLHttpRequestStringBuffer> mBuffer;
  45. };
  46. // This class locks the buffer and allows the callee to write data into it.
  47. class MOZ_STACK_CLASS XMLHttpRequestStringWriterHelper final
  48. {
  49. public:
  50. explicit XMLHttpRequestStringWriterHelper(XMLHttpRequestString& aString);
  51. bool
  52. AddCapacity(int32_t aCapacity);
  53. char16_t*
  54. EndOfExistingData();
  55. void
  56. AddLength(int32_t aLength);
  57. private:
  58. XMLHttpRequestStringWriterHelper(const XMLHttpRequestStringWriterHelper&) = delete;
  59. XMLHttpRequestStringWriterHelper& operator=(const XMLHttpRequestStringWriterHelper&) = delete;
  60. XMLHttpRequestStringWriterHelper& operator=(const XMLHttpRequestStringWriterHelper&&) = delete;
  61. RefPtr<XMLHttpRequestStringBuffer> mBuffer;
  62. MutexAutoLock mLock;
  63. };
  64. // This class is the internal XMLHttpRequestStringBuffer of the
  65. // XMLHttpRequestString plus the current length. GetAsString will return the
  66. // string with that particular length also if the XMLHttpRequestStringBuffer is
  67. // grown in the meantime.
  68. class XMLHttpRequestStringSnapshot final
  69. {
  70. friend class XMLHttpRequestStringBuffer;
  71. friend class XMLHttpRequestStringSnapshotReaderHelper;
  72. public:
  73. XMLHttpRequestStringSnapshot();
  74. ~XMLHttpRequestStringSnapshot();
  75. XMLHttpRequestStringSnapshot& operator=(const XMLHttpRequestStringSnapshot&);
  76. void Reset()
  77. {
  78. ResetInternal(false /* isVoid */);
  79. }
  80. void SetVoid()
  81. {
  82. ResetInternal(true /* isVoid */);
  83. }
  84. bool IsVoid() const
  85. {
  86. return mVoid;
  87. }
  88. bool IsEmpty() const
  89. {
  90. return !mLength;
  91. }
  92. MOZ_MUST_USE bool GetAsString(DOMString& aString) const;
  93. private:
  94. XMLHttpRequestStringSnapshot(const XMLHttpRequestStringSnapshot&) = delete;
  95. XMLHttpRequestStringSnapshot& operator=(const XMLHttpRequestStringSnapshot&&) = delete;
  96. void Set(XMLHttpRequestStringBuffer* aBuffer, uint32_t aLength);
  97. void ResetInternal(bool aIsVoid);
  98. RefPtr<XMLHttpRequestStringBuffer> mBuffer;
  99. uint32_t mLength;
  100. bool mVoid;
  101. };
  102. // This class locks the buffer and allows the callee to read data from it.
  103. class MOZ_STACK_CLASS XMLHttpRequestStringSnapshotReaderHelper final
  104. {
  105. public:
  106. explicit XMLHttpRequestStringSnapshotReaderHelper(XMLHttpRequestStringSnapshot& aSnapshot);
  107. const char16_t*
  108. Buffer() const;
  109. uint32_t
  110. Length() const;
  111. private:
  112. XMLHttpRequestStringSnapshotReaderHelper(const XMLHttpRequestStringSnapshotReaderHelper&) = delete;
  113. XMLHttpRequestStringSnapshotReaderHelper& operator=(const XMLHttpRequestStringSnapshotReaderHelper&) = delete;
  114. XMLHttpRequestStringSnapshotReaderHelper& operator=(const XMLHttpRequestStringSnapshotReaderHelper&&) = delete;
  115. RefPtr<XMLHttpRequestStringBuffer> mBuffer;
  116. MutexAutoLock mLock;
  117. };
  118. class XMLHttpRequestStringBuffer final
  119. {
  120. friend class XMLHttpRequestStringWriterHelper;
  121. friend class XMLHttpRequestStringSnapshotReaderHelper;
  122. public:
  123. NS_INLINE_DECL_THREADSAFE_REFCOUNTING(XMLHttpRequestStringBuffer)
  124. NS_DECL_OWNINGTHREAD
  125. XMLHttpRequestStringBuffer()
  126. : mMutex("XMLHttpRequestStringBuffer::mMutex")
  127. {
  128. }
  129. uint32_t
  130. Length()
  131. {
  132. MutexAutoLock lock(mMutex);
  133. return mData.Length();
  134. }
  135. uint32_t
  136. UnsafeLength() const
  137. {
  138. return mData.Length();
  139. }
  140. void
  141. Append(const nsAString& aString)
  142. {
  143. NS_ASSERT_OWNINGTHREAD(XMLHttpRequestStringBuffer);
  144. MutexAutoLock lock(mMutex);
  145. mData.Append(aString);
  146. }
  147. MOZ_MUST_USE bool
  148. GetAsString(nsAString& aString)
  149. {
  150. MutexAutoLock lock(mMutex);
  151. return aString.Assign(mData, mozilla::fallible);
  152. }
  153. size_t
  154. SizeOfThis(MallocSizeOf aMallocSizeOf) const
  155. {
  156. return mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
  157. }
  158. MOZ_MUST_USE bool
  159. GetAsString(DOMString& aString, uint32_t aLength)
  160. {
  161. MutexAutoLock lock(mMutex);
  162. MOZ_ASSERT(aLength <= mData.Length());
  163. nsStringBuffer* buf = nsStringBuffer::FromString(mData);
  164. if (buf) {
  165. // We have to use SetEphemeralStringBuffer, because once we release our
  166. // mutex mData can get mutated from some other thread while the DOMString
  167. // is still alive.
  168. aString.SetEphemeralStringBuffer(buf, aLength);
  169. return true;
  170. }
  171. // We can get here if mData is empty. In that case it won't have an
  172. // nsStringBuffer....
  173. MOZ_ASSERT(mData.IsEmpty());
  174. return aString.AsAString().Assign(mData.BeginReading(), aLength,
  175. mozilla::fallible);
  176. }
  177. void
  178. CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot)
  179. {
  180. MutexAutoLock lock(mMutex);
  181. aSnapshot.Set(this, mData.Length());
  182. }
  183. private:
  184. ~XMLHttpRequestStringBuffer()
  185. {}
  186. nsString& UnsafeData()
  187. {
  188. return mData;
  189. }
  190. Mutex mMutex;
  191. // The following member variable is protected by mutex.
  192. nsString mData;
  193. };
  194. } // dom namespace
  195. } // mozilla namespace
  196. #endif // mozilla_dom_XMLHttpRequestString_h