Bug 1518774, r=dragana a=lizzard
authorHonza Bambas <honzab.moz@firemni.cz>
Wed, 27 Feb 2019 23:00:02 +0100
changeset 516185 6bacdb768e5af3f69cc3977ff70219ffaebac0cf
parent 516184 571ad2687c2ea8b846d9468e493fae909eb35e78
child 516186 eccb1f5d6a0720aebc8f00172d72cf5254b3f2e5
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdragana, lizzard
bugs1518774
milestone66.0
Bug 1518774, r=dragana a=lizzard
dom/canvas/test/mochitest.ini
xpcom/io/nsStringStream.cpp
--- a/dom/canvas/test/mochitest.ini
+++ b/dom/canvas/test/mochitest.ini
@@ -293,8 +293,9 @@ skip-if = 1
 subsuite = gpu
 tags = offscreencanvas
 skip-if = 1
 [test_offscreencanvas_subworker.html]
 subsuite = gpu
 tags = offscreencanvas
 skip-if = 1
 [test_invalid_mime_type_blob.html]
+skip-if = toolkit == 'android'
--- a/xpcom/io/nsStringStream.cpp
+++ b/xpcom/io/nsStringStream.cpp
@@ -17,16 +17,17 @@
 #include "nsISeekableStream.h"
 #include "nsISupportsPrimitives.h"
 #include "nsCRT.h"
 #include "prerror.h"
 #include "plstr.h"
 #include "nsIClassInfoImpl.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/InputStreamUtils.h"
+#include "mozilla/ReentrantMonitor.h"
 #include "nsIIPCSerializableInputStream.h"
 
 using namespace mozilla::ipc;
 using mozilla::Maybe;
 using mozilla::Some;
 
 //-----------------------------------------------------------------------------
 // nsIStringInputStream implementation
@@ -43,36 +44,40 @@ class nsStringInputStream final : public
   NS_DECL_NSISTRINGINPUTSTREAM
   NS_DECL_NSISEEKABLESTREAM
   NS_DECL_NSITELLABLESTREAM
   NS_DECL_NSISUPPORTSPRIMITIVE
   NS_DECL_NSISUPPORTSCSTRING
   NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
   NS_DECL_NSICLONEABLEINPUTSTREAM
 
-  nsStringInputStream() : mOffset(0) { Clear(); }
+  nsStringInputStream() : mOffset(0), mMon("nsStringInputStream") { Clear(); }
 
   nsresult Init(nsCString&& aString);
 
  private:
   ~nsStringInputStream() {}
 
   uint32_t Length() const { return mData.Length(); }
 
   uint32_t LengthRemaining() const { return Length() - mOffset; }
 
   void Clear() { mData.SetIsVoid(true); }
 
   bool Closed() { return mData.IsVoid(); }
 
   nsDependentCSubstring mData;
   uint32_t mOffset;
+
+  mozilla::ReentrantMonitor mMon;
 };
 
 nsresult nsStringInputStream::Init(nsCString&& aString) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   if (!mData.Assign(std::move(aString), fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   mOffset = 0;
   return NS_OK;
 }
 
@@ -100,29 +105,33 @@ NS_IMPL_CI_INTERFACE_GETTER(nsStringInpu
 NS_IMETHODIMP
 nsStringInputStream::GetType(uint16_t* aType) {
   *aType = TYPE_CSTRING;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringInputStream::GetData(nsACString& data) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   // The stream doesn't have any data when it is closed.  We could fake it
   // and return an empty string here, but it seems better to keep this return
   // value consistent with the behavior of the other 'getter' methods.
   if (NS_WARN_IF(Closed())) {
     return NS_BASE_STREAM_CLOSED;
   }
 
   data.Assign(mData);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringInputStream::SetData(const nsACString& aData) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   if (NS_WARN_IF(!mData.Assign(aData, fallible))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   mOffset = 0;
   return NS_OK;
 }
 
@@ -133,72 +142,84 @@ nsStringInputStream::ToString(char** aRe
 }
 
 /////////
 // nsIStringInputStream implementation
 /////////
 
 NS_IMETHODIMP
 nsStringInputStream::SetData(const char* aData, int32_t aDataLen) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   if (NS_WARN_IF(!aData)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (NS_WARN_IF(!mData.Assign(aData, aDataLen, fallible))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   mOffset = 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringInputStream::AdoptData(char* aData, int32_t aDataLen) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   if (NS_WARN_IF(!aData)) {
     return NS_ERROR_INVALID_ARG;
   }
   mData.Adopt(aData, aDataLen);
   mOffset = 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringInputStream::ShareData(const char* aData, int32_t aDataLen) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   if (NS_WARN_IF(!aData)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (aDataLen < 0) {
     aDataLen = strlen(aData);
   }
 
   mData.Rebind(aData, aDataLen);
   mOffset = 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP_(size_t)
 nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   size_t n = aMallocSizeOf(this);
   n += mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
   return n;
 }
 
 /////////
 // nsIInputStream implementation
 /////////
 
 NS_IMETHODIMP
 nsStringInputStream::Close() {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   Clear();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringInputStream::Available(uint64_t* aLength) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   NS_ASSERTION(aLength, "null ptr");
 
   if (Closed()) {
     return NS_BASE_STREAM_CLOSED;
   }
 
   *aLength = LengthRemaining();
   return NS_OK;
@@ -208,16 +229,18 @@ NS_IMETHODIMP
 nsStringInputStream::Read(char* aBuf, uint32_t aCount, uint32_t* aReadCount) {
   NS_ASSERTION(aBuf, "null ptr");
   return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aReadCount);
 }
 
 NS_IMETHODIMP
 nsStringInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
                                   uint32_t aCount, uint32_t* aResult) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   NS_ASSERTION(aResult, "null ptr");
   NS_ASSERTION(Length() >= mOffset, "bad stream state");
 
   if (Closed()) {
     return NS_BASE_STREAM_CLOSED;
   }
 
   // We may be at end-of-file
@@ -249,16 +272,18 @@ nsStringInputStream::IsNonBlocking(bool*
 }
 
 /////////
 // nsISeekableStream implementation
 /////////
 
 NS_IMETHODIMP
 nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   if (Closed()) {
     return NS_BASE_STREAM_CLOSED;
   }
 
   // Compute new stream position.  The given offset may be a negative value.
 
   int64_t newPos = aOffset;
   switch (aWhence) {
@@ -280,44 +305,50 @@ nsStringInputStream::Seek(int32_t aWhenc
   }
 
   mOffset = (uint32_t)newPos;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringInputStream::SetEOF() {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   if (Closed()) {
     return NS_BASE_STREAM_CLOSED;
   }
 
   mOffset = Length();
   return NS_OK;
 }
 
 /////////
 // nsITellableStream implementation
 /////////
 
 NS_IMETHODIMP
 nsStringInputStream::Tell(int64_t* aOutWhere) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   if (Closed()) {
     return NS_BASE_STREAM_CLOSED;
   }
 
   *aOutWhere = mOffset;
   return NS_OK;
 }
 
 /////////
 // nsIIPCSerializableInputStream implementation
 /////////
 
 void nsStringInputStream::Serialize(InputStreamParams& aParams,
                                     FileDescriptorArray& /* aFDs */) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   StringInputStreamParams params;
   params.data() = PromiseFlatCString(mData);
   aParams = params;
 }
 
 bool nsStringInputStream::Deserialize(const InputStreamParams& aParams,
                                       const FileDescriptorArray& /* aFDs */) {
   if (aParams.type() != InputStreamParams::TStringInputStreamParams) {
@@ -331,31 +362,35 @@ bool nsStringInputStream::Deserialize(co
     NS_WARNING("SetData failed!");
     return false;
   }
 
   return true;
 }
 
 Maybe<uint64_t> nsStringInputStream::ExpectedSerializedLength() {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   return Some(static_cast<uint64_t>(Length()));
 }
 
 /////////
 // nsICloneableInputStream implementation
 /////////
 
 NS_IMETHODIMP
 nsStringInputStream::GetCloneable(bool* aCloneableOut) {
   *aCloneableOut = true;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStringInputStream::Clone(nsIInputStream** aCloneOut) {
+  ReentrantMonitorAutoEnter lock(mMon);
+
   RefPtr<nsStringInputStream> ref = new nsStringInputStream();
   nsresult rv = ref->SetData(mData);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // mOffset is overwritten by SetData().
   ref->mOffset = mOffset;