From b6187e2b2ea12e040152239b37a9933f901c106f Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:33 +0200 Subject: [PATCH 01/10] Backed out changeset 96d1b7238832 (bug 1308317) --- xpcom/ds/nsSupportsArray.cpp | 245 +++++++++++++++++++++++++++-------- xpcom/ds/nsSupportsArray.h | 28 ++-- 2 files changed, 209 insertions(+), 64 deletions(-) diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp index 9dad104225f9..2a94f3e5bcbe 100644 --- a/xpcom/ds/nsSupportsArray.cpp +++ b/xpcom/ds/nsSupportsArray.cpp @@ -6,11 +6,12 @@ #include #include - -#include "nsIObjectInputStream.h" -#include "nsIObjectOutputStream.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/MathAlgorithms.h" #include "nsSupportsArray.h" #include "nsSupportsArrayEnumerator.h" +#include "nsIObjectInputStream.h" +#include "nsIObjectOutputStream.h" nsresult nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const @@ -28,11 +29,69 @@ nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const nsSupportsArray::nsSupportsArray() { + mArray = mAutoArray; + mArraySize = kAutoArraySize; + mCount = 0; } nsSupportsArray::~nsSupportsArray() { - Clear(); + DeleteArray(); +} + +bool +nsSupportsArray::GrowArrayBy(uint32_t aGrowBy) +{ + const uint32_t kGrowArrayBy = 8; + const uint32_t kLinearThreshold = 16 * sizeof(nsISupports*); + + // We have to grow the array. Grow by kGrowArrayBy slots if we're smaller + // than kLinearThreshold bytes, or a power of two if we're larger. + // This is much more efficient with most memory allocators, especially + // if it's very large, or of the allocator is binned. + if (aGrowBy < kGrowArrayBy) { + aGrowBy = kGrowArrayBy; + } + + CheckedUint32 newCount(mArraySize); + newCount += aGrowBy; // Minimum increase + CheckedUint32 newSize(sizeof(mArray[0])); + newSize *= newCount; + + if (!newSize.isValid()) { + return false; + } + + if (newSize.value() >= kLinearThreshold) { + // newCount includes enough space for at least kGrowArrayBy new slots. + // Select the next power-of-two size in bytes above that if newSize is + // not a power of two. + if (newSize.value() & (newSize.value() - 1)) { + newSize = UINT64_C(1) << mozilla::CeilingLog2(newSize.value()); + if (!newSize.isValid()) { + return false; + } + } + + newCount = newSize / sizeof(mArray[0]); + } + // XXX This would be far more efficient in many allocators if we used + // XXX PR_Realloc(), etc + nsISupports** oldArray = mArray; + + mArray = new nsISupports*[newCount.value()]; + mArraySize = newCount.value(); + + if (oldArray) { // need to move old data + if (0 < mCount) { + ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); + } + if (oldArray != &(mAutoArray[0])) { + delete[] oldArray; + } + } + + return true; } nsresult @@ -53,8 +112,6 @@ NS_IMPL_ISUPPORTS(nsSupportsArray, nsISupportsArray, nsICollection, NS_IMETHODIMP nsSupportsArray::Read(nsIObjectInputStream* aStream) { - // TODO(ER): This used to leak when resizing the array. Not sure if that was - // intentional, I'm guessing not. nsresult rv; uint32_t newArraySize; @@ -63,40 +120,43 @@ nsSupportsArray::Read(nsIObjectInputStream* aStream) return rv; } - uint32_t count; - rv = aStream->Read32(&count); + if (newArraySize <= kAutoArraySize) { + if (mArray != mAutoArray) { + delete[] mArray; + mArray = mAutoArray; + } + newArraySize = kAutoArraySize; + } else { + if (newArraySize <= mArraySize) { + // Keep non-default-size mArray, it's more than big enough. + newArraySize = mArraySize; + } else { + nsISupports** array = new nsISupports*[newArraySize]; + if (mArray != mAutoArray) { + delete[] mArray; + } + mArray = array; + } + } + mArraySize = newArraySize; + + rv = aStream->Read32(&mCount); if (NS_FAILED(rv)) { return rv; } - NS_ASSERTION(count <= newArraySize, "overlarge mCount!"); - if (count > newArraySize) { - count = newArraySize; + NS_ASSERTION(mCount <= mArraySize, "overlarge mCount!"); + if (mCount > mArraySize) { + mCount = mArraySize; } - // Don't clear out our array until we know we have enough space for the new - // one and have successfully copied everything out of the stream. - ISupportsArray tmp; - if (!tmp.SetCapacity(newArraySize, mozilla::fallible)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - auto elems = tmp.AppendElements(count, mozilla::fallible); - for (uint32_t i = 0; i < count; i++) { - rv = aStream->ReadObject(true, &elems[i]); + for (uint32_t i = 0; i < mCount; i++) { + rv = aStream->ReadObject(true, &mArray[i]); if (NS_FAILED(rv)) { return rv; } } - // Now clear out existing refs and replace with the new array. - for (auto& item : mArray) { - NS_IF_RELEASE(item); - } - - mArray.Clear(); - mArray.SwapElements(tmp); - return NS_OK; } @@ -105,18 +165,18 @@ nsSupportsArray::Write(nsIObjectOutputStream* aStream) { nsresult rv; - rv = aStream->Write32(mArray.Capacity()); + rv = aStream->Write32(mArraySize); if (NS_FAILED(rv)) { return rv; } - rv = aStream->Write32(mArray.Length()); + rv = aStream->Write32(mCount); if (NS_FAILED(rv)) { return rv; } - for (auto& item : mArray) { - rv = aStream->WriteObject(item, true); + for (uint32_t i = 0; i < mCount; i++) { + rv = aStream->WriteObject(mArray[i], true); if (NS_FAILED(rv)) { return rv; } @@ -125,42 +185,95 @@ nsSupportsArray::Write(nsIObjectOutputStream* aStream) return NS_OK; } +void +nsSupportsArray::DeleteArray(void) +{ + Clear(); + if (mArray != &(mAutoArray[0])) { + delete[] mArray; + mArray = mAutoArray; + mArraySize = kAutoArraySize; + } +} + NS_IMETHODIMP nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports** aOutPtr) { - NS_IF_ADDREF(*aOutPtr = mArray.SafeElementAt(aIndex, nullptr)); + *aOutPtr = nullptr; + if (aIndex < mCount) { + NS_IF_ADDREF(*aOutPtr = mArray[aIndex]); + } return NS_OK; } NS_IMETHODIMP_(int32_t) nsSupportsArray::IndexOf(const nsISupports* aPossibleElement) { - return mArray.IndexOf(aPossibleElement); + const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior + const nsISupports** ep = start; + const nsISupports** end = (start + mCount); + while (ep < end) { + if (aPossibleElement == *ep) { + return (ep - start); + } + ep++; + } + return -1; } NS_IMETHODIMP_(int32_t) nsSupportsArray::LastIndexOf(const nsISupports* aPossibleElement) { - return mArray.LastIndexOf(aPossibleElement); + if (0 < mCount) { + const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior + const nsISupports** ep = (start + mCount); + while (start <= --ep) { + if (aPossibleElement == *ep) { + return (ep - start); + } + } + } + return -1; } NS_IMETHODIMP_(bool) nsSupportsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex) { + if (aIndex <= mCount) { + CheckedUint32 newCount(mCount); + newCount += 1; + if (!newCount.isValid()) { + return false; + } - if (aIndex > mArray.Length() || - !mArray.InsertElementAt(aIndex, aElement, mozilla::fallible)) { - return false; + if (mArraySize < newCount.value()) { + // need to grow the array + if (!GrowArrayBy(1)) { + return false; + } + } + + // Could be slightly more efficient if GrowArrayBy knew about the + // split, but the difference is trivial. + uint32_t slide = (mCount - aIndex); + if (0 < slide) { + ::memmove(mArray + aIndex + 1, mArray + aIndex, + slide * sizeof(nsISupports*)); + } + + mArray[aIndex] = aElement; + NS_IF_ADDREF(aElement); + mCount++; + + return true; } - - NS_IF_ADDREF(aElement); - return true; + return false; } NS_IMETHODIMP_(bool) nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) { - if (aIndex < mArray.Length()) { + if (aIndex < mCount) { NS_IF_ADDREF(aElement); // addref first in case it's the same object! NS_IF_RELEASE(mArray[aIndex]); mArray[aIndex] = aElement; @@ -172,9 +285,15 @@ nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) NS_IMETHODIMP_(bool) nsSupportsArray::RemoveElementAt(uint32_t aIndex) { - if (aIndex + 1 <= mArray.Length()) { + if (aIndex + 1 <= mCount) { NS_IF_RELEASE(mArray[aIndex]); - mArray.RemoveElementAt(aIndex); + + mCount -= 1; + int32_t slide = (mCount - aIndex); + if (0 < slide) { + ::memmove(mArray + aIndex, mArray + aIndex + 1, + slide * sizeof(nsISupports*)); + } return true; } return false; @@ -194,19 +313,35 @@ nsSupportsArray::RemoveElement(nsISupports* aElement) NS_IMETHODIMP nsSupportsArray::Clear(void) { - for (auto& item : mArray) { - NS_IF_RELEASE(item); + if (0 < mCount) { + do { + --mCount; + NS_IF_RELEASE(mArray[mCount]); + } while (0 != mCount); } - - mArray.Clear(); - return NS_OK; } NS_IMETHODIMP nsSupportsArray::Compact(void) { - mArray.Compact(); + if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) { + nsISupports** oldArray = mArray; + if (mCount <= kAutoArraySize) { + mArray = mAutoArray; + mArraySize = kAutoArraySize; + } else { + mArray = new nsISupports*[mCount]; + if (!mArray) { + mArray = oldArray; + return NS_OK; + } + mArraySize = mCount; + } + + ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); + delete[] oldArray; + } return NS_OK; } @@ -228,10 +363,10 @@ nsSupportsArray::Clone(nsISupportsArray** aResult) return rv; } - for (auto& item : mArray) { - // AppendElement does an odd cast of bool to nsresult, we just cast back - // here. - if (!(bool)newArray->AppendElement(item)) { + uint32_t count = 0; + Count(&count); + for (uint32_t i = 0; i < count; i++) { + if (!newArray->InsertElementAt(mArray[i], i)) { return NS_ERROR_OUT_OF_MEMORY; } } diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h index af625f8f64c3..e927a63689eb 100644 --- a/xpcom/ds/nsSupportsArray.h +++ b/xpcom/ds/nsSupportsArray.h @@ -8,9 +8,10 @@ #define nsSupportsArray_h__ #include "nsISupportsArray.h" -#include "nsTArray.h" #include "mozilla/Attributes.h" +static const uint32_t kAutoArraySize = 8; + class nsSupportsArray final : public nsISupportsArray { ~nsSupportsArray(void); // nonvirtual since we're not subclassed @@ -28,16 +29,18 @@ public: // nsICollection methods: NS_IMETHOD Count(uint32_t* aResult) override { - *aResult = mArray.Length(); + *aResult = mCount; return NS_OK; } NS_IMETHOD GetElementAt(uint32_t aIndex, nsISupports** aResult) override; MOZ_MUST_USE NS_IMETHOD QueryElementAt(uint32_t aIndex, const nsIID& aIID, void** aResult) override { - nsISupports* element = mArray.SafeElementAt(aIndex, nullptr); - if (element) { - return element->QueryInterface(aIID, aResult); + if (aIndex < mCount) { + nsISupports* element = mArray[aIndex]; + if (element) { + return element->QueryInterface(aIID, aResult); + } } return NS_ERROR_FAILURE; } @@ -49,7 +52,7 @@ public: MOZ_MUST_USE NS_IMETHOD AppendElement(nsISupports* aElement) override { // XXX Invalid cast of bool to nsresult (bug 778110) - return (nsresult)InsertElementAt(aElement, mArray.Length())/* ? NS_OK : NS_ERROR_FAILURE*/; + return (nsresult)InsertElementAt(aElement, mCount)/* ? NS_OK : NS_ERROR_FAILURE*/; } // XXX this is badly named - should be RemoveFirstElement MOZ_MUST_USE NS_IMETHOD RemoveElement(nsISupports* aElement) override; @@ -90,12 +93,19 @@ public: MOZ_MUST_USE NS_IMETHOD Clone(nsISupportsArray** aResult) override; +protected: + void DeleteArray(void); + + bool GrowArrayBy(uint32_t aGrowBy); + + nsISupports** mArray; + uint32_t mArraySize; + uint32_t mCount; + nsISupports* mAutoArray[kAutoArraySize]; + private: // Copy constructors are not allowed explicit nsSupportsArray(const nsISupportsArray& aOther); - - typedef AutoTArray ISupportsArray; - ISupportsArray mArray; }; #endif // nsSupportsArray_h__ From 3470d6dfe024650ff9932e92c780e228bf26eb9c Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:35 +0200 Subject: [PATCH 02/10] Backed out changeset 928ad5e93372 (bug 1308317) --- xpcom/ds/nsISupportsArray.idl | 3 +++ xpcom/ds/nsSupportsArray.cpp | 13 +++++++------ xpcom/ds/nsSupportsArray.h | 8 +++++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/xpcom/ds/nsISupportsArray.idl b/xpcom/ds/nsISupportsArray.idl index cdf7fbc3fb56..1a92cf2c1fa7 100644 --- a/xpcom/ds/nsISupportsArray.idl +++ b/xpcom/ds/nsISupportsArray.idl @@ -54,6 +54,9 @@ interface nsISupportsArray : nsICollection { nsISupportsArray clone(); + + [notxpcom] boolean RemoveElementsAt(in unsigned long aIndex, + in unsigned long aCount); }; %{C++ diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp index 2a94f3e5bcbe..a37bcc2364bd 100644 --- a/xpcom/ds/nsSupportsArray.cpp +++ b/xpcom/ds/nsSupportsArray.cpp @@ -283,15 +283,16 @@ nsSupportsArray::ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) } NS_IMETHODIMP_(bool) -nsSupportsArray::RemoveElementAt(uint32_t aIndex) +nsSupportsArray::RemoveElementsAt(uint32_t aIndex, uint32_t aCount) { - if (aIndex + 1 <= mCount) { - NS_IF_RELEASE(mArray[aIndex]); - - mCount -= 1; + if (aIndex + aCount <= mCount) { + for (uint32_t i = 0; i < aCount; i++) { + NS_IF_RELEASE(mArray[aIndex + i]); + } + mCount -= aCount; int32_t slide = (mCount - aIndex); if (0 < slide) { - ::memmove(mArray + aIndex, mArray + aIndex + 1, + ::memmove(mArray + aIndex, mArray + aIndex + aCount, slide * sizeof(nsISupports*)); } return true; diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h index e927a63689eb..86f806de9d1a 100644 --- a/xpcom/ds/nsSupportsArray.h +++ b/xpcom/ds/nsSupportsArray.h @@ -82,7 +82,10 @@ public: ReplaceElementAt(nsISupports* aElement, uint32_t aIndex) override; MOZ_MUST_USE NS_IMETHOD_(bool) - RemoveElementAt(uint32_t aIndex) override; + RemoveElementAt(uint32_t aIndex) override + { + return RemoveElementsAt(aIndex, 1); + } MOZ_MUST_USE NS_IMETHOD DeleteElementAt(uint32_t aIndex) override { @@ -93,6 +96,9 @@ public: MOZ_MUST_USE NS_IMETHOD Clone(nsISupportsArray** aResult) override; + MOZ_MUST_USE NS_IMETHOD_(bool) + RemoveElementsAt(uint32_t aIndex, uint32_t aCount) override; + protected: void DeleteArray(void); From b79e4e00ccf4249934a6d7b8be9c77e9a655826e Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:38 +0200 Subject: [PATCH 03/10] Backed out changeset 8c2984643f74 (bug 1308317) --- xpcom/ds/nsISupportsArray.idl | 4 ++++ xpcom/ds/nsSupportsArray.cpp | 25 +++++++++++++++++-------- xpcom/ds/nsSupportsArray.h | 9 +++++++++ xpcom/glue/tests/gtest/TestArray.cpp | 15 +++++++++++---- 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/xpcom/ds/nsISupportsArray.idl b/xpcom/ds/nsISupportsArray.idl index 1a92cf2c1fa7..b09eac2f1c68 100644 --- a/xpcom/ds/nsISupportsArray.idl +++ b/xpcom/ds/nsISupportsArray.idl @@ -34,10 +34,14 @@ class nsISupportsArray; interface nsISupportsArray : nsICollection { [notxpcom] long IndexOf([const] in nsISupports aPossibleElement); + [notxpcom] long IndexOfStartingAt([const] in nsISupports aPossibleElement, + in unsigned long aStartIndex); [notxpcom] long LastIndexOf([const] in nsISupports aPossibleElement); // xpcom-compatible versions long GetIndexOf(in nsISupports aPossibleElement); + long GetIndexOfStartingAt(in nsISupports aPossibleElement, + in unsigned long aStartIndex); long GetLastIndexOf(in nsISupports aPossibleElement); [notxpcom] boolean InsertElementAt(in nsISupports aElement, diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp index a37bcc2364bd..8236fb560ed0 100644 --- a/xpcom/ds/nsSupportsArray.cpp +++ b/xpcom/ds/nsSupportsArray.cpp @@ -209,14 +209,23 @@ nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports** aOutPtr) NS_IMETHODIMP_(int32_t) nsSupportsArray::IndexOf(const nsISupports* aPossibleElement) { - const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior - const nsISupports** ep = start; - const nsISupports** end = (start + mCount); - while (ep < end) { - if (aPossibleElement == *ep) { - return (ep - start); + return IndexOfStartingAt(aPossibleElement, 0); +} + +NS_IMETHODIMP_(int32_t) +nsSupportsArray::IndexOfStartingAt(const nsISupports* aPossibleElement, + uint32_t aStartIndex) +{ + if (aStartIndex < mCount) { + const nsISupports** start = (const nsISupports**)mArray; // work around goofy compiler behavior + const nsISupports** ep = (start + aStartIndex); + const nsISupports** end = (start + mCount); + while (ep < end) { + if (aPossibleElement == *ep) { + return (ep - start); + } + ep++; } - ep++; } return -1; } @@ -303,7 +312,7 @@ nsSupportsArray::RemoveElementsAt(uint32_t aIndex, uint32_t aCount) NS_IMETHODIMP nsSupportsArray::RemoveElement(nsISupports* aElement) { - int32_t theIndex = IndexOf(aElement); + int32_t theIndex = IndexOfStartingAt(aElement, 0); if (theIndex >= 0) { return RemoveElementAt(theIndex) ? NS_OK : NS_ERROR_FAILURE; } diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h index 86f806de9d1a..237375d0bc86 100644 --- a/xpcom/ds/nsSupportsArray.h +++ b/xpcom/ds/nsSupportsArray.h @@ -61,6 +61,8 @@ public: // nsISupportsArray methods: NS_IMETHOD_(int32_t) IndexOf(const nsISupports* aPossibleElement) override; + NS_IMETHOD_(int32_t) IndexOfStartingAt(const nsISupports* aPossibleElement, + uint32_t aStartIndex = 0) override; NS_IMETHOD_(int32_t) LastIndexOf(const nsISupports* aPossibleElement) override; NS_IMETHOD GetIndexOf(nsISupports* aPossibleElement, int32_t* aResult) override @@ -69,6 +71,13 @@ public: return NS_OK; } + NS_IMETHOD GetIndexOfStartingAt(nsISupports* aPossibleElement, + uint32_t aStartIndex, int32_t* aResult) override + { + *aResult = IndexOfStartingAt(aPossibleElement, aStartIndex); + return NS_OK; + } + NS_IMETHOD GetLastIndexOf(nsISupports* aPossibleElement, int32_t* aResult) override { *aResult = LastIndexOf(aPossibleElement); diff --git a/xpcom/glue/tests/gtest/TestArray.cpp b/xpcom/glue/tests/gtest/TestArray.cpp index 5a07bbfc05d2..1e3654107562 100644 --- a/xpcom/glue/tests/gtest/TestArray.cpp +++ b/xpcom/glue/tests/gtest/TestArray.cpp @@ -119,12 +119,19 @@ TEST(Array, main) // test IndexOf && LastIndexOf - int32_t expectedIndex = 0; + int32_t expectedIndex[5] = {0, 4, 6, 12, -1}; + int32_t count = 0; int32_t index = array->IndexOf(foo); - EXPECT_EQ(index, expectedIndex); - expectedIndex = 12; + EXPECT_EQ(index, expectedIndex[count]); + while (-1 != index) { + count++; + index = array->IndexOfStartingAt(foo, index + 1); + if (-1 != index) + EXPECT_EQ(index, expectedIndex[count]); + } index = array->LastIndexOf(foo); - EXPECT_EQ(index, expectedIndex); + count--; + EXPECT_EQ(index, expectedIndex[count]); // test ReplaceElementAt array->ReplaceElementAt(foo, 8); From ac6a59854262f8a18232e1cbdbda24a4b53ccc91 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:40 +0200 Subject: [PATCH 04/10] Backed out changeset 476a831ca87e (bug 1308317) --- xpcom/ds/nsISupportsArray.idl | 2 ++ xpcom/ds/nsSupportsArray.cpp | 12 ++++++++++++ xpcom/ds/nsSupportsArray.h | 7 +++++++ xpcom/glue/tests/gtest/TestArray.cpp | 5 ++++- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/xpcom/ds/nsISupportsArray.idl b/xpcom/ds/nsISupportsArray.idl index b09eac2f1c68..96c1f906da25 100644 --- a/xpcom/ds/nsISupportsArray.idl +++ b/xpcom/ds/nsISupportsArray.idl @@ -50,8 +50,10 @@ interface nsISupportsArray : nsICollection { in unsigned long aIndex); [notxpcom] boolean RemoveElementAt(in unsigned long aIndex); + [notxpcom] boolean RemoveLastElement([const] in nsISupports aElement); // xpcom-compatible versions + void DeleteLastElement(in nsISupports aElement); void DeleteElementAt(in unsigned long aIndex); void Compact(); diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp index 8236fb560ed0..f404055780a4 100644 --- a/xpcom/ds/nsSupportsArray.cpp +++ b/xpcom/ds/nsSupportsArray.cpp @@ -320,6 +320,18 @@ nsSupportsArray::RemoveElement(nsISupports* aElement) return NS_ERROR_FAILURE; } +NS_IMETHODIMP_(bool) +nsSupportsArray::RemoveLastElement(const nsISupports* aElement) +{ + int32_t theIndex = LastIndexOf(aElement); + if (theIndex >= 0) { + return RemoveElementAt(theIndex); + } + + return false; +} + + NS_IMETHODIMP nsSupportsArray::Clear(void) { diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h index 237375d0bc86..a0e528f5e71b 100644 --- a/xpcom/ds/nsSupportsArray.h +++ b/xpcom/ds/nsSupportsArray.h @@ -95,6 +95,13 @@ public: { return RemoveElementsAt(aIndex, 1); } + MOZ_MUST_USE NS_IMETHOD_(bool) + RemoveLastElement(const nsISupports* aElement) override; + + MOZ_MUST_USE NS_IMETHOD DeleteLastElement(nsISupports* aElement) override + { + return (RemoveLastElement(aElement) ? NS_OK : NS_ERROR_FAILURE); + } MOZ_MUST_USE NS_IMETHOD DeleteElementAt(uint32_t aIndex) override { diff --git a/xpcom/glue/tests/gtest/TestArray.cpp b/xpcom/glue/tests/gtest/TestArray.cpp index 1e3654107562..f55da2c7d3e6 100644 --- a/xpcom/glue/tests/gtest/TestArray.cpp +++ b/xpcom/glue/tests/gtest/TestArray.cpp @@ -138,7 +138,7 @@ TEST(Array, main) int32_t replaceResult[13] = {3, 0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3}; CheckArray(array, 13, replaceResult, 9); - // test RemoveElementAt, RemoveElement + // test RemoveElementAt, RemoveElement RemoveLastElement array->RemoveElementAt(0); int32_t removeResult[12] = {0, 1, 2, 3, 4, 3, 5, 3, 7, 8, 9, 3}; CheckArray(array, 12, removeResult, 9); @@ -148,6 +148,9 @@ TEST(Array, main) array->RemoveElement(foo); int32_t removeResult3[10] = {0, 1, 2, 4, 3, 5, 7, 8, 9, 3}; CheckArray(array, 10, removeResult3, 9); + array->RemoveLastElement(foo); + int32_t removeResult4[9] = {0, 1, 2, 4, 3, 5, 7, 8, 9}; + CheckArray(array, 9, removeResult4, 9); foo = nullptr; From 8f39dfed93ff4a3242644004efe778169dc17030 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:42 +0200 Subject: [PATCH 05/10] Backed out changeset bb30697071b2 (bug 1308317) --- xpcom/ds/nsISupportsArray.idl | 2 ++ xpcom/ds/nsSupportsArray.cpp | 29 +++++++++++++++++++++++++++++ xpcom/ds/nsSupportsArray.h | 2 ++ 3 files changed, 33 insertions(+) diff --git a/xpcom/ds/nsISupportsArray.idl b/xpcom/ds/nsISupportsArray.idl index 96c1f906da25..8ff4393e9699 100644 --- a/xpcom/ds/nsISupportsArray.idl +++ b/xpcom/ds/nsISupportsArray.idl @@ -33,6 +33,8 @@ class nsISupportsArray; [scriptable, uuid(241addc8-3608-4e73-8083-2fd6fa09eba2)] interface nsISupportsArray : nsICollection { + [notxpcom] boolean Equals([const] in nsISupportsArray other); + [notxpcom] long IndexOf([const] in nsISupports aPossibleElement); [notxpcom] long IndexOfStartingAt([const] in nsISupports aPossibleElement, in unsigned long aStartIndex); diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp index f404055780a4..ad7c85335845 100644 --- a/xpcom/ds/nsSupportsArray.cpp +++ b/xpcom/ds/nsSupportsArray.cpp @@ -196,6 +196,35 @@ nsSupportsArray::DeleteArray(void) } } + +NS_IMETHODIMP_(bool) +nsSupportsArray::Equals(const nsISupportsArray* aOther) +{ + if (aOther) { + uint32_t countOther; + nsISupportsArray* other = const_cast(aOther); + nsresult rv = other->Count(&countOther); + if (NS_FAILED(rv)) { + return false; + } + + if (mCount == countOther) { + uint32_t index = mCount; + nsCOMPtr otherElem; + while (index--) { + if (NS_FAILED(other->GetElementAt(index, getter_AddRefs(otherElem)))) { + return false; + } + if (mArray[index] != otherElem) { + return false; + } + } + return true; + } + } + return false; +} + NS_IMETHODIMP nsSupportsArray::GetElementAt(uint32_t aIndex, nsISupports** aOutPtr) { diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h index a0e528f5e71b..bf230f97db4b 100644 --- a/xpcom/ds/nsSupportsArray.h +++ b/xpcom/ds/nsSupportsArray.h @@ -60,6 +60,8 @@ public: NS_IMETHOD Clear(void) override; // nsISupportsArray methods: + NS_IMETHOD_(bool) Equals(const nsISupportsArray* aOther) override; + NS_IMETHOD_(int32_t) IndexOf(const nsISupports* aPossibleElement) override; NS_IMETHOD_(int32_t) IndexOfStartingAt(const nsISupports* aPossibleElement, uint32_t aStartIndex = 0) override; From 638c43c71b1a52148f8e1ba9683664b8d334c387 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:44 +0200 Subject: [PATCH 06/10] Backed out changeset 8d8a0f01f28c (bug 1308317) --- xpcom/ds/nsISupportsArray.idl | 3 +++ xpcom/ds/nsSupportsArray.cpp | 32 ++++++++++++++++++++++++++++++++ xpcom/ds/nsSupportsArray.h | 2 ++ 3 files changed, 37 insertions(+) diff --git a/xpcom/ds/nsISupportsArray.idl b/xpcom/ds/nsISupportsArray.idl index 8ff4393e9699..f04d3443ba38 100644 --- a/xpcom/ds/nsISupportsArray.idl +++ b/xpcom/ds/nsISupportsArray.idl @@ -65,6 +65,9 @@ interface nsISupportsArray : nsICollection { [notxpcom] boolean RemoveElementsAt(in unsigned long aIndex, in unsigned long aCount); + + [notxpcom] boolean SizeTo(in long aSize); + }; %{C++ diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp index ad7c85335845..c45e79b5e895 100644 --- a/xpcom/ds/nsSupportsArray.cpp +++ b/xpcom/ds/nsSupportsArray.cpp @@ -396,6 +396,38 @@ nsSupportsArray::Compact(void) return NS_OK; } +NS_IMETHODIMP_(bool) +nsSupportsArray::SizeTo(int32_t aSize) +{ + NS_ASSERTION(aSize >= 0, "negative aSize!"); + + // XXX for aSize < mCount we could resize to mCount + if (mArraySize == (uint32_t)aSize || (uint32_t)aSize < mCount) { + return true; // nothing to do + } + + // switch back to autoarray if possible + nsISupports** oldArray = mArray; + if ((uint32_t)aSize <= kAutoArraySize) { + mArray = mAutoArray; + mArraySize = kAutoArraySize; + } else { + mArray = new nsISupports*[aSize]; + if (!mArray) { + mArray = oldArray; + return false; + } + mArraySize = aSize; + } + + ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); + if (oldArray != mAutoArray) { + delete[] oldArray; + } + + return true; +} + NS_IMETHODIMP nsSupportsArray::Enumerate(nsIEnumerator** aResult) { diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h index bf230f97db4b..ac6cc8df2665 100644 --- a/xpcom/ds/nsSupportsArray.h +++ b/xpcom/ds/nsSupportsArray.h @@ -117,6 +117,8 @@ public: MOZ_MUST_USE NS_IMETHOD_(bool) RemoveElementsAt(uint32_t aIndex, uint32_t aCount) override; + MOZ_MUST_USE NS_IMETHOD_(bool) + SizeTo(int32_t aSize) override; protected: void DeleteArray(void); From 46b2fe93c0e7a0816d77b1014fbc7cc374f1162c Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:46 +0200 Subject: [PATCH 07/10] Backed out changeset 63208c26bfc3 (bug 1308317) --- xpcom/ds/nsISupportsArray.idl | 3 +++ xpcom/ds/nsSupportsArray.cpp | 30 ++++++++++++++++++++++++++++++ xpcom/ds/nsSupportsArray.h | 1 + 3 files changed, 34 insertions(+) diff --git a/xpcom/ds/nsISupportsArray.idl b/xpcom/ds/nsISupportsArray.idl index f04d3443ba38..2cc90186100f 100644 --- a/xpcom/ds/nsISupportsArray.idl +++ b/xpcom/ds/nsISupportsArray.idl @@ -63,6 +63,9 @@ interface nsISupportsArray : nsICollection { nsISupportsArray clone(); + [notxpcom] boolean MoveElement(in long aFrom, + in long aTo); + [notxpcom] boolean RemoveElementsAt(in unsigned long aIndex, in unsigned long aCount); diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp index c45e79b5e895..f767e5594af1 100644 --- a/xpcom/ds/nsSupportsArray.cpp +++ b/xpcom/ds/nsSupportsArray.cpp @@ -360,6 +360,36 @@ nsSupportsArray::RemoveLastElement(const nsISupports* aElement) return false; } +NS_IMETHODIMP_(bool) +nsSupportsArray::MoveElement(int32_t aFrom, int32_t aTo) +{ + nsISupports* tempElement; + + if (aTo == aFrom) { + return true; + } + + if (aTo < 0 || aFrom < 0 || + (uint32_t)aTo >= mCount || (uint32_t)aFrom >= mCount) { + // can't extend the array when moving an element. Also catches mImpl = null + return false; + } + tempElement = mArray[aFrom]; + + if (aTo < aFrom) { + // Moving one element closer to the head; the elements inbetween move down + ::memmove(mArray + aTo + 1, mArray + aTo, + (aFrom - aTo) * sizeof(mArray[0])); + mArray[aTo] = tempElement; + } else { // already handled aFrom == aTo + // Moving one element closer to the tail; the elements inbetween move up + ::memmove(mArray + aFrom, mArray + aFrom + 1, + (aTo - aFrom) * sizeof(mArray[0])); + mArray[aTo] = tempElement; + } + + return true; +} NS_IMETHODIMP nsSupportsArray::Clear(void) diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h index ac6cc8df2665..5e5d48e0c5b9 100644 --- a/xpcom/ds/nsSupportsArray.h +++ b/xpcom/ds/nsSupportsArray.h @@ -56,6 +56,7 @@ public: } // XXX this is badly named - should be RemoveFirstElement MOZ_MUST_USE NS_IMETHOD RemoveElement(nsISupports* aElement) override; + MOZ_MUST_USE NS_IMETHOD_(bool) MoveElement(int32_t aFrom, int32_t aTo) override; NS_IMETHOD Enumerate(nsIEnumerator** aResult) override; NS_IMETHOD Clear(void) override; From 98c8a7a746d1b0474ffa9874b8c97435138c6838 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:49 +0200 Subject: [PATCH 08/10] Backed out changeset ea82808b9abd (bug 1308317) --- xpcom/ds/nsSupportsArray.cpp | 120 ++++++++++++++++++++++++++++++++++- xpcom/ds/nsSupportsArray.h | 6 ++ 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/xpcom/ds/nsSupportsArray.cpp b/xpcom/ds/nsSupportsArray.cpp index f767e5594af1..4e6a7d772489 100644 --- a/xpcom/ds/nsSupportsArray.cpp +++ b/xpcom/ds/nsSupportsArray.cpp @@ -13,6 +13,73 @@ #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" +#if DEBUG_SUPPORTSARRAY +#define MAXSUPPORTS 20 + +class SupportsStats +{ +public: + SupportsStats(); + ~SupportsStats(); + +}; + +static int sizesUsed; // number of the elements of the arrays used +static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations. sorted +static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array) +static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used) +static int GrowInPlace[MAXSUPPORTS]; + +// these are per-allocation +static int MaxElements[3000]; + +// very evil +#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \ + { \ + if (sizesAlloced[i] == (int)(size)) \ + { ((x)[i])++; break; } \ + } \ + if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \ + { sizesAlloced[sizesUsed] = (size); \ + ((x)[sizesUsed++])++; break; \ + } \ + } while (0); + +#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \ + { \ + if (sizesAlloced[i] == (int)(size)) \ + { ((x)[i])--; break; } \ + } \ + } while (0); + + +SupportsStats::SupportsStats() +{ + sizesUsed = 1; + sizesAlloced[0] = 0; +} + +SupportsStats::~SupportsStats() +{ + int i; + for (i = 0; i < sizesUsed; ++i) { + printf("Size %d:\n", sizesAlloced[i]); + printf("\tNumber of SupportsArrays this size (max): %d\n", NumberOfSize[i]); + printf("\tNumber of allocations this size (total): %d\n", AllocedOfSize[i]); + printf("\tNumber of GrowsInPlace this size (total): %d\n", GrowInPlace[i]); + } + printf("Max Size of SupportsArray:\n"); + for (i = 0; i < (int)(sizeof(MaxElements) / sizeof(MaxElements[0])); ++i) { + if (MaxElements[i]) { + printf("\t%d: %d\n", i, MaxElements[i]); + } + } +} + +// Just so constructor/destructor get called +SupportsStats gSupportsStats; +#endif + nsresult nsQueryElementAt::operator()(const nsIID& aIID, void** aResult) const { @@ -32,6 +99,12 @@ nsSupportsArray::nsSupportsArray() mArray = mAutoArray; mArraySize = kAutoArraySize; mCount = 0; +#if DEBUG_SUPPORTSARRAY + mMaxCount = 0; + mMaxSize = 0; + ADD_TO_STATS(NumberOfSize, kAutoArraySize * sizeof(mArray[0])); + MaxElements[0]++; +#endif } nsSupportsArray::~nsSupportsArray() @@ -82,6 +155,19 @@ nsSupportsArray::GrowArrayBy(uint32_t aGrowBy) mArray = new nsISupports*[newCount.value()]; mArraySize = newCount.value(); +#if DEBUG_SUPPORTSARRAY + if (oldArray == mArray) { // can't happen without use of realloc + ADD_TO_STATS(GrowInPlace, mCount); + } + ADD_TO_STATS(AllocedOfSize, mArraySize * sizeof(mArray[0])); + if (mArraySize > mMaxSize) { + ADD_TO_STATS(NumberOfSize, mArraySize * sizeof(mArray[0])); + if (oldArray != &(mAutoArray[0])) { + SUB_FROM_STATS(NumberOfSize, mCount * sizeof(mArray[0])); + } + mMaxSize = mArraySize; + } +#endif if (oldArray) { // need to move old data if (0 < mCount) { ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); @@ -303,6 +389,14 @@ nsSupportsArray::InsertElementAt(nsISupports* aElement, uint32_t aIndex) NS_IF_ADDREF(aElement); mCount++; +#if DEBUG_SUPPORTSARRAY + if (mCount > mMaxCount && + mCount < (int32_t)(sizeof(MaxElements) / sizeof(MaxElements[0]))) { + MaxElements[mCount]++; + MaxElements[mMaxCount]--; + mMaxCount = mCount; + } +#endif return true; } return false; @@ -406,6 +500,9 @@ nsSupportsArray::Clear(void) NS_IMETHODIMP nsSupportsArray::Compact(void) { +#if DEBUG_SUPPORTSARRAY + uint32_t oldArraySize = mArraySize; +#endif if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) { nsISupports** oldArray = mArray; if (mCount <= kAutoArraySize) { @@ -419,7 +516,15 @@ nsSupportsArray::Compact(void) } mArraySize = mCount; } - +#if DEBUG_SUPPORTSARRAY + if (oldArray == mArray && + oldArray != &(mAutoArray[0])) { // can't happen without use of realloc + ADD_TO_STATS(GrowInPlace, oldArraySize); + } + if (oldArray != &(mAutoArray[0])) { + ADD_TO_STATS(AllocedOfSize, mArraySize * sizeof(mArray[0])); + } +#endif ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); delete[] oldArray; } @@ -429,6 +534,9 @@ nsSupportsArray::Compact(void) NS_IMETHODIMP_(bool) nsSupportsArray::SizeTo(int32_t aSize) { +#if DEBUG_SUPPORTSARRAY + uint32_t oldArraySize = mArraySize; +#endif NS_ASSERTION(aSize >= 0, "negative aSize!"); // XXX for aSize < mCount we could resize to mCount @@ -449,7 +557,15 @@ nsSupportsArray::SizeTo(int32_t aSize) } mArraySize = aSize; } - +#if DEBUG_SUPPORTSARRAY + if (oldArray == mArray && + oldArray != &(mAutoArray[0])) { // can't happen without use of realloc + ADD_TO_STATS(GrowInPlace, oldArraySize); + } + if (oldArray != &(mAutoArray[0])) { + ADD_TO_STATS(AllocedOfSize, mArraySize * sizeof(mArray[0])); + } +#endif ::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*)); if (oldArray != mAutoArray) { delete[] oldArray; diff --git a/xpcom/ds/nsSupportsArray.h b/xpcom/ds/nsSupportsArray.h index 5e5d48e0c5b9..e0200f2d23c4 100644 --- a/xpcom/ds/nsSupportsArray.h +++ b/xpcom/ds/nsSupportsArray.h @@ -7,6 +7,8 @@ #ifndef nsSupportsArray_h__ #define nsSupportsArray_h__ +//#define DEBUG_SUPPORTSARRAY 1 + #include "nsISupportsArray.h" #include "mozilla/Attributes.h" @@ -129,6 +131,10 @@ protected: uint32_t mArraySize; uint32_t mCount; nsISupports* mAutoArray[kAutoArraySize]; +#if DEBUG_SUPPORTSARRAY + uint32_t mMaxCount; + uint32_t mMaxSize; +#endif private: // Copy constructors are not allowed From fed18a42c058a8a75b93cd9ce59120161bfe3ed1 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:58:51 +0200 Subject: [PATCH 09/10] Backed out changeset 5af415bbb107 (bug 1308615) --- browser/modules/ContentWebRTC.jsm | 6 +++--- dom/media/MediaManager.cpp | 19 ++++++++++++------- dom/media/MediaPermissionGonk.cpp | 8 +++++--- mobile/android/chrome/content/WebrtcUI.js | 6 +++--- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/browser/modules/ContentWebRTC.jsm b/browser/modules/ContentWebRTC.jsm index 2e0b6c602101..072bba39d362 100644 --- a/browser/modules/ContentWebRTC.jsm +++ b/browser/modules/ContentWebRTC.jsm @@ -73,10 +73,10 @@ this.ContentWebRTC = { let devices = contentWindow.pendingGetUserMediaRequests.get(callID); forgetGUMRequest(contentWindow, callID); - let allowedDevices = Cc["@mozilla.org/array;1"] - .createInstance(Ci.nsIMutableArray); + let allowedDevices = Cc["@mozilla.org/supports-array;1"] + .createInstance(Ci.nsISupportsArray); for (let deviceIndex of aMessage.data.devices) - allowedDevices.appendElement(devices[deviceIndex], /*weak =*/ false); + allowedDevices.AppendElement(devices[deviceIndex]); Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", callID); break; diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 72071cde5bca..dfee0a098eb3 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -21,6 +21,7 @@ #include "nsIScriptGlobalObject.h" #include "nsIPermissionManager.h" #include "nsIPopupWindowManager.h" +#include "nsISupportsArray.h" #include "nsIDocShell.h" #include "nsIDocument.h" #include "nsISupportsPrimitives.h" @@ -2406,10 +2407,14 @@ if (privileged) { return; } - nsCOMPtr devicesCopy = nsArray::Create(); // before we give up devices below + nsCOMPtr devicesCopy; // before we give up devices below if (!askPermission) { + nsresult rv = NS_NewISupportsArray(getter_AddRefs(devicesCopy)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } for (auto& device : **devices) { - nsresult rv = devicesCopy->AppendElement(device, /*weak =*/ false); + rv = devicesCopy->AppendElement(device); if (NS_WARN_IF(NS_FAILED(rv))) { return; } @@ -3027,15 +3032,15 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, if (aSubject) { // A particular device or devices were chosen by the user. // NOTE: does not allow setting a device to null; assumes nullptr - nsCOMPtr array(do_QueryInterface(aSubject)); + nsCOMPtr array(do_QueryInterface(aSubject)); MOZ_ASSERT(array); uint32_t len = 0; - array->GetLength(&len); + array->Count(&len); bool videoFound = false, audioFound = false; for (uint32_t i = 0; i < len; i++) { - nsCOMPtr device; - array->QueryElementAt(i, NS_GET_IID(nsIMediaDevice), - getter_AddRefs(device)); + nsCOMPtr supports; + array->GetElementAt(i,getter_AddRefs(supports)); + nsCOMPtr device(do_QueryInterface(supports)); MOZ_ASSERT(device); // shouldn't be returning anything else... if (device) { nsString type; diff --git a/dom/media/MediaPermissionGonk.cpp b/dom/media/MediaPermissionGonk.cpp index 2a9cbf331c43..5cefc96f2b47 100644 --- a/dom/media/MediaPermissionGonk.cpp +++ b/dom/media/MediaPermissionGonk.cpp @@ -5,12 +5,12 @@ #include "MediaManager.h" #include "MediaPermissionGonk.h" -#include "nsArray.h" #include "nsCOMPtr.h" #include "nsIContentPermissionPrompt.h" #include "nsIDocument.h" #include "nsIDOMNavigatorUserMedia.h" #include "nsIStringEnumerator.h" +#include "nsISupportsArray.h" #include "nsJSUtils.h" #include "nsQueryObject.h" #include "nsPIDOMWindow.h" @@ -67,10 +67,12 @@ static nsresult NotifyPermissionAllow(const nsAString &aCallID, nsTArray > &aDevices) { nsresult rv; - nsCOMPtr array = nsArray::Create(); + nsCOMPtr array; + rv = NS_NewISupportsArray(getter_AddRefs(array)); + NS_ENSURE_SUCCESS(rv, rv); for (uint32_t i = 0; i < aDevices.Length(); ++i) { - rv = array->AppendElement(aDevices.ElementAt(i), /*weak =*/ false); + rv = array->AppendElement(aDevices.ElementAt(i)); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/mobile/android/chrome/content/WebrtcUI.js b/mobile/android/chrome/content/WebrtcUI.js index 475d05bd2c05..8308801d19c7 100644 --- a/mobile/android/chrome/content/WebrtcUI.js +++ b/mobile/android/chrome/content/WebrtcUI.js @@ -150,19 +150,19 @@ var WebrtcUI = { { label: Strings.browser.GetStringFromName("getUserMedia.shareRequest.label"), callback: function(checked /* ignored */, inputs) { - let allowedDevices = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray); + let allowedDevices = Cc["@mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray); let audioId = 0; if (inputs && inputs.audioDevice != undefined) audioId = inputs.audioDevice; if (audioDevices[audioId]) - allowedDevices.appendElement(audioDevices[audioId], /*weak =*/ false); + allowedDevices.AppendElement(audioDevices[audioId]); let videoId = 0; if (inputs && inputs.videoSource != undefined) videoId = inputs.videoSource; if (videoDevices[videoId]) { - allowedDevices.appendElement(videoDevices[videoId], /*weak =*/ false); + allowedDevices.AppendElement(videoDevices[videoId]); let perms = Services.perms; // Although the lifetime is "session" it will be removed upon // use so it's more of a one-shot. From e90a683f18f1fac44c40aeefbb2512e9b2c95c40 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Fri, 14 Oct 2016 14:59:36 +0200 Subject: [PATCH 10/10] Backed out changeset 9c7364b4579d (bug 1308615) for suspicion that this caused pgo windows test crashes --- browser/modules/ContentWebRTC.jsm | 6 ++-- dom/media/MediaManager.cpp | 34 ++++++++++++----------- dom/media/nsIMediaManager.idl | 4 +-- mobile/android/chrome/content/WebrtcUI.js | 4 +-- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/browser/modules/ContentWebRTC.jsm b/browser/modules/ContentWebRTC.jsm index 072bba39d362..fc4a16b67628 100644 --- a/browser/modules/ContentWebRTC.jsm +++ b/browser/modules/ContentWebRTC.jsm @@ -261,8 +261,8 @@ function forgetPendingListsEventually(aContentWindow) { } function updateIndicators() { - let contentWindowArray = MediaManagerService.activeMediaCaptureWindows; - let count = contentWindowArray.length; + let contentWindowSupportsArray = MediaManagerService.activeMediaCaptureWindows; + let count = contentWindowSupportsArray.Count(); let state = { showGlobalIndicator: count > 0, @@ -280,7 +280,7 @@ function updateIndicators() { // sending duplicate notifications. let contentWindows = new Set(); for (let i = 0; i < count; ++i) { - contentWindows.add(contentWindowArray.queryElementAt(i, Ci.nsISupports).top); + contentWindows.add(contentWindowSupportsArray.GetElementAt(i).top); } for (let contentWindow of contentWindows) { diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index dfee0a098eb3..0f7fec5b3358 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -10,7 +10,6 @@ #include "mozilla/dom/MediaStreamTrack.h" #include "GetUserMediaRequest.h" #include "MediaStreamListener.h" -#include "nsArray.h" #include "nsContentUtils.h" #include "nsHashPropertyBag.h" #ifdef MOZ_WIDGET_GONK @@ -3134,11 +3133,14 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, } nsresult -MediaManager::GetActiveMediaCaptureWindows(nsIArray** aArray) +MediaManager::GetActiveMediaCaptureWindows(nsISupportsArray** aArray) { MOZ_ASSERT(aArray); - - nsCOMPtr array = nsArray::Create(); + nsISupportsArray* array; + nsresult rv = NS_NewISupportsArray(&array); // AddRefs + if (NS_FAILED(rv)) { + return rv; + } for (auto iter = mActiveWindows.Iter(); !iter.Done(); iter.Next()) { const uint64_t& id = iter.Key(); @@ -3169,11 +3171,11 @@ MediaManager::GetActiveMediaCaptureWindows(nsIArray** aArray) } } if (capturing) { - array->AppendElement(window, /*weak =*/ false); + array->AppendElement(window); } } - array.forget(aArray); + *aArray = array; return NS_OK; } @@ -3332,14 +3334,14 @@ MediaManager::IterateWindowListeners(nsPIDOMWindowInner* aWindow, void MediaManager::StopMediaStreams() { - nsCOMPtr array; + nsCOMPtr array; GetActiveMediaCaptureWindows(getter_AddRefs(array)); uint32_t len; - array->GetLength(&len); + array->Count(&len); for (uint32_t i = 0; i < len; i++) { - nsCOMPtr win; - array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner), - getter_AddRefs(win)); + nsCOMPtr window; + array->GetElementAt(i, getter_AddRefs(window)); + nsCOMPtr win(do_QueryInterface(window)); if (win) { OnNavigation(win->WindowID()); } @@ -3351,14 +3353,14 @@ MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId) { // Does page currently have a gUM stream active? - nsCOMPtr array; + nsCOMPtr array; GetActiveMediaCaptureWindows(getter_AddRefs(array)); uint32_t len; - array->GetLength(&len); + array->Count(&len); for (uint32_t i = 0; i < len; i++) { - nsCOMPtr win; - array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner), - getter_AddRefs(win)); + nsCOMPtr window; + array->GetElementAt(i, getter_AddRefs(window)); + nsCOMPtr win(do_QueryInterface(window)); if (win && win->WindowID() == aWindowId) { return true; } diff --git a/dom/media/nsIMediaManager.idl b/dom/media/nsIMediaManager.idl index 6eadbe02d61d..aa947a8fa216 100644 --- a/dom/media/nsIMediaManager.idl +++ b/dom/media/nsIMediaManager.idl @@ -4,7 +4,7 @@ #include "nsISupports.idl" -interface nsIArray; +interface nsISupportsArray; interface nsIDOMWindow; %{C++ @@ -16,7 +16,7 @@ interface nsIDOMWindow; interface nsIMediaManagerService : nsISupports { /* return a array of inner windows that have active captures */ - readonly attribute nsIArray activeMediaCaptureWindows; + readonly attribute nsISupportsArray activeMediaCaptureWindows; /* Get the capture state for the given window and all descendant windows (iframes, etc) */ void mediaCaptureWindowState(in nsIDOMWindow aWindow, out boolean aVideo, out boolean aAudio, diff --git a/mobile/android/chrome/content/WebrtcUI.js b/mobile/android/chrome/content/WebrtcUI.js index 8308801d19c7..afdc90e83c97 100644 --- a/mobile/android/chrome/content/WebrtcUI.js +++ b/mobile/android/chrome/content/WebrtcUI.js @@ -58,7 +58,7 @@ var WebrtcUI = { notify: function() { let windows = MediaManagerService.activeMediaCaptureWindows; - let count = windows.length; + let count = windows.Count(); let msg = {}; if (count == 0) { if (this._notificationId) { @@ -76,7 +76,7 @@ var WebrtcUI = { let cameraActive = false; let audioActive = false; for (let i = 0; i < count; i++) { - let win = windows.queryElementAt(i, Ci.nsIDOMWindow); + let win = windows.GetElementAt(i); let hasAudio = {}; let hasVideo = {}; MediaManagerService.mediaCaptureWindowState(win, hasVideo, hasAudio);