From 4c1f33b169b74dce2af414db30fcf113c4bf2a56 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 10 Sep 2018 22:12:07 +0200 Subject: Bug 1470260 - Part 1: Ensure that 'this' stays alive for the duration of the TickRefreshDriver call. --- layout/base/nsRefreshDriver.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index bc1a27852..8a62b517e 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -478,6 +478,9 @@ private: bool NotifyVsync(TimeStamp aVsyncTimestamp) override { + // IMPORTANT: All paths through this method MUST hold a strong ref on + // |this| for the duration of the TickRefreshDriver callback. + if (!NS_IsMainThread()) { MOZ_ASSERT(XRE_IsParentProcess()); // Compress vsync notifications such that only 1 may run at a time @@ -498,6 +501,7 @@ private: aVsyncTimestamp); NS_DispatchToMainThread(vsyncEvent); } else { + RefPtr kungFuDeathGrip(this); TickRefreshDriver(aVsyncTimestamp); } -- cgit v1.2.3 From 69b88dfccc38b9022e65bf459b199bdf4145ce67 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 10 Sep 2018 22:22:16 +0200 Subject: Bug 1470260 - Part 2: Make RefreshDriverTimer ref-counted and hold a strong ref on it on the stack when nsRefreshDriver::Tick can be reached. --- layout/base/nsRefreshDriver.cpp | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 8a62b517e..b975a69dd 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -143,11 +143,7 @@ public: { } - virtual ~RefreshDriverTimer() - { - MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!"); - MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!"); - } + NS_INLINE_DECL_REFCOUNTING(RefreshDriverTimer) virtual void AddRefreshDriver(nsRefreshDriver* aDriver) { @@ -253,6 +249,12 @@ public: } protected: + virtual ~RefreshDriverTimer() + { + MOZ_ASSERT(mContentRefreshDrivers.Length() == 0, "Should have removed all content refresh drivers from here by now!"); + MOZ_ASSERT(mRootRefreshDrivers.Length() == 0, "Should have removed all root refresh drivers from here by now!"); + } + virtual void StartTimer() = 0; virtual void StopTimer() = 0; virtual void ScheduleNextTick(TimeStamp aNowTime) = 0; @@ -335,10 +337,11 @@ protected: nsTArray > mRootRefreshDrivers; // useful callback for nsITimer-based derived classes, here - // bacause of c++ protected shenanigans + // because of c++ protected shenanigans static void TimerTick(nsITimer* aTimer, void* aClosure) { - RefreshDriverTimer *timer = static_cast(aClosure); + RefPtr timer = + static_cast(aClosure); timer->Tick(); } }; @@ -459,9 +462,7 @@ public: private: // Since VsyncObservers are refCounted, but the RefreshDriverTimer are // explicitly shutdown. We create an inner class that has the VsyncObserver - // and is shutdown when the RefreshDriverTimer is deleted. The alternative is - // to (a) make all RefreshDriverTimer RefCounted or (b) use different - // VsyncObserver types. + // and is shutdown when the RefreshDriverTimer is deleted. class RefreshDriverVsyncObserver final : public VsyncObserver { public: @@ -576,7 +577,9 @@ private: // the scheduled TickRefreshDriver() runs. Check mVsyncRefreshDriverTimer // before use. if (mVsyncRefreshDriverTimer) { - mVsyncRefreshDriverTimer->RunRefreshDrivers(aVsyncTimestamp); + RefPtr timer = mVsyncRefreshDriverTimer; + timer->RunRefreshDrivers(aVsyncTimestamp); + // Note: mVsyncRefreshDriverTimer might be null now. } } @@ -829,7 +832,8 @@ protected: static void TimerTickOne(nsITimer* aTimer, void* aClosure) { - InactiveRefreshDriverTimer *timer = static_cast(aClosure); + RefPtr timer = + static_cast(aClosure); timer->TickOne(); } @@ -881,8 +885,8 @@ NS_IMPL_ISUPPORTS(VsyncChildCreateCallback, nsIIPCBackgroundChildCreateCallback) } // namespace mozilla -static RefreshDriverTimer* sRegularRateTimer; -static InactiveRefreshDriverTimer* sThrottledRateTimer; +static StaticRefPtr sRegularRateTimer; +static StaticRefPtr sThrottledRateTimer; #ifdef XP_WIN static int32_t sHighPrecisionTimerRequests = 0; @@ -964,8 +968,6 @@ GetFirstFrameDelay(imgIRequest* req) nsRefreshDriver::Shutdown() { // clean up our timers - delete sRegularRateTimer; - delete sThrottledRateTimer; sRegularRateTimer = nullptr; sThrottledRateTimer = nullptr; @@ -2229,16 +2231,15 @@ nsRefreshDriver::PVsyncActorCreated(VsyncChild* aVsyncChild) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!XRE_IsParentProcess()); - auto* vsyncRefreshDriverTimer = - new VsyncRefreshDriverTimer(aVsyncChild); + RefPtr vsyncRefreshDriverTimer = + new VsyncRefreshDriverTimer(aVsyncChild); // If we are using software timer, swap current timer to // VsyncRefreshDriverTimer. if (sRegularRateTimer) { sRegularRateTimer->SwapRefreshDrivers(vsyncRefreshDriverTimer); - delete sRegularRateTimer; } - sRegularRateTimer = vsyncRefreshDriverTimer; + sRegularRateTimer = vsyncRefreshDriverTimer.forget(); } void -- cgit v1.2.3 From ca36e991ea55f2d9f78bab558fef10720c9244f0 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 08:58:16 +0200 Subject: Cherry-pick libvpx upstream 52add5896661d186dec284ed646a4b33b607d2c7. --- media/libvpx/bug1480092.patch | 36 ++++++++++++++++++++++++++++++++++++ media/libvpx/update.py | 2 ++ media/libvpx/vp8/common/postproc.c | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 media/libvpx/bug1480092.patch diff --git a/media/libvpx/bug1480092.patch b/media/libvpx/bug1480092.patch new file mode 100644 index 000000000..ae774bb20 --- /dev/null +++ b/media/libvpx/bug1480092.patch @@ -0,0 +1,36 @@ +From f00fe25d7eb13ceafbea6a6987d45fdef64cffb3 Mon Sep 17 00:00:00 2001 +From: Pale Moon +Date: Tue, 11 Sep 2018 08:58:16 +0200 +Subject: [PATCH] Cherry-pick libvpx upstream + 52add5896661d186dec284ed646a4b33b607d2c7. + +--- + media/libvpx/vp8/common/postproc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/media/libvpx/vp8/common/postproc.c b/media/libvpx/vp8/common/postproc.c +index a4e6ae170..3b05bc63e 100644 +--- a/media/libvpx/vp8/common/postproc.c ++++ b/media/libvpx/vp8/common/postproc.c +@@ -325,17 +325,17 @@ void vp8_deblock(VP8_COMMON *cm, + YV12_BUFFER_CONFIG *post, + int q, + int low_var_thresh, + int flag) + { + double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065; + int ppl = (int)(level + .5); + +- const MODE_INFO *mode_info_context = cm->show_frame_mi; ++ const MODE_INFO *mode_info_context = cm->mi; + int mbr, mbc; + + /* The pixel thresholds are adjusted according to if or not the macroblock + * is a skipped block. */ + unsigned char *ylimits = cm->pp_limits_buffer; + unsigned char *uvlimits = cm->pp_limits_buffer + 16 * cm->mb_cols; + (void) low_var_thresh; + (void) flag; +-- +2.16.1.windows.4 + diff --git a/media/libvpx/update.py b/media/libvpx/update.py index 85eed5872..1e9d9b478 100755 --- a/media/libvpx/update.py +++ b/media/libvpx/update.py @@ -608,6 +608,8 @@ def apply_patches(): os.system("patch -p3 < input_frame_validation.patch") # Bug 1315288 - Check input frame resolution for vp9 os.system("patch -p3 < input_frame_validation_vp9.patch") + # Cherrypick fix from upstream + os.system("patch -p3 < bug1480092.patch") def update_readme(commit): with open('README_MOZILLA') as f: diff --git a/media/libvpx/vp8/common/postproc.c b/media/libvpx/vp8/common/postproc.c index a4e6ae170..3b05bc63e 100644 --- a/media/libvpx/vp8/common/postproc.c +++ b/media/libvpx/vp8/common/postproc.c @@ -330,7 +330,7 @@ void vp8_deblock(VP8_COMMON *cm, double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065; int ppl = (int)(level + .5); - const MODE_INFO *mode_info_context = cm->show_frame_mi; + const MODE_INFO *mode_info_context = cm->mi; int mbr, mbc; /* The pixel thresholds are adjusted according to if or not the macroblock -- cgit v1.2.3 From ea86809071918516793f5a4b2096c8aea324bb06 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 09:09:21 +0200 Subject: Bug 1473113 - Defer initializing the MAR index until it's needed. --- modules/libmar/src/mar.h | 1 + modules/libmar/src/mar_read.c | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/modules/libmar/src/mar.h b/modules/libmar/src/mar.h index 98b454d94..776daf648 100644 --- a/modules/libmar/src/mar.h +++ b/modules/libmar/src/mar.h @@ -48,6 +48,7 @@ typedef struct MarItem_ { struct MarFile_ { FILE *fp; MarItem *item_table[TABLESIZE]; + int item_table_is_valid; }; typedef struct MarFile_ MarFile; diff --git a/modules/libmar/src/mar_read.c b/modules/libmar/src/mar_read.c index 17744cdfc..378eaea88 100644 --- a/modules/libmar/src/mar_read.c +++ b/modules/libmar/src/mar_read.c @@ -114,6 +114,7 @@ static int mar_read_index(MarFile *mar) { uint32_t offset_to_index, size_of_index; /* verify MAR ID */ + fseek(mar->fp, 0, SEEK_SET); if (fread(id, MAR_ID_SIZE, 1, mar->fp) != 1) return -1; if (memcmp(id, MAR_ID, MAR_ID_SIZE) != 0) @@ -160,11 +161,8 @@ static MarFile *mar_fpopen(FILE *fp) } mar->fp = fp; + mar->item_table_is_valid = 0; memset(mar->item_table, 0, sizeof(mar->item_table)); - if (mar_read_index(mar)) { - mar_close(mar); - return NULL; - } return mar; } @@ -490,6 +488,14 @@ const MarItem *mar_find_item(MarFile *mar, const char *name) { uint32_t hash; const MarItem *item; + if (!mar->item_table_is_valid) { + if (mar_read_index(mar)) { + return NULL; + } else { + mar->item_table_is_valid = 1; + } + } + hash = mar_hash_name(name); item = mar->item_table[hash]; @@ -503,6 +509,14 @@ int mar_enum_items(MarFile *mar, MarItemCallback callback, void *closure) { MarItem *item; int i; + if (!mar->item_table_is_valid) { + if (mar_read_index(mar)) { + return -1; + } else { + mar->item_table_is_valid = 1; + } + } + for (i = 0; i < TABLESIZE; ++i) { item = mar->item_table[i]; while (item) { -- cgit v1.2.3 From 1de1ce5770f45c0b8601a8148d622b272b4ccdbb Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 10:24:52 +0200 Subject: Bug 1478575 - Unify CamerasChild shutdown paths. --- ipc/glue/BackgroundChildImpl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index b157048a4..a129069bc 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -312,6 +312,7 @@ BackgroundChildImpl::DeallocPCamerasChild(camera::PCamerasChild *aActor) RefPtr child = dont_AddRef(static_cast(aActor)); MOZ_ASSERT(aActor); + camera::Shutdown(); #endif return true; } -- cgit v1.2.3 From 6ded94d38cf94a5da8d6a73dfbfca2acb0d719cc Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 11:55:16 +0200 Subject: Bug 1467363 - Protect access to mTransparentSurface with a lock. --- widget/windows/WinCompositorWidget.cpp | 8 ++++++++ widget/windows/WinCompositorWidget.h | 4 ++++ widget/windows/nsWindowGfx.cpp | 2 ++ 3 files changed, 14 insertions(+) diff --git a/widget/windows/WinCompositorWidget.cpp b/widget/windows/WinCompositorWidget.cpp index f660bd019..99ce67573 100644 --- a/widget/windows/WinCompositorWidget.cpp +++ b/widget/windows/WinCompositorWidget.cpp @@ -22,6 +22,7 @@ using namespace mozilla::gfx; WinCompositorWidget::WinCompositorWidget(const CompositorWidgetInitData& aInitData) : mWidgetKey(aInitData.widgetKey()), mWnd(reinterpret_cast(aInitData.hWnd())), + mTransparentSurfaceLock("mTransparentSurfaceLock"), mTransparencyMode(static_cast(aInitData.transparencyMode())), mMemoryDC(nullptr), mCompositeDC(nullptr), @@ -39,6 +40,7 @@ WinCompositorWidget::WinCompositorWidget(const CompositorWidgetInitData& aInitDa void WinCompositorWidget::OnDestroyWindow() { + MutexAutoLock lock(mTransparentSurfaceLock); mTransparentSurface = nullptr; mMemoryDC = nullptr; } @@ -75,6 +77,8 @@ WinCompositorWidget::GetClientSize() already_AddRefed WinCompositorWidget::StartRemoteDrawing() { + MutexAutoLock lock(mTransparentSurfaceLock); + MOZ_ASSERT(!mCompositeDC); RefPtr surf; @@ -229,6 +233,7 @@ WinCompositorWidget::LeavePresentLock() RefPtr WinCompositorWidget::EnsureTransparentSurface() { + mTransparentSurfaceLock.AssertCurrentThreadOwns(); MOZ_ASSERT(mTransparencyMode == eTransparencyTransparent); IntSize size = GetClientSize().ToUnknownSize(); @@ -245,6 +250,7 @@ WinCompositorWidget::EnsureTransparentSurface() void WinCompositorWidget::CreateTransparentSurface(const gfx::IntSize& aSize) { + mTransparentSurfaceLock.AssertCurrentThreadOwns(); MOZ_ASSERT(!mTransparentSurface && !mMemoryDC); RefPtr surface = new gfxWindowsSurface(aSize, SurfaceFormat::A8R8G8B8_UINT32); mTransparentSurface = surface; @@ -254,6 +260,7 @@ WinCompositorWidget::CreateTransparentSurface(const gfx::IntSize& aSize) void WinCompositorWidget::UpdateTransparency(nsTransparencyMode aMode) { + MutexAutoLock lock(mTransparentSurfaceLock); if (mTransparencyMode == aMode) { return; } @@ -270,6 +277,7 @@ WinCompositorWidget::UpdateTransparency(nsTransparencyMode aMode) void WinCompositorWidget::ClearTransparentWindow() { + MutexAutoLock lock(mTransparentSurfaceLock); if (!mTransparentSurface) { return; } diff --git a/widget/windows/WinCompositorWidget.h b/widget/windows/WinCompositorWidget.h index 9661cab45..1689a8641 100644 --- a/widget/windows/WinCompositorWidget.h +++ b/widget/windows/WinCompositorWidget.h @@ -10,6 +10,7 @@ #include "gfxASurface.h" #include "mozilla/gfx/CriticalSection.h" #include "mozilla/gfx/Point.h" +#include "mozilla/Mutex.h" #include "nsIWidget.h" class nsWindow; @@ -83,6 +84,8 @@ public: return mWnd; } + mozilla::Mutex& GetTransparentSurfaceLock() { return mTransparentSurfaceLock; } + private: HDC GetWindowSurface(); void FreeWindowSurface(HDC dc); @@ -95,6 +98,7 @@ private: gfx::CriticalSection mPresentLock; // Transparency handling. + mozilla::Mutex mTransparentSurfaceLock; nsTransparencyMode mTransparencyMode; RefPtr mTransparentSurface; HDC mMemoryDC; diff --git a/widget/windows/nsWindowGfx.cpp b/widget/windows/nsWindowGfx.cpp index a88631f89..9b303a0f2 100644 --- a/widget/windows/nsWindowGfx.cpp +++ b/widget/windows/nsWindowGfx.cpp @@ -320,6 +320,8 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) #if defined(MOZ_XUL) // don't support transparency for non-GDI rendering, for now if (eTransparencyTransparent == mTransparencyMode) { + // This mutex needs to be held when EnsureTransparentSurface is called. + MutexAutoLock lock(mBasicLayersSurface->GetTransparentSurfaceLock()); targetSurface = mBasicLayersSurface->EnsureTransparentSurface(); } #endif -- cgit v1.2.3 From cbfef7fcdb853916ff04015f6ee2d4b86f424a08 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 12:47:26 +0200 Subject: Move surface data checking to a separate function to make it less "totally nuts" --- dom/base/nsContentUtils.cpp | 51 +++++++++++++++++++++++++++++++++++---------- dom/base/nsContentUtils.h | 8 ++++++- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 8612e76df..2f85c1b7e 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7596,6 +7596,23 @@ nsContentUtils::IsFileImage(nsIFile* aFile, nsACString& aType) return StringBeginsWith(aType, NS_LITERAL_CSTRING("image/")); } +nsresult +nsContentUtils::CalculateBufferSizeForImage(const uint32_t& aStride, + const IntSize& aImageSize, + const SurfaceFormat& aFormat, + size_t* aMaxBufferSize, + size_t* aUsedBufferSize) +{ + CheckedInt32 requiredBytes = + CheckedInt32(aStride) * CheckedInt32(aImageSize.height); + if (!requiredBytes.isValid()) { + return NS_ERROR_FAILURE; + } + *aMaxBufferSize = requiredBytes.value(); + *aUsedBufferSize = *aMaxBufferSize - aStride + (aImageSize.width * BytesPerPixel(aFormat)); + return NS_OK; +} + nsresult nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem, imgIContainer** aContainer) @@ -7611,6 +7628,21 @@ nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem, Shmem data = aItem.data().get_Shmem(); + // Validate shared memory buffer size + size_t imageBufLen = 0; + size_t maxBufLen = 0; + nsresult rv = CalculateBufferSizeForImage(imageDetails.stride(), + size, + imageDetails.format(), + &maxBufLen, + &imageBufLen); + if (NS_FAILED(rv)) { + return rv; + } + if (imageBufLen > data.Size()) { + return NS_ERROR_FAILURE; + } + RefPtr image = CreateDataSourceSurfaceFromData(size, static_cast(imageDetails.format()), @@ -7950,20 +7982,17 @@ GetSurfaceDataImpl(mozilla::gfx::DataSourceSurface* aSurface, return GetSurfaceDataContext::NullValue(); } - mozilla::gfx::IntSize size = aSurface->GetSize(); - mozilla::CheckedInt32 requiredBytes = - mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height); - if (!requiredBytes.isValid()) { + size_t bufLen = 0; + size_t maxBufLen = 0; + nsresult rv = nsContentUtils::CalculateBufferSizeForImage(map.mStride, + aSurface->GetSize(), + aSurface->GetFormat(), + &maxBufLen, + &bufLen); + if (NS_FAILED(rv)) { return GetSurfaceDataContext::NullValue(); } - size_t maxBufLen = requiredBytes.value(); - mozilla::gfx::SurfaceFormat format = aSurface->GetFormat(); - - // Surface data handling is totally nuts. This is the magic one needs to - // know to access the data. - size_t bufLen = maxBufLen - map.mStride + (size.width * BytesPerPixel(format)); - // nsDependentCString wants null-terminated string. typename GetSurfaceDataContext::ReturnType surfaceData = aContext.Allocate(maxBufLen + 1); if (GetSurfaceDataContext::GetBuffer(surfaceData)) { diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h index c255f813a..98df92efb 100644 --- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -975,11 +975,17 @@ public: static bool PrefetchEnabled(nsIDocShell* aDocShell); + static nsresult CalculateBufferSizeForImage(const uint32_t& aStride, + const mozilla::gfx::IntSize& aImageSize, + const mozilla::gfx::SurfaceFormat& aFormat, + size_t* aMaxBufferSize, + size_t* aUsedBufferSize); + +private: /** * Fill (with the parameters given) the localized string named |aKey| in * properties file |aFile|. */ -private: static nsresult FormatLocalizedString(PropertiesFile aFile, const char* aKey, const char16_t** aParams, -- cgit v1.2.3 From 09319b435f0e87cb9def1a695ec59e336de8ff51 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 12:48:40 +0200 Subject: Release mapped surface memory on size check failure to plug a leak. --- dom/base/nsContentUtils.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 2f85c1b7e..49fe5143f 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7990,6 +7990,8 @@ GetSurfaceDataImpl(mozilla::gfx::DataSourceSurface* aSurface, &maxBufLen, &bufLen); if (NS_FAILED(rv)) { + // Release mapped memory + aSurface->Unmap(); return GetSurfaceDataContext::NullValue(); } -- cgit v1.2.3 From 6195a2f1e2f5d693effe172ad1012b3c2eeac777 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 13:53:06 +0200 Subject: Fix build bustage in cbfef7fcdb853916ff04015f6ee2d4b86f424a08 - imageDetails.format() needs a cast to SurfaceFormat - style nit: wrap long lines. --- dom/base/nsContentUtils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 49fe5143f..3696195dd 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -7609,7 +7609,8 @@ nsContentUtils::CalculateBufferSizeForImage(const uint32_t& aStride, return NS_ERROR_FAILURE; } *aMaxBufferSize = requiredBytes.value(); - *aUsedBufferSize = *aMaxBufferSize - aStride + (aImageSize.width * BytesPerPixel(aFormat)); + *aUsedBufferSize = *aMaxBufferSize - aStride + + (aImageSize.width * BytesPerPixel(aFormat)); return NS_OK; } @@ -7633,7 +7634,8 @@ nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem, size_t maxBufLen = 0; nsresult rv = CalculateBufferSizeForImage(imageDetails.stride(), size, - imageDetails.format(), + static_cast( + imageDetails.format()), &maxBufLen, &imageBufLen); if (NS_FAILED(rv)) { -- cgit v1.2.3 From a95078a6c6c8ed253c5e279c71462d0d45c1aec3 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 14:24:50 +0200 Subject: Bug 1469309 - Remove an unused sensor type. --- hal/Hal.cpp | 1 + hal/HalSensor.h | 3 +-- hal/sandbox/SandboxHal.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hal/Hal.cpp b/hal/Hal.cpp index 16201a2d8..e60a3ee61 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -590,6 +590,7 @@ UnregisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) { AssertMainThread(); if (!gSensorObservers) { + HAL_ERR("Un-registering a sensor when none have been registered"); return; } diff --git a/hal/HalSensor.h b/hal/HalSensor.h index 551c4271d..5175629c9 100644 --- a/hal/HalSensor.h +++ b/hal/HalSensor.h @@ -18,7 +18,6 @@ namespace hal { * If you add or change any here, do the same in GeckoHalDefines.java. */ enum SensorType { - SENSOR_UNKNOWN = -1, SENSOR_ORIENTATION = 0, SENSOR_ACCELERATION = 1, SENSOR_PROXIMITY = 2, @@ -63,7 +62,7 @@ namespace IPC { struct ParamTraits: public ContiguousEnumSerializer< mozilla::hal::SensorType, - mozilla::hal::SENSOR_UNKNOWN, + mozilla::hal::SENSOR_ORIENTATION, mozilla::hal::NUM_SENSOR_TYPE> { }; diff --git a/hal/sandbox/SandboxHal.cpp b/hal/sandbox/SandboxHal.cpp index 9771b3ef6..5501d459b 100644 --- a/hal/sandbox/SandboxHal.cpp +++ b/hal/sandbox/SandboxHal.cpp @@ -16,6 +16,7 @@ #include "mozilla/dom/battery/Types.h" #include "mozilla/dom/network/Types.h" #include "mozilla/dom/ScreenOrientation.h" +#include "mozilla/EnumeratedRange.h" #include "mozilla/Observer.h" #include "mozilla/Unused.h" #include "nsAutoPtr.h" @@ -404,9 +405,8 @@ public: hal::UnregisterBatteryObserver(this); hal::UnregisterNetworkObserver(this); hal::UnregisterScreenConfigurationObserver(this); - for (int32_t sensor = SENSOR_UNKNOWN + 1; - sensor < NUM_SENSOR_TYPE; ++sensor) { - hal::UnregisterSensorObserver(SensorType(sensor), this); + for (auto sensor : MakeEnumeratedRange(NUM_SENSOR_TYPE)) { + hal::UnregisterSensorObserver(sensor, this); } hal::UnregisterWakeLockObserver(this); hal::UnregisterSystemClockChangeObserver(this); -- cgit v1.2.3 From 9830cd079d8306abc223461190553af64b6fd0ca Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 14:48:21 +0200 Subject: Bug 1472925 - Keep a strong reference to MediaStreamGraph from GraphDriver. --- dom/media/GraphDriver.cpp | 8 +++++--- dom/media/GraphDriver.h | 6 ++---- dom/media/MediaStreamGraph.cpp | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/dom/media/GraphDriver.cpp b/dom/media/GraphDriver.cpp index cae15eb8c..e77268131 100644 --- a/dom/media/GraphDriver.cpp +++ b/dom/media/GraphDriver.cpp @@ -200,7 +200,7 @@ public: STREAM_LOG(LogLevel::Debug, ("Starting system thread")); profiler_register_thread("MediaStreamGraph", &aLocal); LIFECYCLE_LOG("Starting a new system driver for graph %p\n", - mDriver->mGraphImpl); + mDriver->mGraphImpl.get()); RefPtr previousDriver; { @@ -236,7 +236,7 @@ private: void ThreadedDriver::Start() { - LIFECYCLE_LOG("Starting thread for a SystemClockDriver %p\n", mGraphImpl); + LIFECYCLE_LOG("Starting thread for a SystemClockDriver %p\n", mGraphImpl.get()); Unused << NS_WARN_IF(mThread); if (!mThread) { // Ensure we haven't already started it nsCOMPtr event = new MediaStreamGraphInitThreadRunnable(this); @@ -830,7 +830,9 @@ AudioCallbackDriver::Revive() mGraphImpl->SetCurrentDriver(NextDriver()); NextDriver()->Start(); } else { - STREAM_LOG(LogLevel::Debug, ("Starting audio threads for MediaStreamGraph %p from a new thread.", mGraphImpl)); + STREAM_LOG(LogLevel::Debug, + ("Starting audio threads for MediaStreamGraph %p from a new thread.", + mGraphImpl.get())); RefPtr initEvent = new AsyncCubebTask(this, AsyncCubebOperation::INIT); initEvent->Dispatch(); diff --git a/dom/media/GraphDriver.h b/dom/media/GraphDriver.h index 411e175d3..bb4f2689b 100644 --- a/dom/media/GraphDriver.h +++ b/dom/media/GraphDriver.h @@ -210,10 +210,8 @@ protected: // Time of the end of this graph iteration. This must be accessed while having // the monitor. GraphTime mIterationEnd; - // The MediaStreamGraphImpl that owns this driver. This has a lifetime longer - // than the driver, and will never be null. Hence, it can be accesed without - // monitor. - MediaStreamGraphImpl* mGraphImpl; + // The MediaStreamGraphImpl associated with this driver. + const RefPtr mGraphImpl; // This enum specifies the wait state of the driver. enum WaitState { diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index e2934cbb2..1b9e4f674 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -3371,7 +3371,8 @@ MediaStreamGraphImpl::Destroy() // First unregister from memory reporting. UnregisterWeakMemoryReporter(this); - // Clear the self reference which will destroy this instance. + // Clear the self reference which will destroy this instance if all + // associated GraphDrivers are destroyed. mSelfRef = nullptr; } -- cgit v1.2.3 From a6d4e65dbfccc77c027bd827f3ea6be0e8df2838 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 15:33:44 +0200 Subject: Bug 1466991 - Part 1: Factor out ShouldUseXBLScope. --- dom/base/nsIDocument.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 7a73fae71..e5d12ab8f 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -3439,13 +3439,29 @@ nsINode::OwnerDocAsNode() const return OwnerDoc(); } +// ShouldUseXBLScope is defined here as a template so that we can get the faster +// version of IsInAnonymousSubtree if we're statically known to be an +// nsIContent. we could try defining ShouldUseXBLScope separately on nsINode +// and nsIContent, but then we couldn't put its nsINode implementation here +// (because this header does not include nsIContent) and we can't put it in +// nsIContent.h, because the definition of nsIContent::IsInAnonymousSubtree is +// in nsIContentInlines.h. And then we get include hell from people trying to +// call nsINode::GetParentObject but not including nsIContentInlines.h and with +// no really good way to include it. +template +inline bool ShouldUseXBLScope(const T* aNode) +{ + return aNode->IsInAnonymousSubtree() && + !aNode->IsAnonymousContentInSVGUseSubtree(); +} + inline mozilla::dom::ParentObject nsINode::GetParentObject() const { mozilla::dom::ParentObject p(OwnerDoc()); // Note that mUseXBLScope is a no-op for chrome, and other places where we // don't use XBL scopes. - p.mUseXBLScope = IsInAnonymousSubtree() && !IsAnonymousContentInSVGUseSubtree(); + p.mUseXBLScope = ShouldUseXBLScope(this); return p; } -- cgit v1.2.3 From d086e918b45bbc7a841b46c3d444b2e9d7d7e4c3 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 15:38:13 +0200 Subject: Bug 1466991 - Part 2: Reparent nodes when they start being in the XBL scope. --- dom/base/nsINode.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index 09e848710..ca507a5fc 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -27,6 +27,7 @@ #include "mozilla/dom/Element.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/ShadowRoot.h" +#include "mozilla/dom/ScriptSettings.h" #include "nsAttrValueOrString.h" #include "nsBindingManager.h" #include "nsCCUncollectableMarker.h" @@ -1569,6 +1570,48 @@ CheckForOutdatedParent(nsINode* aParent, nsINode* aNode) return NS_OK; } +static nsresult +ReparentWrappersInSubtree(nsIContent* aRoot) +{ + MOZ_ASSERT(ShouldUseXBLScope(aRoot)); + // Start off with no global so we don't fire any error events on failure. + AutoJSAPI jsapi; + jsapi.Init(); + + JSContext* cx = jsapi.cx(); + + nsIGlobalObject* docGlobal = aRoot->OwnerDoc()->GetScopeObject(); + if (NS_WARN_IF(!docGlobal)) { + return NS_ERROR_UNEXPECTED; + } + + JS::Rooted rootedGlobal(cx, docGlobal->GetGlobalJSObject()); + if (NS_WARN_IF(!rootedGlobal)) { + return NS_ERROR_UNEXPECTED; + } + + rootedGlobal = xpc::GetXBLScope(cx, rootedGlobal); + + nsresult rv; + JS::Rooted reflector(cx); + for (nsIContent* cur = aRoot; cur; cur = cur->GetNextNode(aRoot)) { + if ((reflector = cur->GetWrapper())) { + JSAutoCompartment ac(cx, reflector); + rv = ReparentWrapper(cx, reflector); + if NS_FAILED(rv) { + // We _could_ consider BlastSubtreeToPieces here, but it's not really + // needed. Having some nodes in here accessible to content while others + // are not is probably OK. We just need to fail out of the actual + // insertion, so they're not in the DOM. Returning a failure here will + // do that. + return rv; + } + } + } + + return NS_OK; +} + nsresult nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex, bool aNotify, nsAttrAndChildArray& aChildArray) @@ -1606,9 +1649,15 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex, nsIContent* parent = IsNodeOfType(eDOCUMENT) ? nullptr : static_cast(this); + bool wasInXBLScope = ShouldUseXBLScope(aKid); rv = aKid->BindToTree(doc, parent, parent ? parent->GetBindingParent() : nullptr, true); + if (NS_SUCCEEDED(rv) && !wasInXBLScope && ShouldUseXBLScope(aKid)) { + MOZ_ASSERT(ShouldUseXBLScope(this), + "Why does the kid need to use an XBL scope?"); + rv = ReparentWrappersInSubtree(aKid); + } if (NS_FAILED(rv)) { if (GetFirstChild() == aKid) { mFirstChild = aKid->GetNextSibling(); -- cgit v1.2.3