diff options
Diffstat (limited to '')
-rw-r--r-- | dom/xhr/XMLHttpRequestString.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/dom/xhr/XMLHttpRequestString.cpp b/dom/xhr/XMLHttpRequestString.cpp new file mode 100644 index 0000000000..8f9092243a --- /dev/null +++ b/dom/xhr/XMLHttpRequestString.cpp @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "XMLHttpRequestString.h" +#include "js/String.h" +#include "nsISupportsImpl.h" +#include "mozilla/dom/DOMString.h" + +namespace mozilla::dom { + +class XMLHttpRequestStringBuffer final { + friend class XMLHttpRequestStringSnapshot; + friend class XMLHttpRequestStringWriterHelper; + + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(XMLHttpRequestStringBuffer) + NS_DECL_OWNINGTHREAD + + XMLHttpRequestStringBuffer() : mMutex("XMLHttpRequestStringBuffer::mMutex") {} + + uint32_t Length() { + MutexAutoLock lock(mMutex); + return mData.Length(); + } + + uint32_t UnsafeLength() const MOZ_NO_THREAD_SAFETY_ANALYSIS { + return mData.Length(); + } + + mozilla::Result<mozilla::BulkWriteHandle<char16_t>, nsresult> UnsafeBulkWrite( + uint32_t aCapacity) MOZ_NO_THREAD_SAFETY_ANALYSIS { + return mData.BulkWrite(aCapacity, UnsafeLength(), false); + } + + void Append(const nsAString& aString) { + NS_ASSERT_OWNINGTHREAD(XMLHttpRequestStringBuffer); + + MutexAutoLock lock(mMutex); + mData.Append(aString); + } + + [[nodiscard]] bool GetAsString(nsAString& aString) { + MutexAutoLock lock(mMutex); + return aString.Assign(mData, mozilla::fallible); + } + + size_t SizeOfThis(MallocSizeOf aMallocSizeOf) { + MutexAutoLock lock(mMutex); + return mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf); + } + + [[nodiscard]] bool GetAsString(DOMString& aString, uint32_t aLength) { + MutexAutoLock lock(mMutex); + MOZ_ASSERT(aLength <= mData.Length()); + + // XXX: Bug 1408793 suggests encapsulating the following sequence within + // DOMString. + nsStringBuffer* buf = nsStringBuffer::FromString(mData); + if (buf) { + // We have to use SetStringBuffer, because once we release our mutex mData + // can get mutated from some other thread while the DOMString is still + // alive. + aString.SetStringBuffer(buf, aLength); + return true; + } + + // We can get here if mData is empty. In that case it won't have an + // nsStringBuffer.... + MOZ_ASSERT(mData.IsEmpty()); + return aString.AsAString().Assign(mData.BeginReading(), aLength, + mozilla::fallible); + } + + void CreateSnapshot(XMLHttpRequestStringSnapshot& aSnapshot) { + MutexAutoLock lock(mMutex); + aSnapshot.Set(this, mData.Length()); + } + + private: + ~XMLHttpRequestStringBuffer() = default; + + Mutex mMutex; + + // The following member variable is protected by mutex. + nsString mData MOZ_GUARDED_BY(mMutex); +}; + +// --------------------------------------------------------------------------- +// XMLHttpRequestString + +XMLHttpRequestString::XMLHttpRequestString() + : mBuffer(new XMLHttpRequestStringBuffer()) {} + +XMLHttpRequestString::~XMLHttpRequestString() = default; + +void XMLHttpRequestString::Truncate() { + mBuffer = new XMLHttpRequestStringBuffer(); +} + +uint32_t XMLHttpRequestString::Length() const { return mBuffer->Length(); } + +void XMLHttpRequestString::Append(const nsAString& aString) { + mBuffer->Append(aString); +} + +bool XMLHttpRequestString::GetAsString(nsAString& aString) const { + return mBuffer->GetAsString(aString); +} + +size_t XMLHttpRequestString::SizeOfThis(MallocSizeOf aMallocSizeOf) const { + return mBuffer->SizeOfThis(aMallocSizeOf); +} + +bool XMLHttpRequestString::IsEmpty() const { return !mBuffer->Length(); } + +void XMLHttpRequestString::CreateSnapshot( + XMLHttpRequestStringSnapshot& aSnapshot) { + mBuffer->CreateSnapshot(aSnapshot); +} + +// --------------------------------------------------------------------------- +// XMLHttpRequestStringSnapshot + +XMLHttpRequestStringSnapshot::XMLHttpRequestStringSnapshot() + : mLength(0), mVoid(false) {} + +XMLHttpRequestStringSnapshot::~XMLHttpRequestStringSnapshot() = default; + +void XMLHttpRequestStringSnapshot::ResetInternal(bool aIsVoid) { + mBuffer = nullptr; + mLength = 0; + mVoid = aIsVoid; +} + +void XMLHttpRequestStringSnapshot::Set(XMLHttpRequestStringBuffer* aBuffer, + uint32_t aLength) { + MOZ_ASSERT(aBuffer); + MOZ_ASSERT(aLength <= aBuffer->UnsafeLength()); + + mBuffer = aBuffer; + mLength = aLength; + mVoid = false; +} + +bool XMLHttpRequestStringSnapshot::GetAsString(DOMString& aString) const { + if (mBuffer) { + MOZ_ASSERT(!mVoid); + return mBuffer->GetAsString(aString, mLength); + } + + if (mVoid) { + aString.SetNull(); + } + + return true; +} + +JSString* XMLHttpRequestStringSnapshot::GetAsJSStringCopy( + JSContext* aCx) const { + MutexAutoLock lock(mBuffer->mMutex); + return JS_NewUCStringCopyN(aCx, mBuffer->mData.BeginReading(), + mBuffer->mData.Length()); +} + +// --------------------------------------------------------------------------- +// XMLHttpRequestStringWriterHelper + +XMLHttpRequestStringWriterHelper::XMLHttpRequestStringWriterHelper( + XMLHttpRequestString& aString) + : mBuffer(aString.mBuffer), mLock(aString.mBuffer->mMutex) {} + +XMLHttpRequestStringWriterHelper::~XMLHttpRequestStringWriterHelper() = default; + +uint32_t XMLHttpRequestStringWriterHelper::Length() const { + return mBuffer->UnsafeLength(); +} + +mozilla::Result<mozilla::BulkWriteHandle<char16_t>, nsresult> +XMLHttpRequestStringWriterHelper::BulkWrite(uint32_t aCapacity) { + return mBuffer->UnsafeBulkWrite(aCapacity); +} + +} // namespace mozilla::dom |