tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

XMLHttpRequestString.cpp (5558B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "XMLHttpRequestString.h"
      8 
      9 #include "js/String.h"
     10 #include "mozilla/dom/DOMString.h"
     11 #include "nsISupportsImpl.h"
     12 
     13 namespace mozilla::dom {
     14 
     15 class XMLHttpRequestStringBuffer final {
     16  friend class XMLHttpRequestStringSnapshot;
     17  friend class XMLHttpRequestStringWriterHelper;
     18 
     19 public:
     20  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(XMLHttpRequestStringBuffer)
     21  NS_DECL_OWNINGTHREAD
     22 
     23  XMLHttpRequestStringBuffer() : mMutex("XMLHttpRequestStringBuffer::mMutex") {}
     24 
     25  uint32_t Length() {
     26    MutexAutoLock lock(mMutex);
     27    return mData.Length();
     28  }
     29 
     30  uint32_t UnsafeLength() const MOZ_NO_THREAD_SAFETY_ANALYSIS {
     31    return mData.Length();
     32  }
     33 
     34  mozilla::Result<mozilla::BulkWriteHandle<char16_t>, nsresult> UnsafeBulkWrite(
     35      uint32_t aCapacity) MOZ_NO_THREAD_SAFETY_ANALYSIS {
     36    return mData.BulkWrite(aCapacity, UnsafeLength(), false);
     37  }
     38 
     39  void Append(const nsAString& aString) {
     40    NS_ASSERT_OWNINGTHREAD(XMLHttpRequestStringBuffer);
     41 
     42    MutexAutoLock lock(mMutex);
     43    mData.Append(aString);
     44  }
     45 
     46  [[nodiscard]] bool GetAsString(nsAString& aString) {
     47    MutexAutoLock lock(mMutex);
     48    return aString.Assign(mData, mozilla::fallible);
     49  }
     50 
     51  size_t SizeOfThis(MallocSizeOf aMallocSizeOf) {
     52    MutexAutoLock lock(mMutex);
     53    return mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
     54  }
     55 
     56  [[nodiscard]] bool GetAsString(DOMString& aString, uint32_t aLength) {
     57    MutexAutoLock lock(mMutex);
     58    MOZ_ASSERT(aLength <= mData.Length());
     59 
     60    // XXX: Bug 1408793 suggests encapsulating the following sequence within
     61    //      DOMString.
     62    if (StringBuffer* buf = mData.GetStringBuffer()) {
     63      // We have to use SetStringBuffer, because once we release our mutex mData
     64      // can get mutated from some other thread while the DOMString is still
     65      // alive.
     66      aString.SetStringBuffer(buf, aLength);
     67      return true;
     68    }
     69 
     70    // We can get here if mData is empty.  In that case it won't have an
     71    // nsStringBuffer....
     72    MOZ_ASSERT(mData.IsEmpty());
     73    return aString.AsAString().Assign(mData.BeginReading(), aLength,
     74                                      mozilla::fallible);
     75  }
     76 
     77  void CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot) {
     78    MutexAutoLock lock(mMutex);
     79    aSnapshot.Set(this, mData.Length());
     80  }
     81 
     82 private:
     83  ~XMLHttpRequestStringBuffer() = default;
     84 
     85  Mutex mMutex;
     86 
     87  // The following member variable is protected by mutex.
     88  nsString mData MOZ_GUARDED_BY(mMutex);
     89 };
     90 
     91 // ---------------------------------------------------------------------------
     92 // XMLHttpRequestString
     93 
     94 XMLHttpRequestString::XMLHttpRequestString()
     95    : mBuffer(new XMLHttpRequestStringBuffer()) {}
     96 
     97 XMLHttpRequestString::~XMLHttpRequestString() = default;
     98 
     99 void XMLHttpRequestString::Truncate() {
    100  mBuffer = new XMLHttpRequestStringBuffer();
    101 }
    102 
    103 uint32_t XMLHttpRequestString::Length() const { return mBuffer->Length(); }
    104 
    105 void XMLHttpRequestString::Append(const nsAString& aString) {
    106  mBuffer->Append(aString);
    107 }
    108 
    109 bool XMLHttpRequestString::GetAsString(nsAString& aString) const {
    110  return mBuffer->GetAsString(aString);
    111 }
    112 
    113 size_t XMLHttpRequestString::SizeOfThis(MallocSizeOf aMallocSizeOf) const {
    114  return mBuffer->SizeOfThis(aMallocSizeOf);
    115 }
    116 
    117 bool XMLHttpRequestString::IsEmpty() const { return !mBuffer->Length(); }
    118 
    119 void XMLHttpRequestString::CreateSnapshot(
    120    XMLHttpRequestStringSnapshot& aSnapshot) {
    121  mBuffer->CreateSnapshot(aSnapshot);
    122 }
    123 
    124 // ---------------------------------------------------------------------------
    125 // XMLHttpRequestStringSnapshot
    126 
    127 XMLHttpRequestStringSnapshot::XMLHttpRequestStringSnapshot()
    128    : mLength(0), mVoid(false) {}
    129 
    130 XMLHttpRequestStringSnapshot::~XMLHttpRequestStringSnapshot() = default;
    131 
    132 void XMLHttpRequestStringSnapshot::ResetInternal(bool aIsVoid) {
    133  mBuffer = nullptr;
    134  mLength = 0;
    135  mVoid = aIsVoid;
    136 }
    137 
    138 void XMLHttpRequestStringSnapshot::Set(XMLHttpRequestStringBuffer* aBuffer,
    139                                       uint32_t aLength) {
    140  MOZ_ASSERT(aBuffer);
    141  MOZ_ASSERT(aLength <= aBuffer->UnsafeLength());
    142 
    143  mBuffer = aBuffer;
    144  mLength = aLength;
    145  mVoid = false;
    146 }
    147 
    148 bool XMLHttpRequestStringSnapshot::GetAsString(DOMString& aString) const {
    149  if (mBuffer) {
    150    MOZ_ASSERT(!mVoid);
    151    return mBuffer->GetAsString(aString, mLength);
    152  }
    153 
    154  if (mVoid) {
    155    aString.SetNull();
    156  }
    157 
    158  return true;
    159 }
    160 
    161 JSString* XMLHttpRequestStringSnapshot::GetAsJSStringCopy(
    162    JSContext* aCx) const {
    163  MutexAutoLock lock(mBuffer->mMutex);
    164  return JS_NewUCStringCopyN(aCx, mBuffer->mData.BeginReading(),
    165                             mBuffer->mData.Length());
    166 }
    167 
    168 // ---------------------------------------------------------------------------
    169 // XMLHttpRequestStringWriterHelper
    170 
    171 XMLHttpRequestStringWriterHelper::XMLHttpRequestStringWriterHelper(
    172    XMLHttpRequestString& aString)
    173    : mBuffer(aString.mBuffer), mLock(aString.mBuffer->mMutex) {}
    174 
    175 XMLHttpRequestStringWriterHelper::~XMLHttpRequestStringWriterHelper() = default;
    176 
    177 uint32_t XMLHttpRequestStringWriterHelper::Length() const {
    178  return mBuffer->UnsafeLength();
    179 }
    180 
    181 mozilla::Result<mozilla::BulkWriteHandle<char16_t>, nsresult>
    182 XMLHttpRequestStringWriterHelper::BulkWrite(uint32_t aCapacity) {
    183  return mBuffer->UnsafeBulkWrite(aCapacity);
    184 }
    185 
    186 }  // namespace mozilla::dom