aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Beich <jbeich@FreeBSD.org>2017-12-26 22:03:18 +0000
committerJan Beich <jbeich@FreeBSD.org>2017-12-26 22:03:18 +0000
commit5e7649c09a21d2d6622b6e6f25e4edf38d61e9c0 (patch)
tree97a775b15aacf279c92886279dedfdf89f7b7950
parentfbb6042c02e7c64c771989e6258b0bfd474fc83b (diff)
downloadports-5e7649c09a21d2d6622b6e6f25e4edf38d61e9c0.tar.gz
ports-5e7649c09a21d2d6622b6e6f25e4edf38d61e9c0.zip
MFH: r457317
www/firefox: apply some FF58 fixes PR: 222859 Security: a891c5b4-3d7a-4de9-9c71-eef3fd698c77 Approved by: ports-secteam blanket
Notes
Notes: svn path=/branches/2017Q4/; revision=457318
-rw-r--r--www/firefox/Makefile2
-rw-r--r--www/firefox/files/patch-bug1224396146
-rw-r--r--www/firefox/files/patch-bug139940039
-rw-r--r--www/firefox/files/patch-bug139952093
-rw-r--r--www/firefox/files/patch-bug1408276170
-rw-r--r--www/firefox/files/patch-bug1409951177
-rw-r--r--www/firefox/files/patch-bug141013452
-rw-r--r--www/firefox/files/patch-bug1412145286
-rw-r--r--www/firefox/files/patch-bug141374125
-rw-r--r--www/firefox/files/patch-bug1414425231
-rw-r--r--www/firefox/files/patch-bug141445270
-rw-r--r--www/firefox/files/patch-bug141494543
-rw-r--r--www/firefox/files/patch-bug141544122
-rw-r--r--www/firefox/files/patch-bug141558234
-rw-r--r--www/firefox/files/patch-bug141559858
-rw-r--r--www/firefox/files/patch-bug141779725
-rw-r--r--www/firefox/files/patch-bug141844726
-rw-r--r--www/firefox/files/patch-bug1418854102
-rw-r--r--www/firefox/files/patch-bug141936332
-rw-r--r--www/firefox/files/patch-bug142238928
-rw-r--r--www/firefox/files/patch-bug1423086222
-rw-r--r--www/firefox/files/patch-bug142315969
-rw-r--r--www/firefox/files/patch-bug1424373305
-rw-r--r--www/firefox/files/patch-z-bug1382366159
24 files changed, 2415 insertions, 1 deletions
diff --git a/www/firefox/Makefile b/www/firefox/Makefile
index 6bc262e63268..608b482ceccd 100644
--- a/www/firefox/Makefile
+++ b/www/firefox/Makefile
@@ -4,7 +4,7 @@
PORTNAME= firefox
DISTVERSION= 56.0.2
DISTVERSIONSUFFIX=.source
-PORTREVISION= 11
+PORTREVISION= 12
PORTEPOCH= 1
CATEGORIES= www ipv6
MASTER_SITES= MOZILLA/${PORTNAME}/releases/${DISTVERSION}/source \
diff --git a/www/firefox/files/patch-bug1224396 b/www/firefox/files/patch-bug1224396
new file mode 100644
index 000000000000..433bf755fb02
--- /dev/null
+++ b/www/firefox/files/patch-bug1224396
@@ -0,0 +1,146 @@
+commit 94f55f3a6124
+Author: Lee Salzman <lsalzman@mozilla.com>
+Date: Wed Nov 22 12:19:29 2017 -0500
+
+ Bug 1224396 - Skia path allocation cleanups. r=msreckovic a=gchang
+
+ MozReview-Commit-ID: GAf2vC1Fucv
+
+ --HG--
+ extra : source : db4543ce21ce1e8a1c81b685a16e61f71db2f602
+---
+ gfx/skia/skia/include/core/SkPathRef.h | 24 ++++++++++++++----------
+ gfx/skia/skia/src/core/SkArenaAlloc.cpp | 23 ++++++++++++++++++-----
+ gfx/skia/skia/src/core/SkArenaAlloc.h | 5 ++++-
+ 3 files changed, 36 insertions(+), 16 deletions(-)
+
+diff --git gfx/skia/skia/include/core/SkPathRef.h gfx/skia/skia/include/core/SkPathRef.h
+index 5e6fda7d85b2..24870c64fbc0 100644
+--- gfx/skia/skia/include/core/SkPathRef.h
++++ gfx/skia/skia/include/core/SkPathRef.h
+@@ -16,7 +16,7 @@
+ #include "SkRRect.h"
+ #include "SkRect.h"
+ #include "SkRefCnt.h"
+-#include <stddef.h> // ptrdiff_t
++#include "../private/SkTemplates.h"
+
+ class SkRBuffer;
+ class SkWBuffer;
+@@ -433,31 +433,35 @@ private:
+ */
+ void makeSpace(size_t size) {
+ SkDEBUGCODE(this->validate();)
+- ptrdiff_t growSize = size - fFreeSpace;
+- if (growSize <= 0) {
++ if (size <= fFreeSpace) {
+ return;
+ }
++ size_t growSize = size - fFreeSpace;
+ size_t oldSize = this->currSize();
+ // round to next multiple of 8 bytes
+ growSize = (growSize + 7) & ~static_cast<size_t>(7);
+ // we always at least double the allocation
+- if (static_cast<size_t>(growSize) < oldSize) {
++ if (growSize < oldSize) {
+ growSize = oldSize;
+ }
+ if (growSize < kMinSize) {
+ growSize = kMinSize;
+ }
+- size_t newSize = oldSize + growSize;
++ constexpr size_t maxSize = std::numeric_limits<size_t>::max();
++ size_t newSize;
++ if (growSize <= maxSize - oldSize) {
++ newSize = oldSize + growSize;
++ } else {
++ SK_ABORT("Path too big.");
++ }
+ // Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO:
+ // encapsulate this.
+ fPoints = reinterpret_cast<SkPoint*>(sk_realloc_throw(fPoints, newSize));
+ size_t oldVerbSize = fVerbCnt * sizeof(uint8_t);
+- void* newVerbsDst = reinterpret_cast<void*>(
+- reinterpret_cast<intptr_t>(fPoints) + newSize - oldVerbSize);
+- void* oldVerbsSrc = reinterpret_cast<void*>(
+- reinterpret_cast<intptr_t>(fPoints) + oldSize - oldVerbSize);
++ void* newVerbsDst = SkTAddOffset<void>(fPoints, newSize - oldVerbSize);
++ void* oldVerbsSrc = SkTAddOffset<void>(fPoints, oldSize - oldVerbSize);
+ memmove(newVerbsDst, oldVerbsSrc, oldVerbSize);
+- fVerbs = reinterpret_cast<uint8_t*>(reinterpret_cast<intptr_t>(fPoints) + newSize);
++ fVerbs = SkTAddOffset<uint8_t>(fPoints, newSize);
+ fFreeSpace += growSize;
+ SkDEBUGCODE(this->validate();)
+ }
+diff --git gfx/skia/skia/src/core/SkArenaAlloc.cpp gfx/skia/skia/src/core/SkArenaAlloc.cpp
+index eca3aa97d761..57a19093d065 100644
+--- gfx/skia/skia/src/core/SkArenaAlloc.cpp
++++ gfx/skia/skia/src/core/SkArenaAlloc.cpp
+@@ -8,6 +8,7 @@
+ #include <algorithm>
+ #include <cstddef>
+ #include "SkArenaAlloc.h"
++#include "SkTypes.h"
+
+ static char* end_chain(char*) { return nullptr; }
+
+@@ -95,19 +96,31 @@ void SkArenaAlloc::ensureSpace(uint32_t size, uint32_t alignment) {
+ // This must be conservative to add the right amount of extra memory to handle the alignment
+ // padding.
+ constexpr uint32_t alignof_max_align_t = 8;
+- uint32_t objSizeAndOverhead = size + headerSize + sizeof(Footer);
++ constexpr uint32_t maxSize = std::numeric_limits<uint32_t>::max();
++ constexpr uint32_t overhead = headerSize + sizeof(Footer);
++ SkASSERT_RELEASE(size <= maxSize - overhead);
++ uint32_t objSizeAndOverhead = size + overhead;
+ if (alignment > alignof_max_align_t) {
+- objSizeAndOverhead += alignment - 1;
++ uint32_t alignmentOverhead = alignment - 1;
++ SkASSERT_RELEASE(objSizeAndOverhead <= maxSize - alignmentOverhead);
++ objSizeAndOverhead += alignmentOverhead;
+ }
+
+- uint32_t allocationSize = std::max(objSizeAndOverhead, fExtraSize * fFib0);
+- fFib0 += fFib1;
+- std::swap(fFib0, fFib1);
++ uint32_t minAllocationSize;
++ if (fExtraSize <= maxSize / fFib0) {
++ minAllocationSize = fExtraSize * fFib0;
++ fFib0 += fFib1;
++ std::swap(fFib0, fFib1);
++ } else {
++ minAllocationSize = maxSize;
++ }
++ uint32_t allocationSize = std::max(objSizeAndOverhead, minAllocationSize);
+
+ // Round up to a nice size. If > 32K align to 4K boundary else up to max_align_t. The > 32K
+ // heuristic is from the JEMalloc behavior.
+ {
+ uint32_t mask = allocationSize > (1 << 15) ? (1 << 12) - 1 : 16 - 1;
++ SkASSERT_RELEASE(allocationSize <= maxSize - mask);
+ allocationSize = (allocationSize + mask) & ~mask;
+ }
+
+diff --git gfx/skia/skia/src/core/SkArenaAlloc.h gfx/skia/skia/src/core/SkArenaAlloc.h
+index 494696ce768d..05d3336684e9 100644
+--- gfx/skia/skia/src/core/SkArenaAlloc.h
++++ gfx/skia/skia/src/core/SkArenaAlloc.h
+@@ -157,6 +157,7 @@ private:
+ template <typename T>
+ char* commonArrayAlloc(uint32_t count) {
+ char* objStart;
++ SkASSERT_RELEASE(count <= std::numeric_limits<uint32_t>::max() / sizeof(T));
+ uint32_t arraySize = SkTo<uint32_t>(count * sizeof(T));
+ uint32_t alignment = SkTo<uint32_t>(alignof(T));
+
+@@ -164,7 +165,9 @@ private:
+ objStart = this->allocObject(arraySize, alignment);
+ fCursor = objStart + arraySize;
+ } else {
+- uint32_t totalSize = arraySize + sizeof(Footer) + sizeof(uint32_t);
++ constexpr uint32_t overhead = sizeof(Footer) + sizeof(uint32_t);
++ SkASSERT_RELEASE(arraySize <= std::numeric_limits<uint32_t>::max() - overhead);
++ uint32_t totalSize = arraySize + overhead;
+ objStart = this->allocObjectWithFooter(totalSize, alignment);
+
+ // Can never be UB because max value is alignof(T).
diff --git a/www/firefox/files/patch-bug1399400 b/www/firefox/files/patch-bug1399400
new file mode 100644
index 000000000000..be983e1369b7
--- /dev/null
+++ b/www/firefox/files/patch-bug1399400
@@ -0,0 +1,39 @@
+commit 7c15d03b1e83
+Author: Blake Kaplan <mrbkap@gmail.com>
+Date: Mon Dec 18 19:39:45 2017 -0500
+
+ Bug 1399400 - Use a strong reference when handling mTextField. r=bz a=jcristau
+
+ MozReview-Commit-ID: IqzGDM4ezeW
+
+ --HG--
+ extra : rebase_source : 8f9a1f72360fcabdc6e57fec3dbdda1bd705fd03
+ extra : source : 02d457ace9bb8430e25cfb3a1fb6b0303c9d01c5
+---
+ layout/forms/nsNumberControlFrame.cpp | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git layout/forms/nsNumberControlFrame.cpp layout/forms/nsNumberControlFrame.cpp
+index 00b4492f23f1..68819267c906 100644
+--- layout/forms/nsNumberControlFrame.cpp
++++ layout/forms/nsNumberControlFrame.cpp
+@@ -592,15 +592,17 @@ nsNumberControlFrame::HandleFocusEvent(WidgetEvent* aEvent)
+ {
+ if (aEvent->mOriginalTarget != mTextField) {
+ // Move focus to our text field
++ RefPtr<HTMLInputElement> textField = HTMLInputElement::FromContent(mTextField);
+ IgnoredErrorResult ignored;
+- HTMLInputElement::FromContent(mTextField)->Focus(ignored);
++ textField->Focus(ignored);
+ }
+ }
+
+ void
+ nsNumberControlFrame::HandleSelectCall()
+ {
+- HTMLInputElement::FromContent(mTextField)->Select();
++ RefPtr<HTMLInputElement> textField = HTMLInputElement::FromContent(mTextField);
++ textField->Select();
+ }
+
+ #define STYLES_DISABLING_NATIVE_THEMING \
diff --git a/www/firefox/files/patch-bug1399520 b/www/firefox/files/patch-bug1399520
new file mode 100644
index 000000000000..0db6cf64bb7c
--- /dev/null
+++ b/www/firefox/files/patch-bug1399520
@@ -0,0 +1,93 @@
+commit b4603106d015
+Author: Liang-Heng Chen <xeonchen@gmail.com>
+Date: Thu Oct 19 22:29:41 2017 -0400
+
+ Bug 1399520 - Avoid race condition. r=dragana
+
+ MozReview-Commit-ID: 6Pd2HXqBgX4
+---
+ modules/libjar/nsJAR.cpp | 26 ++++++++++++++++++--------
+ modules/libjar/nsJAR.h | 8 +++++---
+ 2 files changed, 23 insertions(+), 11 deletions(-)
+
+diff --git modules/libjar/nsJAR.cpp modules/libjar/nsJAR.cpp
+index 80589e03f92b..b3121d99ef0a 100644
+--- modules/libjar/nsJAR.cpp
++++ modules/libjar/nsJAR.cpp
+@@ -43,11 +43,27 @@ NS_IMPL_QUERY_INTERFACE(nsJAR, nsIZipReader)
+ NS_IMPL_ADDREF(nsJAR)
+
+ // Custom Release method works with nsZipReaderCache...
++// Release might be called from multi-thread, we have to
++// take this function carefully to avoid delete-after-use.
+ MozExternalRefCountType nsJAR::Release(void)
+ {
+ nsrefcnt count;
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+- count = --mRefCnt;
++
++ RefPtr<nsZipReaderCache> cache;
++ if (mRefCnt == 2) { // don't use a lock too frequently
++ // Use a mutex here to guarantee mCache is not racing and the target instance
++ // is still valid to increase ref-count.
++ MutexAutoLock lock(mLock);
++ cache = mCache;
++ mCache = nullptr;
++ }
++ if (cache) {
++ DebugOnly<nsresult> rv = cache->ReleaseZip(this);
++ MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to release zip file");
++ }
++
++ count = --mRefCnt; // don't access any member variable after this line
+ NS_LOG_RELEASE(this, count, "nsJAR");
+ if (0 == count) {
+ mRefCnt = 1; /* stabilize */
+@@ -56,13 +72,7 @@ MozExternalRefCountType nsJAR::Release(void)
+ delete this;
+ return 0;
+ }
+- if (1 == count && mCache) {
+-#ifdef DEBUG
+- nsresult rv =
+-#endif
+- mCache->ReleaseZip(this);
+- NS_ASSERTION(NS_SUCCEEDED(rv), "failed to release zip file");
+- }
++
+ return count;
+ }
+
+diff --git modules/libjar/nsJAR.h modules/libjar/nsJAR.h
+index 7f675c93003b..4fe948680fbf 100644
+--- modules/libjar/nsJAR.h
++++ modules/libjar/nsJAR.h
+@@ -12,6 +12,7 @@
+ #include "mozilla/Logging.h"
+ #include "prinrval.h"
+
++#include "mozilla/Atomics.h"
+ #include "mozilla/Mutex.h"
+ #include "nsIComponentManager.h"
+ #include "nsCOMPtr.h"
+@@ -75,8 +76,9 @@ class nsJAR final : public nsIZipReader
+ mReleaseTime = PR_INTERVAL_NO_TIMEOUT;
+ }
+
+- void SetZipReaderCache(nsZipReaderCache* cache) {
+- mCache = cache;
++ void SetZipReaderCache(nsZipReaderCache* aCache) {
++ mozilla::MutexAutoLock lock(mLock);
++ mCache = aCache;
+ }
+
+ nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc);
+@@ -89,7 +91,7 @@ class nsJAR final : public nsIZipReader
+ RefPtr<nsZipArchive> mZip; // The underlying zip archive
+ PRIntervalTime mReleaseTime; // used by nsZipReaderCache for flushing entries
+ nsZipReaderCache* mCache; // if cached, this points to the cache it's contained in
+- mozilla::Mutex mLock;
++ mozilla::Mutex mLock; // protect mCache and mZip
+ int64_t mMtime;
+ bool mOpened;
+ bool mIsOmnijar;
diff --git a/www/firefox/files/patch-bug1408276 b/www/firefox/files/patch-bug1408276
new file mode 100644
index 000000000000..e0e434921252
--- /dev/null
+++ b/www/firefox/files/patch-bug1408276
@@ -0,0 +1,170 @@
+commit a9bc6108422a
+Author: Karl Tomlinson <karlt+@karlt.net>
+Date: Tue Oct 17 18:14:43 2017 +1300
+
+ Bug 1408276 - Move to LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP at end of iteration. r=padenot, a=gchang
+
+ MozReview-Commit-ID: GbfIOPZPuGu
+
+ --HG--
+ extra : rebase_source : acc2bcee9a36d2b8f18826f08825895de5df0c1e
+---
+ dom/media/GraphDriver.cpp | 27 +++++++++++++++++----------
+ dom/media/MediaStreamGraph.cpp | 32 +++++++++++++++++++++-----------
+ dom/media/MediaStreamGraphImpl.h | 12 +++++++++++-
+ 3 files changed, 49 insertions(+), 22 deletions(-)
+
+diff --git dom/media/GraphDriver.cpp dom/media/GraphDriver.cpp
+index 7f6f386fdaca..13944338e3d7 100644
+--- dom/media/GraphDriver.cpp
++++ dom/media/GraphDriver.cpp
+@@ -284,8 +284,7 @@ SystemClockDriver::IsFallback()
+ void
+ ThreadedDriver::RunThread()
+ {
+- bool stillProcessing = true;
+- while (stillProcessing) {
++ while (true) {
+ mIterationStart = IterationEnd();
+ mIterationEnd += GetIntervalForIteration();
+
+@@ -324,10 +323,16 @@ ThreadedDriver::RunThread()
+ (long)stateComputedTime,
+ (long)nextStateComputedTime));
+
+- stillProcessing = mGraphImpl->OneIteration(nextStateComputedTime);
++ bool stillProcessing = mGraphImpl->OneIteration(nextStateComputedTime);
+
++ if (!stillProcessing) {
++ // Enter shutdown mode. The stable-state handler will detect this
++ // and complete shutdown if the graph does not get restarted.
++ mGraphImpl->SignalMainThreadCleanup();
++ return;
++ }
+ MonitorAutoLock lock(GraphImpl()->GetMonitor());
+- if (NextDriver() && stillProcessing) {
++ if (NextDriver()) {
+ LOG(LogLevel::Debug, ("Switching to AudioCallbackDriver"));
+ RemoveCallback();
+ NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd);
+@@ -1009,13 +1014,20 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
+ mGraphImpl->NotifyOutputData(aOutputBuffer, static_cast<size_t>(aFrames),
+ mSampleRate, mOutputChannels);
+
++ if (!stillProcessing) {
++ // Enter shutdown mode. The stable-state handler will detect this
++ // and complete shutdown if the graph does not get restarted.
++ mGraphImpl->SignalMainThreadCleanup();
++ return aFrames - 1;
++ }
++
+ bool switching = false;
+ {
+ MonitorAutoLock mon(mGraphImpl->GetMonitor());
+ switching = !!NextDriver();
+ }
+
+- if (switching && stillProcessing) {
++ if (switching) {
+ // If the audio stream has not been started by the previous driver or
+ // the graph itself, keep it alive.
+ MonitorAutoLock mon(mGraphImpl->GetMonitor());
+@@ -1032,11 +1044,6 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
+ return aFrames - 1;
+ }
+
+- if (!stillProcessing) {
+- LOG(LogLevel::Debug,
+- ("Stopping audio thread for MediaStreamGraph %p", this));
+- return aFrames - 1;
+- }
+ return aFrames;
+ }
+
+diff --git dom/media/MediaStreamGraph.cpp dom/media/MediaStreamGraph.cpp
+index 3a742aafe9b2..6420e038a8fe 100644
+--- dom/media/MediaStreamGraph.cpp
++++ dom/media/MediaStreamGraph.cpp
+@@ -1193,11 +1193,13 @@ MediaStreamGraphImpl::PrepareUpdatesToMainThreadState(bool aFinalUpdate)
+ }
+ }
+
+- // Don't send the message to the main thread if it's not going to have
+- // any work to do.
+- if (aFinalUpdate ||
+- !mUpdateRunnables.IsEmpty() ||
+- !mStreamUpdates.IsEmpty()) {
++ // If this is the final update, then a stable state event will soon be
++ // posted just before this thread finishes, and so there is no need to also
++ // post here.
++ if (!aFinalUpdate &&
++ // Don't send the message to the main thread if it's not going to have
++ // any work to do.
++ !(mUpdateRunnables.IsEmpty() && mStreamUpdates.IsEmpty())) {
+ EnsureStableStateEventPosted();
+ }
+ }
+@@ -1430,12 +1432,7 @@ MediaStreamGraphImpl::UpdateMainThreadState()
+ (IsEmpty() && mBackMessageQueue.IsEmpty());
+ PrepareUpdatesToMainThreadState(finalUpdate);
+ if (finalUpdate) {
+- // Enter shutdown mode. The stable-state handler will detect this
+- // and complete shutdown. Destroy any streams immediately.
+- LOG(LogLevel::Debug,
+- ("MediaStreamGraph %p waiting for main thread cleanup", this));
+- // We'll shut down this graph object if it does not get restarted.
+- mLifecycleState = LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP;
++ // Enter shutdown mode when this iteration is completed.
+ // No need to Destroy streams here. The main-thread owner of each
+ // stream is responsible for calling Destroy on them.
+ return false;
+@@ -1861,6 +1858,19 @@ MediaStreamGraphImpl::EnsureStableStateEventPosted()
+ mAbstractMainThread->Dispatch(event.forget());
+ }
+
++void
++MediaStreamGraphImpl::SignalMainThreadCleanup()
++{
++ MOZ_ASSERT(mDriver->OnThread());
++
++ MonitorAutoLock lock(mMonitor);
++ LOG(LogLevel::Debug,
++ ("MediaStreamGraph %p waiting for main thread cleanup", this));
++ mLifecycleState =
++ MediaStreamGraphImpl::LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP;
++ EnsureStableStateEventPosted();
++}
++
+ void
+ MediaStreamGraphImpl::AppendMessage(UniquePtr<ControlMessage> aMessage)
+ {
+diff --git dom/media/MediaStreamGraphImpl.h dom/media/MediaStreamGraphImpl.h
+index dfea12bca3a8..dce49da39166 100644
+--- dom/media/MediaStreamGraphImpl.h
++++ dom/media/MediaStreamGraphImpl.h
+@@ -197,6 +197,14 @@ public:
+ */
+ bool OneIteration(GraphTime aStateEnd);
+
++ /**
++ * Called from the driver, when the graph thread is about to stop, to tell
++ * the main thread to attempt to begin cleanup. The main thread may either
++ * shutdown or revive the graph depending on whether it receives new
++ * messages.
++ */
++ void SignalMainThreadCleanup();
++
+ bool Running() const
+ {
+ mMonitor.AssertCurrentThreadOwns();
+@@ -720,7 +728,9 @@ public:
+ LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION
+ };
+ /**
+- * Modified only on the main thread in mMonitor.
++ * Modified only in mMonitor. Transitions to
++ * LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP occur on the graph thread at
++ * the end of an iteration. All other transitions occur on the main thread.
+ */
+ LifecycleState mLifecycleState;
+ /**
diff --git a/www/firefox/files/patch-bug1409951 b/www/firefox/files/patch-bug1409951
new file mode 100644
index 000000000000..22c8398360bb
--- /dev/null
+++ b/www/firefox/files/patch-bug1409951
@@ -0,0 +1,177 @@
+commit d5562dbcfd63
+Author: Henri Sivonen <hsivonen@hsivonen.fi>
+Date: Fri Dec 1 10:45:25 2017 -0500
+
+ Bug 1409951 - Use a stack to end serializer contexts instead of recomputing them. r=smaug, a=gchang
+
+ MozReview-Commit-ID: FOd8AUmtYyA
+
+ --HG--
+ extra : rebase_source : 1f02ebc32fe80591d617f27ec70094a109ead2b0
+ extra : source : b0a3a621f5c85b5e9a4eb97de77fcb2558ac17c6
+---
+ dom/base/nsDocumentEncoder.cpp | 56 +++++++++++++++++++-------------------
+ dom/base/nsPlainTextSerializer.cpp | 1 +
+ 2 files changed, 29 insertions(+), 28 deletions(-)
+
+diff --git dom/base/nsDocumentEncoder.cpp dom/base/nsDocumentEncoder.cpp
+index 5912d67da86e..2fb488750366 100644
+--- dom/base/nsDocumentEncoder.cpp
++++ dom/base/nsDocumentEncoder.cpp
+@@ -49,6 +49,7 @@
+ #include "mozilla/dom/Element.h"
+ #include "mozilla/dom/ShadowRoot.h"
+ #include "nsLayoutUtils.h"
++#include "mozilla/ScopeExit.h"
+
+ using namespace mozilla;
+ using namespace mozilla::dom;
+@@ -92,8 +93,8 @@ protected:
+ int32_t aDepth);
+ nsresult SerializeRangeContextStart(const nsTArray<nsINode*>& aAncestorArray,
+ nsAString& aString);
+- nsresult SerializeRangeContextEnd(const nsTArray<nsINode*>& aAncestorArray,
+- nsAString& aString);
++ nsresult SerializeRangeContextEnd(nsAString& aString);
++
+ virtual int32_t
+ GetImmediateContextCount(const nsTArray<nsINode*>& aAncestorArray)
+ {
+@@ -185,6 +186,7 @@ protected:
+ AutoTArray<int32_t, 8> mStartOffsets;
+ AutoTArray<nsIContent*, 8> mEndNodes;
+ AutoTArray<int32_t, 8> mEndOffsets;
++ AutoTArray<AutoTArray<nsINode*, 8>, 8> mRangeContexts;
+ // Whether the serializer cares about being notified to scan elements to
+ // keep track of whether they are preformatted. This stores the out
+ // argument of nsIContentSerializer::Init().
+@@ -874,6 +876,9 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray<nsINode*>& aAncesto
+ if (mDisableContextSerialize) {
+ return NS_OK;
+ }
++
++ AutoTArray<nsINode*, 8>* serializedContext = mRangeContexts.AppendElement();
++
+ int32_t i = aAncestorArray.Length(), j;
+ nsresult rv = NS_OK;
+
+@@ -889,7 +894,7 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray<nsINode*>& aAncesto
+ // Either a general inclusion or as immediate context
+ if (IncludeInContext(node) || i < j) {
+ rv = SerializeNodeStart(node, 0, -1, aString);
+-
++ serializedContext->AppendElement(node);
+ if (NS_FAILED(rv))
+ break;
+ }
+@@ -899,34 +904,24 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray<nsINode*>& aAncesto
+ }
+
+ nsresult
+-nsDocumentEncoder::SerializeRangeContextEnd(const nsTArray<nsINode*>& aAncestorArray,
+- nsAString& aString)
++nsDocumentEncoder::SerializeRangeContextEnd(nsAString& aString)
+ {
+ if (mDisableContextSerialize) {
+ return NS_OK;
+ }
+- int32_t i = 0, j;
+- int32_t count = aAncestorArray.Length();
+- nsresult rv = NS_OK;
+
+- // currently only for table-related elements
+- j = GetImmediateContextCount(aAncestorArray);
++ MOZ_RELEASE_ASSERT(!mRangeContexts.IsEmpty(), "Tried to end context without starting one.");
++ AutoTArray<nsINode*, 8>& serializedContext = mRangeContexts.LastElement();
+
+- while (i < count) {
+- nsINode *node = aAncestorArray.ElementAt(i++);
++ nsresult rv = NS_OK;
++ for (nsINode* node : Reversed(serializedContext)) {
++ rv = SerializeNodeEnd(node, aString);
+
+- if (!node)
++ if (NS_FAILED(rv))
+ break;
+-
+- // Either a general inclusion or as immediate context
+- if (IncludeInContext(node) || i - 1 < j) {
+- rv = SerializeNodeEnd(node, aString);
+-
+- if (NS_FAILED(rv))
+- break;
+- }
+ }
+
++ mRangeContexts.RemoveElementAt(mRangeContexts.Length() - 1);
+ return rv;
+ }
+
+@@ -992,7 +987,7 @@ nsDocumentEncoder::SerializeRangeToString(nsRange *aRange,
+ rv = SerializeRangeNodes(aRange, mCommonParent, aOutputString, 0);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+- rv = SerializeRangeContextEnd(mCommonAncestors, aOutputString);
++ rv = SerializeRangeContextEnd(aOutputString);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return rv;
+@@ -1029,6 +1024,11 @@ NS_IMETHODIMP
+ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
+ nsAString& aOutputString)
+ {
++ MOZ_ASSERT(mRangeContexts.IsEmpty(), "Re-entrant call to nsDocumentEncoder.");
++ auto rangeContextGuard = MakeScopeExit([&] {
++ mRangeContexts.Clear();
++ });
++
+ if (!mDocument)
+ return NS_ERROR_NOT_INITIALIZED;
+
+@@ -1112,10 +1112,8 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
+ prevNode = node;
+ } else if (prevNode) {
+ // Went from a <tr> to a non-<tr>
+- mCommonAncestors.Clear();
+- nsContentUtils::GetAncestors(p->GetParentNode(), mCommonAncestors);
+ mDisableContextSerialize = false;
+- rv = SerializeRangeContextEnd(mCommonAncestors, output);
++ rv = SerializeRangeContextEnd(output);
+ NS_ENSURE_SUCCESS(rv, rv);
+ prevNode = nullptr;
+ }
+@@ -1134,10 +1132,8 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
+ nsCOMPtr<nsINode> p = do_QueryInterface(prevNode);
+ rv = SerializeNodeEnd(p, output);
+ NS_ENSURE_SUCCESS(rv, rv);
+- mCommonAncestors.Clear();
+- nsContentUtils::GetAncestors(p->GetParentNode(), mCommonAncestors);
+ mDisableContextSerialize = false;
+- rv = SerializeRangeContextEnd(mCommonAncestors, output);
++ rv = SerializeRangeContextEnd(output);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+@@ -1196,6 +1192,10 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
+ NS_IMETHODIMP
+ nsDocumentEncoder::EncodeToStream(nsIOutputStream* aStream)
+ {
++ MOZ_ASSERT(mRangeContexts.IsEmpty(), "Re-entrant call to nsDocumentEncoder.");
++ auto rangeContextGuard = MakeScopeExit([&] {
++ mRangeContexts.Clear();
++ });
+ nsresult rv = NS_OK;
+
+ if (!mDocument)
+diff --git dom/base/nsPlainTextSerializer.cpp dom/base/nsPlainTextSerializer.cpp
+index 189469f73bb6..d7ddb0274be5 100644
+--- dom/base/nsPlainTextSerializer.cpp
++++ dom/base/nsPlainTextSerializer.cpp
+@@ -388,6 +388,7 @@ nsPlainTextSerializer::ScanElementForPreformat(Element* aElement)
+ NS_IMETHODIMP
+ nsPlainTextSerializer::ForgetElementForPreformat(Element* aElement)
+ {
++ MOZ_RELEASE_ASSERT(!mPreformatStack.empty(), "Tried to pop without previous push.");
+ mPreformatStack.pop();
+ return NS_OK;
+ }
diff --git a/www/firefox/files/patch-bug1410134 b/www/firefox/files/patch-bug1410134
new file mode 100644
index 000000000000..7a30e8a20fe8
--- /dev/null
+++ b/www/firefox/files/patch-bug1410134
@@ -0,0 +1,52 @@
+commit 2d5001acfa08
+Author: Tim Huang <tihuang@mozilla.com>
+Date: Tue Nov 28 14:56:55 2017 -0500
+
+ Bug 1410134 - Fix the remove-while-iterating for RemoveCookiesWithOriginAttributes. r=jdm, a=gchang
+
+ MozReview-Commit-ID: u56N4084lL
+
+ --HG--
+ extra : source : ffab26e34d92c1fc2e5103d2bad3625e180963bb
+---
+ netwerk/cookie/nsCookieService.cpp | 24 ++++++++++--------------
+ 1 file changed, 10 insertions(+), 14 deletions(-)
+
+diff --git netwerk/cookie/nsCookieService.cpp netwerk/cookie/nsCookieService.cpp
+index 7d939da101e2..0692b7088751 100644
+--- netwerk/cookie/nsCookieService.cpp
++++ netwerk/cookie/nsCookieService.cpp
+@@ -4899,23 +4899,19 @@ nsCookieService::RemoveCookiesWithOriginAttributes(
+ }
+
+ // Pattern matches. Delete all cookies within this nsCookieEntry.
+- const nsCookieEntry::ArrayType& cookies = entry->GetCookies();
++ uint32_t cookiesCount = entry->GetCookies().Length();
+
+- while (!cookies.IsEmpty()) {
+- nsCookie *cookie = cookies.LastElement();
+-
+- nsAutoCString host;
+- cookie->GetHost(host);
+-
+- nsAutoCString name;
+- cookie->GetName(name);
+-
+- nsAutoCString path;
+- cookie->GetPath(path);
++ for (nsCookieEntry::IndexType i = 0 ; i < cookiesCount; ++i) {
++ // Remove the first cookie from the list.
++ nsListIter iter(entry, 0);
++ RefPtr<nsCookie> cookie = iter.Cookie();
+
+ // Remove the cookie.
+- nsresult rv = Remove(host, entry->mOriginAttributes, name, path, false);
+- NS_ENSURE_SUCCESS(rv, rv);
++ RemoveCookieFromList(iter);
++
++ if (cookie) {
++ NotifyChanged(cookie, u"deleted");
++ }
+ }
+ }
+ DebugOnly<nsresult> rv = transaction.Commit();
diff --git a/www/firefox/files/patch-bug1412145 b/www/firefox/files/patch-bug1412145
new file mode 100644
index 000000000000..595ba7297dc9
--- /dev/null
+++ b/www/firefox/files/patch-bug1412145
@@ -0,0 +1,286 @@
+commit d83a24ce6fb3
+Author: Xidorn Quan <me@upsuper.org>
+Date: Tue Nov 28 17:06:51 2017 -0600
+
+ Bug 1412145 - Drop more backpointers of CSSOM objects in dtor and unlink. r=bz, a=gchang
+
+ MozReview-Commit-ID: Ftg3WMBBNlO
+---
+ layout/style/GroupRule.cpp | 7 +++++++
+ layout/style/GroupRule.h | 1 +
+ layout/style/MediaList.h | 4 +++-
+ layout/style/ServoCSSRuleList.cpp | 2 ++
+ layout/style/ServoKeyframeRule.cpp | 12 ++++++++++--
+ layout/style/ServoKeyframesRule.cpp | 23 ++++++++++++++++-------
+ layout/style/ServoMediaRule.cpp | 17 +++++++++++++++--
+ layout/style/ServoPageRule.cpp | 2 ++
+ layout/style/ServoStyleRule.cpp | 1 +
+ layout/style/nsCSSRules.cpp | 31 +++++++++++++++++++++++++++----
+ 10 files changed, 84 insertions(+), 16 deletions(-)
+
+diff --git layout/style/GroupRule.cpp layout/style/GroupRule.cpp
+index 28739e1818eb..32bd8c83e43a 100644
+--- layout/style/GroupRule.cpp
++++ layout/style/GroupRule.cpp
+@@ -198,6 +198,13 @@ GeckoGroupRuleRules::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
+ // ServoGroupRuleRules
+ //
+
++ServoGroupRuleRules::~ServoGroupRuleRules()
++{
++ if (mRuleList) {
++ mRuleList->DropReference();
++ }
++}
++
+ #ifdef DEBUG
+ void
+ ServoGroupRuleRules::List(FILE* out, int32_t aIndent) const
+diff --git layout/style/GroupRule.h layout/style/GroupRule.h
+index ac9e26921f0b..5c336e5c3611 100644
+--- layout/style/GroupRule.h
++++ layout/style/GroupRule.h
+@@ -87,6 +87,7 @@ struct ServoGroupRuleRules
+ // Do we ever clone Servo rules?
+ MOZ_ASSERT_UNREACHABLE("stylo: Cloning GroupRule not implemented");
+ }
++ ~ServoGroupRuleRules();
+
+ void SetParentRule(GroupRule* aParentRule) {
+ if (mRuleList) {
+diff --git layout/style/MediaList.h layout/style/MediaList.h
+index 4e8c12a2461a..b95e6ec26895 100644
+--- layout/style/MediaList.h
++++ layout/style/MediaList.h
+@@ -84,7 +84,9 @@ protected:
+ virtual nsresult Delete(const nsAString& aOldMedium) = 0;
+ virtual nsresult Append(const nsAString& aNewMedium) = 0;
+
+- virtual ~MediaList() {}
++ virtual ~MediaList() {
++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared");
++ }
+
+ // not refcounted; sheet will let us know when it goes away
+ // mStyleSheet is the sheet that needs to be dirtied when this
+diff --git layout/style/ServoCSSRuleList.cpp layout/style/ServoCSSRuleList.cpp
+index 37ce9be9f337..31f481899964 100644
+--- layout/style/ServoCSSRuleList.cpp
++++ layout/style/ServoCSSRuleList.cpp
+@@ -234,6 +234,8 @@ ServoCSSRuleList::GetDOMCSSRuleType(uint32_t aIndex) const
+
+ ServoCSSRuleList::~ServoCSSRuleList()
+ {
++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared");
++ MOZ_ASSERT(!mParentRule, "Backpointer should have been cleared");
+ DropAllRules();
+ }
+
+diff --git layout/style/ServoKeyframeRule.cpp layout/style/ServoKeyframeRule.cpp
+index 1be82c3100c5..6ca8a1815f8c 100644
+--- layout/style/ServoKeyframeRule.cpp
++++ layout/style/ServoKeyframeRule.cpp
+@@ -35,7 +35,10 @@ public:
+ return NS_OK;
+ }
+
+- void DropReference() { mRule = nullptr; }
++ void DropReference() {
++ mRule = nullptr;
++ mDecls->SetOwningRule(nullptr);
++ }
+
+ DeclarationBlock* GetCSSDeclaration(Operation aOperation) final
+ {
+@@ -81,7 +84,9 @@ public:
+ }
+
+ private:
+- virtual ~ServoKeyframeDeclaration() {}
++ virtual ~ServoKeyframeDeclaration() {
++ MOZ_ASSERT(!mRule, "Backpointer should have been cleared");
++ }
+
+ ServoKeyframeRule* mRule;
+ RefPtr<ServoDeclarationBlock> mDecls;
+@@ -102,6 +107,9 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
+
+ ServoKeyframeRule::~ServoKeyframeRule()
+ {
++ if (mDeclaration) {
++ mDeclaration->DropReference();
++ }
+ }
+
+ NS_IMPL_ADDREF_INHERITED(ServoKeyframeRule, dom::CSSKeyframeRule)
+diff --git layout/style/ServoKeyframesRule.cpp layout/style/ServoKeyframesRule.cpp
+index 9a7252a5a639..7341b954ec60 100644
+--- layout/style/ServoKeyframesRule.cpp
++++ layout/style/ServoKeyframesRule.cpp
+@@ -90,7 +90,12 @@ public:
+ {
+ mStyleSheet = nullptr;
+ mParentRule = nullptr;
+- DropAllRules();
++ for (css::Rule* rule : mRules) {
++ if (rule) {
++ rule->SetStyleSheet(nullptr);
++ rule->SetParentRule(nullptr);
++ }
++ }
+ }
+
+ size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+@@ -103,15 +108,16 @@ public:
+ }
+
+ private:
+- virtual ~ServoKeyframeList() {}
++ virtual ~ServoKeyframeList() {
++ MOZ_ASSERT(!mParentRule, "Backpointer should have been cleared");
++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared");
++ DropAllRules();
++ }
+
+ void DropAllRules()
+ {
+- for (css::Rule* rule : mRules) {
+- if (rule) {
+- rule->SetStyleSheet(nullptr);
+- rule->SetParentRule(nullptr);
+- }
++ if (mParentRule || mStyleSheet) {
++ DropReference();
+ }
+ mRules.Clear();
+ mRawRule = nullptr;
+@@ -163,6 +169,9 @@ ServoKeyframesRule::ServoKeyframesRule(RefPtr<RawServoKeyframesRule> aRawRule,
+
+ ServoKeyframesRule::~ServoKeyframesRule()
+ {
++ if (mKeyframeList) {
++ mKeyframeList->DropReference();
++ }
+ }
+
+ NS_IMPL_ADDREF_INHERITED(ServoKeyframesRule, dom::CSSKeyframesRule)
+diff --git layout/style/ServoMediaRule.cpp layout/style/ServoMediaRule.cpp
+index 002ae20ffd0b..fbda581a377f 100644
+--- layout/style/ServoMediaRule.cpp
++++ layout/style/ServoMediaRule.cpp
+@@ -24,6 +24,9 @@ ServoMediaRule::ServoMediaRule(RefPtr<RawServoMediaRule> aRawRule,
+
+ ServoMediaRule::~ServoMediaRule()
+ {
++ if (mMediaList) {
++ mMediaList->SetStyleSheet(nullptr);
++ }
+ }
+
+ NS_IMPL_ADDREF_INHERITED(ServoMediaRule, CSSMediaRule)
+@@ -33,8 +36,18 @@ NS_IMPL_RELEASE_INHERITED(ServoMediaRule, CSSMediaRule)
+ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoMediaRule)
+ NS_INTERFACE_MAP_END_INHERITING(CSSMediaRule)
+
+-NS_IMPL_CYCLE_COLLECTION_INHERITED(ServoMediaRule, CSSMediaRule,
+- mMediaList)
++NS_IMPL_CYCLE_COLLECTION_CLASS(ServoMediaRule)
++
++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoMediaRule, CSSMediaRule)
++ if (tmp->mMediaList) {
++ tmp->mMediaList->SetStyleSheet(nullptr);
++ tmp->mMediaList = nullptr;
++ }
++NS_IMPL_CYCLE_COLLECTION_UNLINK_END
++
++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoMediaRule, CSSMediaRule)
++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaList)
++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+ /* virtual */ already_AddRefed<css::Rule>
+ ServoMediaRule::Clone() const
+diff --git layout/style/ServoPageRule.cpp layout/style/ServoPageRule.cpp
+index 97c718ed1ba9..93e8ff334122 100644
+--- layout/style/ServoPageRule.cpp
++++ layout/style/ServoPageRule.cpp
+@@ -26,6 +26,7 @@ ServoPageRuleDeclaration::ServoPageRuleDeclaration(
+
+ ServoPageRuleDeclaration::~ServoPageRuleDeclaration()
+ {
++ mDecls->SetOwningRule(nullptr);
+ }
+
+ // QueryInterface implementation for ServoPageRuleDeclaration
+@@ -141,6 +142,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoPageRule, CSSPageRule)
+ // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use
+ // directly because the wrapper is on the declaration, not on us.
+ tmp->mDecls.ReleaseWrapper(static_cast<nsISupports*>(p));
++ tmp->mDecls.mDecls->SetOwningRule(nullptr);
+ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoPageRule, CSSPageRule)
+diff --git layout/style/ServoStyleRule.cpp layout/style/ServoStyleRule.cpp
+index 1d7470eef037..855e643515f9 100644
+--- layout/style/ServoStyleRule.cpp
++++ layout/style/ServoStyleRule.cpp
+@@ -28,6 +28,7 @@ ServoStyleRuleDeclaration::ServoStyleRuleDeclaration(
+
+ ServoStyleRuleDeclaration::~ServoStyleRuleDeclaration()
+ {
++ mDecls->SetOwningRule(nullptr);
+ }
+
+ // QueryInterface implementation for ServoStyleRuleDeclaration
+diff --git layout/style/nsCSSRules.cpp layout/style/nsCSSRules.cpp
+index 5081244c6a53..0bdedc4a3b03 100644
+--- layout/style/nsCSSRules.cpp
++++ layout/style/nsCSSRules.cpp
+@@ -212,12 +212,25 @@ ImportRule::~ImportRule()
+ NS_IMPL_ADDREF_INHERITED(ImportRule, CSSImportRule)
+ NS_IMPL_RELEASE_INHERITED(ImportRule, CSSImportRule)
+
+-NS_IMPL_CYCLE_COLLECTION_INHERITED(ImportRule, CSSImportRule, mMedia, mChildSheet)
+-
+ // QueryInterface implementation for ImportRule
+ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ImportRule)
+ NS_INTERFACE_MAP_END_INHERITING(CSSImportRule)
+
++NS_IMPL_CYCLE_COLLECTION_CLASS(ImportRule)
++
++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ImportRule, CSSImportRule)
++ if (tmp->mChildSheet) {
++ tmp->mChildSheet->SetOwnerRule(nullptr);
++ tmp->mChildSheet = nullptr;
++ }
++ tmp->mMedia = nullptr;
++NS_IMPL_CYCLE_COLLECTION_UNLINK_END
++
++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ImportRule, CSSImportRule)
++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMedia)
++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildSheet)
++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
++
+ #ifdef DEBUG
+ /* virtual */ void
+ ImportRule::List(FILE* out, int32_t aIndent) const
+@@ -342,8 +355,18 @@ NS_IMPL_RELEASE_INHERITED(MediaRule, CSSMediaRule)
+ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaRule)
+ NS_INTERFACE_MAP_END_INHERITING(CSSMediaRule)
+
+-NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRule, CSSMediaRule,
+- mMedia)
++NS_IMPL_CYCLE_COLLECTION_CLASS(MediaRule)
++
++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaRule, CSSMediaRule)
++ if (tmp->mMedia) {
++ tmp->mMedia->SetStyleSheet(nullptr);
++ tmp->mMedia = nullptr;
++ }
++NS_IMPL_CYCLE_COLLECTION_UNLINK_END
++
++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaRule, CSSMediaRule)
++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMedia)
++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+ /* virtual */ void
+ MediaRule::SetStyleSheet(StyleSheet* aSheet)
diff --git a/www/firefox/files/patch-bug1413741 b/www/firefox/files/patch-bug1413741
new file mode 100644
index 000000000000..28e94186d836
--- /dev/null
+++ b/www/firefox/files/patch-bug1413741
@@ -0,0 +1,25 @@
+commit bd17df85baf4
+Author: Andrea Marchesini <amarchesini@mozilla.com>
+Date: Tue Nov 14 08:18:41 2017 +0100
+
+ Bug 1413741 - Improve the use of XHR.mProxy in workers after the dispatching of sync OpenRunnable, r=smaug a=gchang
+
+ --HG--
+ extra : source : 063022b93ec40d00601a21b92525a4285f984484
+---
+ dom/xhr/XMLHttpRequestWorker.cpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git dom/xhr/XMLHttpRequestWorker.cpp dom/xhr/XMLHttpRequestWorker.cpp
+index c337bb258767..9954da23493f 100644
+--- dom/xhr/XMLHttpRequestWorker.cpp
++++ dom/xhr/XMLHttpRequestWorker.cpp
+@@ -1895,7 +1895,7 @@ XMLHttpRequestWorker::Open(const nsACString& aMethod,
+ ++mProxy->mOpenCount;
+ runnable->Dispatch(Terminating, aRv);
+ if (aRv.Failed()) {
+- if (!--mProxy->mOpenCount) {
++ if (mProxy && !--mProxy->mOpenCount) {
+ ReleaseProxy();
+ }
+
diff --git a/www/firefox/files/patch-bug1414425 b/www/firefox/files/patch-bug1414425
new file mode 100644
index 000000000000..4ae66b3a662a
--- /dev/null
+++ b/www/firefox/files/patch-bug1414425
@@ -0,0 +1,231 @@
+commit 8dce7d3eb6a3
+Author: Valentin Gosu <valentin.gosu@gmail.com>
+Date: Thu Nov 9 16:32:51 2017 +0100
+
+ Bug 1414425 - Make sure the appropriate triggeringPrincipal is set for a meta refresh. r=bz, a=gchang
+
+ MozReview-Commit-ID: 4Kn6P4hnx74
+
+ --HG--
+ extra : source : 229546747cbf04cf71a235275d7c2eb2520a298b
+---
+ browser/base/content/tab-content.js | 2 +-
+ .../content/test/general/browser_refreshBlocker.js | 2 +-
+ docshell/base/nsDocShell.cpp | 28 +++++++++++++++-------
+ docshell/base/nsDocShell.h | 12 +++++++---
+ docshell/base/nsIRefreshURI.idl | 23 ++++++++++++++----
+ 5 files changed, 50 insertions(+), 17 deletions(-)
+
+diff --git browser/base/content/tab-content.js browser/base/content/tab-content.js
+index 4d85ada0321b..5497a1cc208d 100644
+--- browser/base/content/tab-content.js
++++ browser/base/content/tab-content.js
+@@ -995,7 +995,7 @@ var RefreshBlocker = {
+
+ let URI = Services.io.newURI(data.URI);
+
+- refreshURI.forceRefreshURI(URI, data.delay, true);
++ refreshURI.forceRefreshURI(URI, null, data.delay, true);
+ }
+ },
+
+diff --git browser/base/content/test/general/browser_refreshBlocker.js browser/base/content/test/general/browser_refreshBlocker.js
+index cd82cf40b479..4a280d4cb12b 100644
+--- browser/base/content/test/general/browser_refreshBlocker.js
++++ browser/base/content/test/general/browser_refreshBlocker.js
+@@ -20,7 +20,7 @@ async function attemptFakeRefresh(browser, expectRefresh) {
+ await ContentTask.spawn(browser, expectRefresh, async function(contentExpectRefresh) {
+ let URI = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;
+ let refresher = docShell.QueryInterface(Ci.nsIRefreshURI);
+- refresher.refreshURI(URI, 0, false, true);
++ refresher.refreshURI(URI, null, 0, false, true);
+
+ Assert.equal(refresher.refreshPending, contentExpectRefresh,
+ "Got the right refreshPending state");
+diff --git docshell/base/nsDocShell.cpp docshell/base/nsDocShell.cpp
+index 3ded70a66fe8..83cb87dd8255 100644
+--- docshell/base/nsDocShell.cpp
++++ docshell/base/nsDocShell.cpp
+@@ -6831,7 +6831,8 @@ nsDocShell::ScrollByPages(int32_t aNumPages)
+ //*****************************************************************************
+
+ NS_IMETHODIMP
+-nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat,
++nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal,
++ int32_t aDelay, bool aRepeat,
+ bool aMetaRefresh)
+ {
+ NS_ENSURE_ARG(aURI);
+@@ -6860,7 +6861,7 @@ nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat,
+ }
+
+ nsCOMPtr<nsITimerCallback> refreshTimer =
+- new nsRefreshTimer(this, aURI, aDelay, aRepeat, aMetaRefresh);
++ new nsRefreshTimer(this, aURI, aPrincipal, aDelay, aRepeat, aMetaRefresh);
+
+ uint32_t busyFlags = 0;
+ GetBusyFlags(&busyFlags);
+@@ -6891,6 +6892,7 @@ nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat,
+
+ nsresult
+ nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
++ nsIPrincipal* aPrincipal,
+ int32_t aDelay,
+ bool aMetaRefresh,
+ nsITimer* aTimer)
+@@ -6911,11 +6913,11 @@ nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
+ }
+ }
+
+- return ForceRefreshURI(aURI, aDelay, aMetaRefresh);
++ return ForceRefreshURI(aURI, aPrincipal, aDelay, aMetaRefresh);
+ }
+
+ NS_IMETHODIMP
+-nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh)
++nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDelay, bool aMetaRefresh)
+ {
+ NS_ENSURE_ARG(aURI);
+
+@@ -6963,6 +6965,13 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh)
+ loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
+ }
+
++ // If the principal is null, the refresh will have a triggeringPrincipal
++ // derived from the referrer URI, or will be set to the system principal
++ // if there is no refererrer. See LoadURI()
++ if (aPrincipal) {
++ loadInfo->SetTriggeringPrincipal(aPrincipal);
++ }
++
+ /*
+ * LoadURI(...) will cancel all refresh timers... This causes the
+ * Timer and its refreshData instance to be released...
+@@ -7203,7 +7212,7 @@ nsDocShell::SetupRefreshURIFromHeader(nsIURI* aBaseURI,
+ return NS_ERROR_FAILURE;
+ }
+
+- rv = RefreshURI(uri, seconds * 1000, false, true);
++ rv = RefreshURI(uri, aPrincipal, seconds * 1000, false, true);
+ }
+ }
+ }
+@@ -13793,9 +13802,12 @@ nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState)
+ return NS_OK;
+ }
+
+-nsRefreshTimer::nsRefreshTimer(nsDocShell* aDocShell, nsIURI* aURI,
++nsRefreshTimer::nsRefreshTimer(nsDocShell* aDocShell,
++ nsIURI* aURI,
++ nsIPrincipal* aPrincipal,
+ int32_t aDelay, bool aRepeat, bool aMetaRefresh)
+- : mDocShell(aDocShell), mURI(aURI), mDelay(aDelay), mRepeat(aRepeat),
++ : mDocShell(aDocShell), mURI(aURI), mPrincipal(aPrincipal),
++ mDelay(aDelay), mRepeat(aRepeat),
+ mMetaRefresh(aMetaRefresh)
+ {
+ }
+@@ -13822,7 +13834,7 @@ nsRefreshTimer::Notify(nsITimer* aTimer)
+ // Get the delay count to determine load type
+ uint32_t delay = 0;
+ aTimer->GetDelay(&delay);
+- mDocShell->ForceRefreshURIFromTimer(mURI, delay, mMetaRefresh, aTimer);
++ mDocShell->ForceRefreshURIFromTimer(mURI, mPrincipal, delay, mMetaRefresh, aTimer);
+ }
+ return NS_OK;
+ }
+diff --git docshell/base/nsDocShell.h docshell/base/nsDocShell.h
+index f805deaa2edf..57fc63fe5795 100644
+--- docshell/base/nsDocShell.h
++++ docshell/base/nsDocShell.h
+@@ -114,8 +114,12 @@ class nsRefreshTimer : public nsITimerCallback
+ , public nsINamed
+ {
+ public:
+- nsRefreshTimer(nsDocShell* aDocShell, nsIURI* aURI, int32_t aDelay,
+- bool aRepeat, bool aMetaRefresh);
++ nsRefreshTimer(nsDocShell* aDocShell,
++ nsIURI* aURI,
++ nsIPrincipal* aPrincipal,
++ int32_t aDelay,
++ bool aRepeat,
++ bool aMetaRefresh);
+
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSITIMERCALLBACK
+@@ -125,6 +129,7 @@ public:
+
+ RefPtr<nsDocShell> mDocShell;
+ nsCOMPtr<nsIURI> mURI;
++ nsCOMPtr<nsIPrincipal> mPrincipal;
+ int32_t mDelay;
+ bool mRepeat;
+ bool mMetaRefresh;
+@@ -259,7 +264,8 @@ public:
+ // ForceRefreshURI method on nsIRefreshURI, but makes sure to take
+ // the timer involved out of mRefreshURIList if it's there.
+ // aTimer must not be null.
+- nsresult ForceRefreshURIFromTimer(nsIURI* aURI, int32_t aDelay,
++ nsresult ForceRefreshURIFromTimer(nsIURI* aURI, nsIPrincipal* aPrincipal,
++ int32_t aDelay,
+ bool aMetaRefresh, nsITimer* aTimer);
+
+ friend class OnLinkClickEvent;
+diff --git docshell/base/nsIRefreshURI.idl docshell/base/nsIRefreshURI.idl
+index f872d8b7f5cf..3e85e4c516c6 100644
+--- docshell/base/nsIRefreshURI.idl
++++ docshell/base/nsIRefreshURI.idl
+@@ -18,23 +18,33 @@ interface nsIRefreshURI : nsISupports {
+ * queued and executed when the current load finishes.
+ *
+ * @param aUri The uri to refresh.
++ * @param aPrincipal The triggeringPrincipal for the refresh load
++ * May be null, in which case a principal will be built based on the
++ * referrer URI of the previous docshell load, or will use the system
++ * principal when there is no referrer.
+ * @param aMillis The number of milliseconds to wait.
+ * @param aRepeat Flag to indicate if the uri is to be
+ * repeatedly refreshed every aMillis milliseconds.
+ * @param aMetaRefresh Flag to indicate if this is a Meta refresh.
+ */
+- void refreshURI(in nsIURI aURI, in long aMillis, in boolean aRepeat,
++ void refreshURI(in nsIURI aURI, in nsIPrincipal aPrincipal,
++ in long aMillis, in boolean aRepeat,
+ in boolean aMetaRefresh);
+
+ /**
+ * Loads a URI immediately as if it were a refresh.
+ *
+ * @param aURI The URI to refresh.
++ * @param aPrincipal The triggeringPrincipal for the refresh load
++ * May be null, in which case a principal will be built based on the
++ * referrer URI of the previous docshell load, or will use the system
++ * principal when there is no referrer.
+ * @param aMillis The number of milliseconds by which this refresh would
+ * be delayed if it were not being forced.
+ * @param aMetaRefresh Flag to indicate if this is a meta refresh.
+ */
+- void forceRefreshURI(in nsIURI aURI, in long aMillis, in boolean aMetaRefresh);
++ void forceRefreshURI(in nsIURI aURI, in nsIPrincipal aPrincipal,
++ in long aMillis, in boolean aMetaRefresh);
+
+ /**
+ * Checks the passed in channel to see if there is a refresh header,
+@@ -57,10 +67,15 @@ interface nsIRefreshURI : nsISupports {
+ * the current page finishes loading.
+ *
+ * @param aBaseURI base URI to resolve refresh uri with.
+- * @param principal the associated principal
++ * @param aPrincipal The triggeringPrincipal for the refresh load
++ * May be null, in which case a principal will be built based on the
++ * referrer URI of the previous docshell load, or will use the system
++ * principal when there is no referrer.
+ * @param aHeader The meta refresh header string.
+ */
+- void setupRefreshURIFromHeader(in nsIURI aBaseURI, in nsIPrincipal principal, in ACString aHeader);
++ void setupRefreshURIFromHeader(in nsIURI aBaseURI,
++ in nsIPrincipal principal,
++ in ACString aHeader);
+
+ /**
+ * Cancels all timer loads.
diff --git a/www/firefox/files/patch-bug1414452 b/www/firefox/files/patch-bug1414452
new file mode 100644
index 000000000000..695ea3e848a9
--- /dev/null
+++ b/www/firefox/files/patch-bug1414452
@@ -0,0 +1,70 @@
+commit 24a8b8309514
+Author: Olli Pettay <Olli.Pettay@helsinki.fi>
+Date: Tue Nov 28 16:17:17 2017 +0200
+
+ Bug 1414452 - Clear dirAutoSetBy properties iteratively. r=peterv, a=abillings
+
+ --HG--
+ extra : source : 157a15cd5ecc8706b502f78c51e79b58ac59eaf0
+---
+ dom/base/DirectionalityUtils.cpp | 23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+diff --git dom/base/DirectionalityUtils.cpp dom/base/DirectionalityUtils.cpp
+index fb443e23688c..f132c8970fe7 100644
+--- dom/base/DirectionalityUtils.cpp
++++ dom/base/DirectionalityUtils.cpp
+@@ -419,7 +419,7 @@ class nsTextNodeDirectionalityMap
+
+ nsTextNodeDirectionalityMap* map =
+ reinterpret_cast<nsTextNodeDirectionalityMap * >(aPropertyValue);
+- map->EnsureMapIsClear(textNode);
++ map->EnsureMapIsClear();
+ delete map;
+ }
+
+@@ -548,11 +548,11 @@ private:
+ return OpRemove;
+ }
+
+- static nsCheapSetOperator ClearEntry(nsPtrHashKey<Element>* aEntry, void* aData)
++ static nsCheapSetOperator TakeEntries(nsPtrHashKey<Element>* aEntry, void* aData)
+ {
+- Element* rootNode = aEntry->GetKey();
+- rootNode->ClearHasDirAutoSet();
+- rootNode->DeleteProperty(nsGkAtoms::dirAutoSetBy);
++ AutoTArray<Element*, 8>* entries =
++ static_cast<AutoTArray<Element*, 8>*>(aData);
++ entries->AppendElement(aEntry->GetKey());
+ return OpRemove;
+ }
+
+@@ -568,12 +568,15 @@ public:
+ mElements.EnumerateEntries(ResetNodeDirection, &data);
+ }
+
+- void EnsureMapIsClear(nsINode* aTextNode)
++ void EnsureMapIsClear()
+ {
+ AutoRestore<Element*> restore(mElementToBeRemoved);
+- DebugOnly<uint32_t> clearedEntries =
+- mElements.EnumerateEntries(ClearEntry, aTextNode);
+- MOZ_ASSERT(clearedEntries == 0, "Map should be empty already");
++ AutoTArray<Element*, 8> entries;
++ mElements.EnumerateEntries(TakeEntries, &entries);
++ for (Element* el : entries) {
++ el->ClearHasDirAutoSet();
++ el->DeleteProperty(nsGkAtoms::dirAutoSetBy);
++ }
+ }
+
+ static void RemoveElementFromMap(nsTextNode* aTextNode, Element* aElement)
+@@ -613,7 +616,7 @@ public:
+ static void EnsureMapIsClearFor(nsINode* aTextNode)
+ {
+ if (aTextNode->HasTextNodeDirectionalityMap()) {
+- GetDirectionalityMap(aTextNode)->EnsureMapIsClear(aTextNode);
++ GetDirectionalityMap(aTextNode)->EnsureMapIsClear();
+ }
+ }
+ };
diff --git a/www/firefox/files/patch-bug1414945 b/www/firefox/files/patch-bug1414945
new file mode 100644
index 000000000000..3b57e971dc90
--- /dev/null
+++ b/www/firefox/files/patch-bug1414945
@@ -0,0 +1,43 @@
+commit 26740772e0c9
+Author: Philip Chimento <philip.chimento@gmail.com>
+Date: Mon Nov 6 15:49:15 2017 -0800
+
+ Bug 1414945 - Don't use TimeDuration in static initializer. r=jandem
+
+ On Darwin this would cause a race between two static initializers.
+
+ --HG--
+ extra : rebase_source : 0547c4018334f7112022f1893c5f36a47dc14501
+---
+ js/src/shell/js.cpp | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git js/src/shell/js.cpp js/src/shell/js.cpp
+index afb4990ecc0f..f8f81446c7ae 100644
+--- js/src/shell/js.cpp
++++ js/src/shell/js.cpp
+@@ -150,7 +150,7 @@ static const size_t gMaxStackSize = 128 * sizeof(size_t) * 1024;
+ * Limit the timeout to 30 minutes to prevent an overflow on platfoms
+ * that represent the time internally in microseconds using 32-bit int.
+ */
+-static const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(1800.0);
++static const double MAX_TIMEOUT_SECONDS = 1800.0;
+
+ // SharedArrayBuffer and Atomics are enabled by default (tracking Firefox).
+ #define SHARED_MEMORY_DEFAULT 1
+@@ -3852,6 +3852,7 @@ Sleep_fn(JSContext* cx, unsigned argc, Value* vp)
+ }
+
+ duration = TimeDuration::FromSeconds(Max(0.0, t_secs));
++ const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(MAX_TIMEOUT_SECONDS);
+ if (duration > MAX_TIMEOUT_INTERVAL) {
+ JS_ReportErrorASCII(cx, "Excessive sleep interval");
+ return false;
+@@ -4019,6 +4020,7 @@ SetTimeoutValue(JSContext* cx, double t)
+ JS_ReportErrorASCII(cx, "timeout is not a number");
+ return false;
+ }
++ const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(MAX_TIMEOUT_SECONDS);
+ if (TimeDuration::FromSeconds(t) > MAX_TIMEOUT_INTERVAL) {
+ JS_ReportErrorASCII(cx, "Excessive timeout value");
+ return false;
diff --git a/www/firefox/files/patch-bug1415441 b/www/firefox/files/patch-bug1415441
new file mode 100644
index 000000000000..c51fed60cfea
--- /dev/null
+++ b/www/firefox/files/patch-bug1415441
@@ -0,0 +1,22 @@
+commit 8b02d6d479da
+Author: JW Wang <jwwang@mozilla.com>
+Date: Fri Dec 8 10:01:18 2017 +0800
+
+ Bug 1415441 - Eagerly init gMediaDecoderLog to debug crash. r=cpearce, a=jcristau
+---
+ dom/media/MediaDecoder.cpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git dom/media/MediaDecoder.cpp dom/media/MediaDecoder.cpp
+index cbf97ddf084d..5de31894d9d9 100644
+--- dom/media/MediaDecoder.cpp
++++ dom/media/MediaDecoder.cpp
+@@ -280,6 +280,8 @@ void
+ MediaDecoder::InitStatics()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
++ // Eagerly init gMediaDecoderLog to work around bug 1415441.
++ MOZ_LOG(gMediaDecoderLog, LogLevel::Info, ("MediaDecoder::InitStatics"));
+ }
+
+ NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
diff --git a/www/firefox/files/patch-bug1415582 b/www/firefox/files/patch-bug1415582
new file mode 100644
index 000000000000..47faa0eb70d1
--- /dev/null
+++ b/www/firefox/files/patch-bug1415582
@@ -0,0 +1,34 @@
+commit 1ab98367b3c1
+Author: Randell Jesup <rjesup@jesup.org>
+Date: Wed Nov 8 11:00:24 2017 -0500
+
+ Bug 1415582 - Mirror changes done to Encoder InitDone to decoder. r=bwc, a=gchang
+
+ --HG--
+ extra : source : 833205c1f498bed137fb2e0a06d14ef31e3c0609
+---
+ media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
+index b8067a278f18..50189c488df1 100644
+--- media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
++++ media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h
+@@ -449,7 +449,7 @@ private:
+ class InitDoneCallback : public GetGMPVideoDecoderCallback
+ {
+ public:
+- explicit InitDoneCallback(WebrtcGmpVideoDecoder* aDecoder,
++ explicit InitDoneCallback(const RefPtr<WebrtcGmpVideoDecoder>& aDecoder,
+ const RefPtr<GmpInitDoneRunnable>& aInitDone)
+ : mDecoder(aDecoder),
+ mInitDone(aInitDone)
+@@ -465,7 +465,7 @@ private:
+ }
+
+ private:
+- WebrtcGmpVideoDecoder* mDecoder;
++ RefPtr<WebrtcGmpVideoDecoder> mDecoder;
+ RefPtr<GmpInitDoneRunnable> mInitDone;
+ };
+
diff --git a/www/firefox/files/patch-bug1415598 b/www/firefox/files/patch-bug1415598
new file mode 100644
index 000000000000..6fd819610ca9
--- /dev/null
+++ b/www/firefox/files/patch-bug1415598
@@ -0,0 +1,58 @@
+commit 63db080ae5cb
+Author: Marco Bonardo <mbonardo@mozilla.com>
+Date: Thu Dec 7 15:28:41 2017 +0100
+
+ Bug 1415598. r=gijs, a=jcristau
+
+ --HG--
+ extra : source : 94f1fb1043a81e619d7b73d48a86d66d1cf4eebc
+---
+ toolkit/components/places/History.cpp | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git toolkit/components/places/History.cpp toolkit/components/places/History.cpp
+index 94755d3bdde5..b3618c065601 100644
+--- toolkit/components/places/History.cpp
++++ toolkit/components/places/History.cpp
+@@ -1955,6 +1955,7 @@ History::InitMemoryReporter()
+ NS_IMETHODIMP
+ History::NotifyVisited(nsIURI* aURI)
+ {
++ MOZ_ASSERT(NS_IsMainThread());
+ NS_ENSURE_ARG(aURI);
+
+ nsAutoScriptBlocker scriptBlocker;
+@@ -2565,6 +2566,7 @@ NS_IMETHODIMP
+ History::RegisterVisitedCallback(nsIURI* aURI,
+ Link* aLink)
+ {
++ MOZ_ASSERT(NS_IsMainThread());
+ NS_ASSERTION(aURI, "Must pass a non-null URI!");
+ if (XRE_IsContentProcess()) {
+ NS_PRECONDITION(aLink, "Must pass a non-null Link!");
+@@ -2594,7 +2596,16 @@ History::RegisterVisitedCallback(nsIURI* aURI,
+ if (NS_FAILED(rv) || !aLink) {
+ // Remove our array from the hashtable so we don't keep it around.
+ MOZ_ASSERT(key == mObservers.GetEntry(aURI), "The URIs hash mutated!");
+- mObservers.RemoveEntry(key);
++ // In some case calling RemoveEntry on the key obtained by PutEntry
++ // crashes for currently unknown reasons. Our suspect is that something
++ // between PutEntry and this call causes a nested loop that either removes
++ // the entry or reallocs the hash.
++ // TODO (Bug 1412647): we must figure the root cause for these issues and
++ // remove this stop-gap crash fix.
++ key = mObservers.GetEntry(aURI);
++ if (key) {
++ mObservers.RemoveEntry(key);
++ }
+ return rv;
+ }
+ }
+@@ -2626,6 +2637,7 @@ NS_IMETHODIMP
+ History::UnregisterVisitedCallback(nsIURI* aURI,
+ Link* aLink)
+ {
++ MOZ_ASSERT(NS_IsMainThread());
+ // TODO: aURI is sometimes null - see bug 548685
+ NS_ASSERTION(aURI, "Must pass a non-null URI!");
+ NS_ASSERTION(aLink, "Must pass a non-null Link object!");
diff --git a/www/firefox/files/patch-bug1417797 b/www/firefox/files/patch-bug1417797
new file mode 100644
index 000000000000..e3e1fc5d44a3
--- /dev/null
+++ b/www/firefox/files/patch-bug1417797
@@ -0,0 +1,25 @@
+commit 95077ef89979
+Author: Dan Minor <dminor@mozilla.com>
+Date: Mon Nov 20 07:09:19 2017 -0500
+
+ Bug 1417797 - Stop callback in WebrtcGmpVideoDecoder::ReleaseGmp. r=jesup, a=gchang
+
+ --HG--
+ extra : source : d0eb2fe1a7389d40d1abdccbeeaef9c4b30ae7b1
+---
+ media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
+index 53212d888dcb..e3063ea3fefb 100644
+--- media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
++++ media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp
+@@ -923,6 +923,8 @@ int32_t
+ WebrtcGmpVideoDecoder::ReleaseGmp()
+ {
+ LOGD(("GMP Released:"));
++ RegisterDecodeCompleteCallback(nullptr);
++
+ if (mGMPThread) {
+ mGMPThread->Dispatch(
+ WrapRunnableNM(&WebrtcGmpVideoDecoder::ReleaseGmp_g,
diff --git a/www/firefox/files/patch-bug1418447 b/www/firefox/files/patch-bug1418447
new file mode 100644
index 000000000000..87a08fef5b66
--- /dev/null
+++ b/www/firefox/files/patch-bug1418447
@@ -0,0 +1,26 @@
+commit 69f7bf805f94
+Author: Lee Salzman <lsalzman@mozilla.com>
+Date: Tue Nov 21 16:55:20 2017 -0500
+
+ Bug 1418447 - Limit Skia edge builder allocations. r=milan, a=abillings
+
+ MozReview-Commit-ID: 1SnxwtoYJJm
+
+ --HG--
+ extra : source : a81b848ebcc668f10a73eff586cebed570533b48
+---
+ gfx/skia/skia/src/core/SkEdgeBuilder.cpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git gfx/skia/skia/src/core/SkEdgeBuilder.cpp gfx/skia/skia/src/core/SkEdgeBuilder.cpp
+index ceb8f1ad3105..af8da00a2f04 100644
+--- gfx/skia/skia/src/core/SkEdgeBuilder.cpp
++++ gfx/skia/skia/src/core/SkEdgeBuilder.cpp
+@@ -248,6 +248,7 @@ int SkEdgeBuilder::buildPoly(const SkPath& path, const SkIRect* iclip, int shift
+ // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since
+ // we turn portions that are clipped out on the left/right into vertical
+ // segments.
++ SkASSERT_RELEASE(maxEdgeCount <= std::numeric_limits<int>::max() / SkLineClipper::kMaxClippedLineSegments);
+ maxEdgeCount *= SkLineClipper::kMaxClippedLineSegments;
+ }
+
diff --git a/www/firefox/files/patch-bug1418854 b/www/firefox/files/patch-bug1418854
new file mode 100644
index 000000000000..e707d06094ac
--- /dev/null
+++ b/www/firefox/files/patch-bug1418854
@@ -0,0 +1,102 @@
+commit 1fe2b37624d6
+Author: Michal Novotny <michal.novotny@gmail.com>
+Date: Wed Dec 6 20:48:06 2017 -0500
+
+ Bug 1418854 - Race condition in AutoClose. r=honzab, a=jcristau
+
+ --HG--
+ extra : source : 3e425d2e71df08dc944a26eaa41158522a75ff02
+---
+ netwerk/base/AutoClose.h | 43 ++++++++++++++++++++++---------------------
+ 1 file changed, 22 insertions(+), 21 deletions(-)
+
+diff --git netwerk/base/AutoClose.h netwerk/base/AutoClose.h
+index 8c401071428f..43ab27133fdd 100644
+--- netwerk/base/AutoClose.h
++++ netwerk/base/AutoClose.h
+@@ -8,6 +8,7 @@
+ #define mozilla_net_AutoClose_h
+
+ #include "nsCOMPtr.h"
++#include "mozilla/Mutex.h"
+
+ namespace mozilla { namespace net {
+
+@@ -18,49 +19,48 @@ template <typename T>
+ class AutoClose
+ {
+ public:
+- AutoClose() { }
++ AutoClose() : mMutex("net::AutoClose.mMutex") { }
+ ~AutoClose(){
+- Close();
++ CloseAndRelease();
+ }
+
+- explicit operator bool() const
++ explicit operator bool()
+ {
++ MutexAutoLock lock(mMutex);
+ return mPtr;
+ }
+
+ already_AddRefed<T> forget()
+ {
++ MutexAutoLock lock(mMutex);
+ return mPtr.forget();
+ }
+
+ void takeOver(nsCOMPtr<T> & rhs)
+ {
+- Close();
+- mPtr = rhs.forget();
+- }
+-
+- void takeOver(AutoClose<T> & rhs)
+- {
+- Close();
+- mPtr = rhs.mPtr.forget();
++ already_AddRefed<T> other = rhs.forget();
++ TakeOverInternal(&other);
+ }
+
+ void CloseAndRelease()
+ {
+- Close();
+- mPtr = nullptr;
+- }
+-
+- T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
+- {
+- return mPtr.operator->();
++ TakeOverInternal(nullptr);
+ }
+
+ private:
+- void Close()
++ void TakeOverInternal(already_AddRefed<T> *aOther)
+ {
+- if (mPtr) {
+- mPtr->Close();
++ nsCOMPtr<T> ptr;
++ {
++ MutexAutoLock lock(mMutex);
++ ptr.swap(mPtr);
++ if (aOther) {
++ mPtr = *aOther;
++ }
++ }
++
++ if (ptr) {
++ ptr->Close();
+ }
+ }
+
+@@ -68,6 +68,7 @@ private:
+ AutoClose(const AutoClose<T> &) = delete;
+
+ nsCOMPtr<T> mPtr;
++ Mutex mMutex;
+ };
+
+ } // namespace net
diff --git a/www/firefox/files/patch-bug1419363 b/www/firefox/files/patch-bug1419363
new file mode 100644
index 000000000000..e80b3cd55f6b
--- /dev/null
+++ b/www/firefox/files/patch-bug1419363
@@ -0,0 +1,32 @@
+commit 2eda8f3435d6
+Author: Andreas Pehrson <pehrsons@mozilla.com>
+Date: Fri Dec 1 10:52:18 2017 -0500
+
+ Bug 1419363 - Switch to WeakPtr. r=jib a=gchang
+
+ --HG--
+ extra : source : e0a21cc26e07b19383d2bf5038b88eed211de53e
+---
+ dom/html/HTMLMediaElement.cpp | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git dom/html/HTMLMediaElement.cpp dom/html/HTMLMediaElement.cpp
+index 12ea373e8782..285a36400ad9 100644
+--- dom/html/HTMLMediaElement.cpp
++++ dom/html/HTMLMediaElement.cpp
+@@ -5168,11 +5168,14 @@ public:
+ {
+ NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
+
++ if (!mElement) {
++ return;
++ }
+ mElement->NotifyMediaStreamTracksAvailable(aStream);
+ }
+
+ private:
+- HTMLMediaElement* mElement;
++ WeakPtr<HTMLMediaElement> mElement;
+ };
+
+ class HTMLMediaElement::MediaStreamTrackListener :
diff --git a/www/firefox/files/patch-bug1422389 b/www/firefox/files/patch-bug1422389
new file mode 100644
index 000000000000..07096fca06db
--- /dev/null
+++ b/www/firefox/files/patch-bug1422389
@@ -0,0 +1,28 @@
+commit 25e68494fad3
+Author: Jan-Ivar Bruaroey <jib@mozilla.com>
+Date: Fri Dec 1 20:49:46 2017 -0500
+
+ Bug 1422389 - Limit default engine resolution. r=mchiang, a=abillings
+
+ MozReview-Commit-ID: LS1z7I4myeb
+
+ --HG--
+ extra : rebase_source : 200216163b4555ede8912e64871eea81eb8affac
+ extra : source : f0fd6e20a13d11660a5ac57e9703f09978f12acb
+---
+ dom/media/webrtc/MediaEngineDefault.cpp | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git dom/media/webrtc/MediaEngineDefault.cpp dom/media/webrtc/MediaEngineDefault.cpp
+index ea5996e92e23..01efb04b5df8 100644
+--- dom/media/webrtc/MediaEngineDefault.cpp
++++ dom/media/webrtc/MediaEngineDefault.cpp
+@@ -120,6 +120,8 @@ MediaEngineDefaultVideoSource::Allocate(const dom::MediaTrackConstraints &aConst
+ MediaEngine::DEFAULT_43_VIDEO_HEIGHT
+ #endif
+ );
++ mOpts.mWidth = std::max(160, std::min(mOpts.mWidth, 4096));
++ mOpts.mHeight = std::max(90, std::min(mOpts.mHeight, 2160));
+ mState = kAllocated;
+ *aOutHandle = nullptr;
+ return NS_OK;
diff --git a/www/firefox/files/patch-bug1423086 b/www/firefox/files/patch-bug1423086
new file mode 100644
index 000000000000..123fb66344b6
--- /dev/null
+++ b/www/firefox/files/patch-bug1423086
@@ -0,0 +1,222 @@
+commit 96370abe22e4
+Author: Byron Campen [:bwc] <docfaraday@gmail.com>
+Date: Mon Dec 18 12:36:23 2017 -0600
+
+ Bug 1423086: (beta backport) Use nsITimerCallback for DTMF timers. r=drno a=ritu
+
+ MozReview-Commit-ID: 2IlDknNhlAG
+
+ --HG--
+ extra : rebase_source : 344b2b1b10084099a37fb793fc25b71144a4428c
+---
+ .../src/peerconnection/PeerConnectionImpl.cpp | 72 +++++++++++-----------
+ .../src/peerconnection/PeerConnectionImpl.h | 28 +++++----
+ 2 files changed, 51 insertions(+), 49 deletions(-)
+
+diff --git media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+index 68949feb7254..edb07486b45a 100644
+--- media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
++++ media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+@@ -2521,8 +2521,8 @@ PeerConnectionImpl::RemoveTrack(MediaStreamTrack& aTrack) {
+ nsString wideTrackId;
+ aTrack.GetId(wideTrackId);
+ for (size_t i = 0; i < mDTMFStates.Length(); ++i) {
+- if (mDTMFStates[i].mTrackId == wideTrackId) {
+- mDTMFStates[i].mSendTimer->Cancel();
++ if (mDTMFStates[i]->mTrackId == wideTrackId) {
++ mDTMFStates[i]->mSendTimer->Cancel();
+ mDTMFStates.RemoveElementAt(i);
+ break;
+ }
+@@ -2593,17 +2593,17 @@ PeerConnectionImpl::InsertDTMF(mozilla::dom::RTCRtpSender& sender,
+ mst->GetId(senderTrackId);
+
+ // Attempt to locate state for the DTMFSender
+- DTMFState* state = nullptr;
++ RefPtr<DTMFState> state;
+ for (auto& dtmfState : mDTMFStates) {
+- if (dtmfState.mTrackId == senderTrackId) {
+- state = &dtmfState;
++ if (dtmfState->mTrackId == senderTrackId) {
++ state = dtmfState;
+ break;
+ }
+ }
+
+ // No state yet, create a new one
+ if (!state) {
+- state = mDTMFStates.AppendElement();
++ state = *mDTMFStates.AppendElement(new DTMFState);
+ state->mPeerConnectionImpl = this;
+ state->mTrackId = senderTrackId;
+ state->mSendTimer = NS_NewTimer();
+@@ -2627,9 +2627,7 @@ PeerConnectionImpl::InsertDTMF(mozilla::dom::RTCRtpSender& sender,
+ state->mDuration = duration;
+ state->mInterToneGap = interToneGap;
+ if (!state->mTones.IsEmpty()) {
+- state->mSendTimer->InitWithNamedFuncCallback(DTMFSendTimerCallback_m, state, 0,
+- nsITimer::TYPE_ONE_SHOT,
+- "DTMFSendTimerCallback_m");
++ state->mSendTimer->InitWithCallback(state, 0, nsITimer::TYPE_ONE_SHOT);
+ }
+ return NS_OK;
+ }
+@@ -2653,8 +2651,8 @@ PeerConnectionImpl::GetDTMFToneBuffer(mozilla::dom::RTCRtpSender& sender,
+
+ // Attempt to locate state for the DTMFSender
+ for (auto& dtmfState : mDTMFStates) {
+- if (dtmfState.mTrackId == senderTrackId) {
+- outToneBuffer = dtmfState.mTones;
++ if (dtmfState->mTrackId == senderTrackId) {
++ outToneBuffer = dtmfState->mTones;
+ break;
+ }
+ }
+@@ -2671,8 +2669,8 @@ PeerConnectionImpl::ReplaceTrack(MediaStreamTrack& aThisTrack,
+ aThisTrack.GetId(trackId);
+
+ for (size_t i = 0; i < mDTMFStates.Length(); ++i) {
+- if (mDTMFStates[i].mTrackId == trackId) {
+- mDTMFStates[i].mSendTimer->Cancel();
++ if (mDTMFStates[i]->mTrackId == trackId) {
++ mDTMFStates[i]->mSendTimer->Cancel();
+ mDTMFStates.RemoveElementAt(i);
+ break;
+ }
+@@ -3117,7 +3115,7 @@ PeerConnectionImpl::CloseInt()
+ PC_AUTO_ENTER_API_CALL_NO_CHECK();
+
+ for (auto& dtmfState : mDTMFStates) {
+- dtmfState.mSendTimer->Cancel();
++ dtmfState->mSendTimer->Cancel();
+ }
+
+ // We do this at the end of the call because we want to make sure we've waited
+@@ -4201,63 +4199,63 @@ PeerConnectionImpl::GetRemoteStreams(nsTArray<RefPtr<DOMMediaStream > >& result)
+ return NS_OK;
+ }
+
+-void
+-PeerConnectionImpl::DTMFSendTimerCallback_m(nsITimer* timer, void* closure)
++nsresult
++PeerConnectionImpl::DTMFState::Notify(nsITimer* timer)
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+- auto state = static_cast<DTMFState*>(closure);
+-
+ nsString eventTone;
+- if (!state->mTones.IsEmpty()) {
+- uint16_t toneChar = state->mTones.CharAt(0);
++ if (!mTones.IsEmpty()) {
++ uint16_t toneChar = mTones.CharAt(0);
+ int tone = GetDTMFToneCode(toneChar);
+
+ eventTone.Assign(toneChar);
+
+- state->mTones.Cut(0, 1);
++ mTones.Cut(0, 1);
+
+ if (tone == -1) {
+- state->mSendTimer->InitWithNamedFuncCallback(DTMFSendTimerCallback_m, state,
+- 2000, nsITimer::TYPE_ONE_SHOT,
+- "DTMFSendTimerCallback_m");
++ mSendTimer->InitWithCallback(this, 2000, nsITimer::TYPE_ONE_SHOT);
+ } else {
+ // Reset delay if necessary
+- state->mSendTimer->InitWithNamedFuncCallback(DTMFSendTimerCallback_m, state,
+- state->mDuration + state->mInterToneGap,
+- nsITimer::TYPE_ONE_SHOT,
+- "DTMFSendTimerCallback_m");
++ mSendTimer->InitWithCallback(this,
++ mDuration + mInterToneGap,
++ nsITimer::TYPE_ONE_SHOT);
+
+ RefPtr<AudioSessionConduit> conduit =
+- state->mPeerConnectionImpl->mMedia->GetAudioConduit(state->mLevel);
++ mPeerConnectionImpl->mMedia->GetAudioConduit(mLevel);
+
+ if (conduit) {
+- uint32_t duration = state->mDuration;
+- state->mPeerConnectionImpl->mSTSThread->Dispatch(WrapRunnableNM([conduit, tone, duration] () {
++ uint32_t duration = mDuration;
++ mPeerConnectionImpl->mSTSThread->Dispatch(WrapRunnableNM([conduit, tone, duration] () {
+ //Note: We default to channel 0, not inband, and 6dB attenuation.
+ // here. We might want to revisit these choices in the future.
+ conduit->InsertDTMFTone(0, tone, true, duration, 6);
+ }), NS_DISPATCH_NORMAL);
+ }
+-
+ }
+ } else {
+- state->mSendTimer->Cancel();
++ mSendTimer->Cancel();
+ }
+
+- RefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(state->mPeerConnectionImpl->mPCObserver);
++ RefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPeerConnectionImpl->mPCObserver);
+ if (!pco) {
+ NS_WARNING("Failed to dispatch the RTCDTMFToneChange event!");
+- return;
++ return NS_OK; // Return is ignored anyhow
+ }
+
+ JSErrorResult jrv;
+- pco->OnDTMFToneChange(state->mTrackId, eventTone, jrv);
++ pco->OnDTMFToneChange(mTrackId, eventTone, jrv);
+
+ if (jrv.Failed()) {
+ NS_WARNING("Failed to dispatch the RTCDTMFToneChange event!");
+- return;
+ }
++
++ return NS_OK;
+ }
+
++PeerConnectionImpl::DTMFState::DTMFState() = default;
++PeerConnectionImpl::DTMFState::~DTMFState() = default;
++
++NS_IMPL_ISUPPORTS(PeerConnectionImpl::DTMFState, nsITimerCallback)
++
+ } // end mozilla namespace
+diff --git media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+index 3090a25bf57e..5213931161fc 100644
+--- media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
++++ media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+@@ -829,20 +829,24 @@ private:
+ uint16_t mMaxSending[SdpMediaSection::kMediaTypes];
+
+ // DTMF
+- struct DTMFState {
+- PeerConnectionImpl* mPeerConnectionImpl;
+- nsCOMPtr<nsITimer> mSendTimer;
+- nsString mTrackId;
+- nsString mTones;
+- size_t mLevel;
+- uint32_t mDuration;
+- uint32_t mInterToneGap;
++ class DTMFState : public nsITimerCallback {
++ virtual ~DTMFState();
++ public:
++ DTMFState();
++
++ NS_DECL_NSITIMERCALLBACK
++ NS_DECL_THREADSAFE_ISUPPORTS
++
++ PeerConnectionImpl* mPeerConnectionImpl;
++ nsCOMPtr<nsITimer> mSendTimer;
++ nsString mTrackId;
++ nsString mTones;
++ size_t mLevel;
++ uint32_t mDuration;
++ uint32_t mInterToneGap;
+ };
+
+- static void
+- DTMFSendTimerCallback_m(nsITimer* timer, void*);
+-
+- nsTArray<DTMFState> mDTMFStates;
++ nsTArray<RefPtr<DTMFState>> mDTMFStates;
+
+ std::vector<unsigned> mSendPacketDumpFlags;
+ std::vector<unsigned> mRecvPacketDumpFlags;
diff --git a/www/firefox/files/patch-bug1423159 b/www/firefox/files/patch-bug1423159
new file mode 100644
index 000000000000..85e7148b5b91
--- /dev/null
+++ b/www/firefox/files/patch-bug1423159
@@ -0,0 +1,69 @@
+commit 6508b1194af3
+Author: Olli Pettay <Olli.Pettay@helsinki.fi>
+Date: Sun Dec 10 14:49:49 2017 -0500
+
+ Bug 1423159 - Ensure proper multiprocess mouse enter/exit handling. r=stone, a=abillings
+
+ --HG--
+ extra : source : 689357a9394830406290ae1fb2200521a99bd7ad
+---
+ dom/events/EventStateManager.cpp | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git dom/events/EventStateManager.cpp dom/events/EventStateManager.cpp
+index 441036b5c5bf..f076f8ae0f09 100644
+--- dom/events/EventStateManager.cpp
++++ dom/events/EventStateManager.cpp
+@@ -4041,33 +4041,36 @@ EventStateManager::DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
+ return nullptr;
+ }
+
++ nsCOMPtr<nsIContent> targetContent = aTargetContent;
++ nsCOMPtr<nsIContent> relatedContent = aRelatedContent;
++
+ nsAutoPtr<WidgetMouseEvent> dispatchEvent;
+ CreateMouseOrPointerWidgetEvent(aMouseEvent, aMessage,
+- aRelatedContent, dispatchEvent);
++ relatedContent, dispatchEvent);
+
+ AutoWeakFrame previousTarget = mCurrentTarget;
+- mCurrentTargetContent = aTargetContent;
++ mCurrentTargetContent = targetContent;
+
+ nsIFrame* targetFrame = nullptr;
+
+ nsEventStatus status = nsEventStatus_eIgnore;
+- ESMEventCB callback(aTargetContent);
+- EventDispatcher::Dispatch(aTargetContent, mPresContext, dispatchEvent, nullptr,
++ ESMEventCB callback(targetContent);
++ EventDispatcher::Dispatch(targetContent, mPresContext, dispatchEvent, nullptr,
+ &status, &callback);
+
+ if (mPresContext) {
+ // Although the primary frame was checked in event callback, it may not be
+ // the same object after event dispatch and handling, so refetch it.
+- targetFrame = mPresContext->GetPrimaryFrameFor(aTargetContent);
++ targetFrame = mPresContext->GetPrimaryFrameFor(targetContent);
+
+ // If we are entering/leaving remote content, dispatch a mouse enter/exit
+ // event to the remote frame.
+- if (IsRemoteTarget(aTargetContent)) {
++ if (IsRemoteTarget(targetContent)) {
+ if (aMessage == eMouseOut) {
+ // For remote content, send a "top-level" widget mouse exit event.
+ nsAutoPtr<WidgetMouseEvent> remoteEvent;
+ CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseExitFromWidget,
+- aRelatedContent, remoteEvent);
++ relatedContent, remoteEvent);
+ remoteEvent->mExitFrom = WidgetMouseEvent::eTopLevel;
+
+ // mCurrentTarget is set to the new target, so we must reset it to the
+@@ -4079,7 +4082,7 @@ EventStateManager::DispatchMouseOrPointerEvent(WidgetMouseEvent* aMouseEvent,
+ } else if (aMessage == eMouseOver) {
+ nsAutoPtr<WidgetMouseEvent> remoteEvent;
+ CreateMouseOrPointerWidgetEvent(aMouseEvent, eMouseEnterIntoWidget,
+- aRelatedContent, remoteEvent);
++ relatedContent, remoteEvent);
+ HandleCrossProcessEvent(remoteEvent, &status);
+ }
+ }
diff --git a/www/firefox/files/patch-bug1424373 b/www/firefox/files/patch-bug1424373
new file mode 100644
index 000000000000..e237dfc67cd8
--- /dev/null
+++ b/www/firefox/files/patch-bug1424373
@@ -0,0 +1,305 @@
+commit 3512ab03dd1f
+Author: Mike Conley <mconley@mozilla.com>
+Date: Mon Dec 18 11:19:53 2017 -0500
+
+ Bug 1424373 - Don't set crash reporting prefs when showing about:tabcrashed for a crash without a report. r=Mossop a=jcristau
+---
+ browser/base/content/aboutTabCrashed.js | 1 +
+ .../test/tabcrashed/browser_autoSubmitRequest.js | 63 ++++++++++++++++++++--
+ .../content/test/tabcrashed/browser_withoutDump.js | 10 +---
+ browser/base/content/test/tabcrashed/head.js | 12 +++++
+ browser/modules/ContentCrashHandlers.jsm | 13 +++--
+ 5 files changed, 83 insertions(+), 16 deletions(-)
+
+diff --git browser/base/content/aboutTabCrashed.js browser/base/content/aboutTabCrashed.js
+index 822e3f78d4b5..8fccc92aa0fe 100644
+--- browser/base/content/aboutTabCrashed.js
++++ browser/base/content/aboutTabCrashed.js
+@@ -303,6 +303,7 @@ var AboutTabCrashed = {
+ includeURL,
+ URL,
+ autoSubmit,
++ hasReport: this.hasReport,
+ });
+ },
+ };
+diff --git browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js
+index a86b1e2c79b7..e04ebc80cdea 100644
+--- browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js
++++ browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js
+@@ -19,9 +19,9 @@ requestLongerTimeout(2);
+ add_task(async function test_show_form() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[AUTOSUBMIT_PREF, false]],
+- })
++ });
+
+- return BrowserTestUtils.withNewTab({
++ await BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: PAGE,
+ }, async function(browser) {
+@@ -66,9 +66,9 @@ add_task(async function test_show_form() {
+ add_task(async function test_show_form() {
+ await SpecialPowers.pushPrefEnv({
+ set: [[AUTOSUBMIT_PREF, true]],
+- })
++ });
+
+- return BrowserTestUtils.withNewTab({
++ await BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: PAGE,
+ }, async function(browser) {
+@@ -95,3 +95,58 @@ add_task(async function test_show_form() {
+ "Autosubmission pref should have been set.");
+ });
+ });
++
++/**
++ * Tests that we properly set the autoSubmit preference if the user is
++ * presented with a tabcrashed page without a crash report.
++ */
++add_task(async function test_no_offer() {
++ // We should default to sending the report.
++ Assert.ok(TabCrashHandler.prefs.getBoolPref("sendReport"));
++
++ await SpecialPowers.pushPrefEnv({
++ set: [[AUTOSUBMIT_PREF, false]],
++ });
++
++ await BrowserTestUtils.withNewTab({
++ gBrowser,
++ url: PAGE,
++ }, async function(browser) {
++ await TabStateFlusher.flush(browser);
++
++ // Make it so that it seems like no dump is available for the next crash.
++ prepareNoDump();
++
++ // Now crash the browser.
++ await BrowserTestUtils.crashBrowser(browser);
++
++ // eslint-disable-next-line mozilla/no-cpows-in-tests
++ let doc = browser.contentDocument;
++
++ // Ensure the request to autosubmit is invisible, since there's no report.
++ let requestRect = doc.getElementById("requestAutoSubmit")
++ .getBoundingClientRect();
++ Assert.equal(0, requestRect.height,
++ "Request for autosubmission has no height");
++ Assert.equal(0, requestRect.width,
++ "Request for autosubmission has no width");
++
++ // Since the pref is set to false, the checkbox should be
++ // unchecked.
++ let autoSubmit = doc.getElementById("autoSubmit");
++ Assert.ok(!autoSubmit.checked,
++ "Checkbox for autosubmission is not checked.");
++
++ let restoreButton = doc.getElementById("restoreTab");
++ restoreButton.click();
++
++ await BrowserTestUtils.browserLoaded(browser, false, PAGE);
++
++ // The autosubmission pref should now be set.
++ Assert.ok(!Services.prefs.getBoolPref(AUTOSUBMIT_PREF),
++ "Autosubmission pref should not have changed.");
++ });
++
++ // We should not have changed the default value for sending the report.
++ Assert.ok(TabCrashHandler.prefs.getBoolPref("sendReport"));
++});
+diff --git browser/base/content/test/tabcrashed/browser_withoutDump.js browser/base/content/test/tabcrashed/browser_withoutDump.js
+index 62d997240af4..33bc2b3164a1 100644
+--- browser/base/content/test/tabcrashed/browser_withoutDump.js
++++ browser/base/content/test/tabcrashed/browser_withoutDump.js
+@@ -2,16 +2,8 @@
+
+ const PAGE = "data:text/html,<html><body>A%20regular,%20everyday,%20normal%20page.";
+
+-/**
+- * Monkey patches TabCrashHandler.getDumpID to return null in order to test
+- * about:tabcrashed when a dump is not available.
+- */
+ add_task(async function setup() {
+- let originalGetDumpID = TabCrashHandler.getDumpID;
+- TabCrashHandler.getDumpID = function(browser) { return null; };
+- registerCleanupFunction(() => {
+- TabCrashHandler.getDumpID = originalGetDumpID;
+- });
++ prepareNoDump();
+ });
+
+ /**
+diff --git browser/base/content/test/tabcrashed/head.js browser/base/content/test/tabcrashed/head.js
+index e437acbcc4d5..9102e409ee91 100644
+--- browser/base/content/test/tabcrashed/head.js
++++ browser/base/content/test/tabcrashed/head.js
+@@ -121,3 +121,15 @@ async function setupLocalCrashReportServer() {
+ env.set("MOZ_CRASHREPORTER_URL", serverUrl);
+ });
+ }
++
++/**
++ * Monkey patches TabCrashHandler.getDumpID to return null in order to test
++ * about:tabcrashed when a dump is not available.
++ */
++function prepareNoDump() {
++ let originalGetDumpID = TabCrashHandler.getDumpID;
++ TabCrashHandler.getDumpID = function(browser) { return null; };
++ registerCleanupFunction(() => {
++ TabCrashHandler.getDumpID = originalGetDumpID;
++ });
++}
+diff --git browser/modules/ContentCrashHandlers.jsm browser/modules/ContentCrashHandlers.jsm
+index 36e60ede4f03..524d6a86a50a 100644
+--- browser/modules/ContentCrashHandlers.jsm
++++ browser/modules/ContentCrashHandlers.jsm
+@@ -361,8 +361,14 @@ this.TabCrashHandler = {
+ * even if they are empty.
+ */
+ maybeSendCrashReport(message) {
+- if (!AppConstants.MOZ_CRASHREPORTER)
++ if (!AppConstants.MOZ_CRASHREPORTER) {
++ return;
++ }
++
++ if (!message.data.hasReport) {
++ // There was no report, so nothing to do.
+ return;
++ }
+
+ let browser = message.target.browser;
+
+@@ -374,8 +380,9 @@ this.TabCrashHandler = {
+
+ let childID = this.browserMap.get(browser);
+ let dumpID = this.childMap.get(childID);
+- if (!dumpID)
+- return
++ if (!dumpID) {
++ return;
++ }
+
+ if (!message.data.sendReport) {
+ Services.telemetry.getHistogramById("FX_CONTENT_CRASH_NOT_SUBMITTED").add(1);
+
+commit a4a421108540
+Author: Mike Conley <mconley@mozilla.com>
+Date: Thu Dec 21 16:36:13 2017 -0500
+
+ Bug 1424373 - Rename crash report submission pref. r=Mossop a=jcristau
+---
+ browser/app/profile/firefox.js | 2 +-
+ browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js | 2 +-
+ browser/components/preferences/in-content/privacy.xul | 6 +++---
+ .../tests/browser_bug1020245_openPreferences_to_paneContent.js | 4 ++--
+ .../components/sessionstore/test/browser_background_tab_crash.js | 2 +-
+ browser/modules/ContentCrashHandlers.jsm | 4 ++--
+ browser/modules/test/browser/browser_UnsubmittedCrashHandler.js | 4 ++--
+ 7 files changed, 12 insertions(+), 12 deletions(-)
+
+diff --git browser/app/profile/firefox.js browser/app/profile/firefox.js
+index 8c29be0acc58..a1844936fdea 100644
+--- browser/app/profile/firefox.js
++++ browser/app/profile/firefox.js
+@@ -1664,7 +1664,7 @@ pref("browser.crashReports.unsubmittedCheck.enabled", false);
+ // without a user choice before we suppress the notification for
+ // some number of days.
+ pref("browser.crashReports.unsubmittedCheck.chancesUntilSuppress", 4);
+-pref("browser.crashReports.unsubmittedCheck.autoSubmit", false);
++pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false);
+
+ // Preferences for the form autofill system extension
+ // The truthy values of "extensions.formautofill.available" are "on" and "detect",
+diff --git browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js
+index e04ebc80cdea..1d4a70a1d145 100644
+--- browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js
++++ browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js
+@@ -1,7 +1,7 @@
+ "use strict";
+
+ const PAGE = "data:text/html,<html><body>A%20regular,%20everyday,%20normal%20page.";
+-const AUTOSUBMIT_PREF = "browser.crashReports.unsubmittedCheck.autoSubmit";
++const AUTOSUBMIT_PREF = "browser.crashReports.unsubmittedCheck.autoSubmit2";
+
+ const {TabStateFlusher} =
+ Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
+diff --git browser/components/preferences/in-content-new/privacy.xul browser/components/preferences/in-content-new/privacy.xul
+index 7eb882972ffa..1d34065ac7e5 100644
+--- browser/components/preferences/in-content-new/privacy.xul
++++ browser/components/preferences/in-content-new/privacy.xul
+@@ -161,8 +161,8 @@
+
+ <!-- Data Choices tab -->
+ #ifdef MOZ_CRASHREPORTER
+- <preference id="browser.crashReports.unsubmittedCheck.autoSubmit"
+- name="browser.crashReports.unsubmittedCheck.autoSubmit"
++ <preference id="browser.crashReports.unsubmittedCheck.autoSubmit2"
++ name="browser.crashReports.unsubmittedCheck.autoSubmit2"
+ type="bool"/>
+ #endif
+
+@@ -671,7 +671,7 @@
+ #ifdef MOZ_CRASHREPORTER
+ <hbox align="center">
+ <checkbox id="automaticallySubmitCrashesBox"
+- preference="browser.crashReports.unsubmittedCheck.autoSubmit"
++ preference="browser.crashReports.unsubmittedCheck.autoSubmit2"
+ label="&alwaysSubmitCrashReports1.label;"
+ accesskey="&alwaysSubmitCrashReports1.accesskey;"/>
+ <label id="crashReporterLearnMore"
+diff --git browser/components/sessionstore/test/browser_background_tab_crash.js browser/components/sessionstore/test/browser_background_tab_crash.js
+index 9df18999a32f..34d92a9bdb39 100644
+--- browser/components/sessionstore/test/browser_background_tab_crash.js
++++ browser/components/sessionstore/test/browser_background_tab_crash.js
+@@ -147,7 +147,7 @@ add_task(async function test_background_crash_simple() {
+ */
+ add_task(async function test_background_crash_autosubmit_backlogged() {
+ await SpecialPowers.pushPrefEnv({
+- set: [["browser.crashReports.unsubmittedCheck.autoSubmit", true]],
++ set: [["browser.crashReports.unsubmittedCheck.autoSubmit2", true]],
+ });
+
+ await setupBackgroundTabs(async function([tab1, tab2]) {
+diff --git browser/modules/ContentCrashHandlers.jsm browser/modules/ContentCrashHandlers.jsm
+index a5f95677c006..7127e2785c3a 100644
+--- browser/modules/ContentCrashHandlers.jsm
++++ browser/modules/ContentCrashHandlers.jsm
+@@ -885,11 +885,11 @@ this.UnsubmittedCrashHandler = {
+
+ get autoSubmit() {
+ return Services.prefs
+- .getBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit");
++ .getBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit2");
+ },
+
+ set autoSubmit(val) {
+- Services.prefs.setBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit",
++ Services.prefs.setBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit2",
+ val);
+ },
+
+diff --git browser/modules/test/browser/browser_UnsubmittedCrashHandler.js browser/modules/test/browser/browser_UnsubmittedCrashHandler.js
+index 12c673ca92d2..2e79413d0a15 100644
+--- browser/modules/test/browser/browser_UnsubmittedCrashHandler.js
++++ browser/modules/test/browser/browser_UnsubmittedCrashHandler.js
+@@ -398,7 +398,7 @@ add_task(async function test_can_submit_several() {
+ * and sends the pending crash reports.
+ */
+ add_task(async function test_can_submit_always() {
+- let pref = "browser.crashReports.unsubmittedCheck.autoSubmit";
++ let pref = "browser.crashReports.unsubmittedCheck.autoSubmit2";
+ Assert.equal(Services.prefs.getBoolPref(pref), false,
+ "We should not be auto-submitting by default");
+
+@@ -442,7 +442,7 @@ add_task(async function test_can_submit_always() {
+ */
+ add_task(async function test_can_auto_submit() {
+ await SpecialPowers.pushPrefEnv({ set: [
+- ["browser.crashReports.unsubmittedCheck.autoSubmit", true],
++ ["browser.crashReports.unsubmittedCheck.autoSubmit2", true],
+ ]});
+
+ let reportIDs = await createPendingCrashReports(3);
diff --git a/www/firefox/files/patch-z-bug1382366 b/www/firefox/files/patch-z-bug1382366
new file mode 100644
index 000000000000..bdc3afee6f63
--- /dev/null
+++ b/www/firefox/files/patch-z-bug1382366
@@ -0,0 +1,159 @@
+commit bc308d794057
+Author: Karl Tomlinson <karlt+@karlt.net>
+Date: Sat Nov 4 19:00:46 2017 +1300
+
+ Bug 1382366 - Disable AudioCallback -> SystemClockDriver fallback before disowning graph. f=pehrsons, r=padenot, a=gchang
+
+ MozReview-Commit-ID: ESr6yxjPVWf
+
+ --HG--
+ extra : rebase_source : 6ed3093ab9dec68515f39353dc46ab40780cd161
+ extra : source : 53f055298fa9d2446fd90ad8a51fefd3b15b16c1
+---
+ dom/media/GraphDriver.cpp | 38 +++++++++++---------------------------
+ dom/media/GraphDriver.h | 14 ++++++++------
+ 2 files changed, 19 insertions(+), 33 deletions(-)
+
+diff --git dom/media/GraphDriver.cpp dom/media/GraphDriver.cpp
+index 13944338e3d7..62c847e90155 100644
+--- dom/media/GraphDriver.cpp
++++ dom/media/GraphDriver.cpp
+@@ -33,8 +33,7 @@ GraphDriver::GraphDriver(MediaStreamGraphImpl* aGraphImpl)
+ mWaitState(WAITSTATE_RUNNING),
+ mCurrentTimeStamp(TimeStamp::Now()),
+ mPreviousDriver(nullptr),
+- mNextDriver(nullptr),
+- mScheduled(false)
++ mNextDriver(nullptr)
+ { }
+
+ void GraphDriver::SetGraphTime(GraphDriver* aPreviousDriver,
+@@ -121,12 +120,6 @@ void GraphDriver::SetPreviousDriver(GraphDriver* aPreviousDriver)
+ mPreviousDriver = aPreviousDriver;
+ }
+
+-bool GraphDriver::Scheduled()
+-{
+- GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
+- return mScheduled;
+-}
+-
+ ThreadedDriver::ThreadedDriver(MediaStreamGraphImpl* aGraphImpl)
+ : GraphDriver(aGraphImpl)
+ { }
+@@ -216,8 +209,7 @@ ThreadedDriver::Start()
+ // Note: mThread may be null during event->Run() if we pass to NewNamedThread! See AudioInitTask
+ nsresult rv = NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread));
+ if (NS_SUCCEEDED(rv)) {
+- rv = mThread->EventTarget()->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
+- mScheduled = NS_SUCCEEDED(rv);
++ mThread->EventTarget()->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
+ }
+ }
+ }
+@@ -545,6 +537,7 @@ AudioCallbackDriver::AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl)
+ , mAddedMixer(false)
+ , mInCallback(false)
+ , mMicrophoneActive(false)
++ , mShouldFallbackIfError(false)
+ , mFromFallback(false)
+ {
+ LOG(LogLevel::Debug, ("AudioCallbackDriver ctor for graph %p", aGraphImpl));
+@@ -765,13 +758,13 @@ AudioCallbackDriver::Start()
+ "to ensure it runs after previous shutdown."));
+ RefPtr<AsyncCubebTask> initEvent =
+ new AsyncCubebTask(AsAudioCallbackDriver(), AsyncCubebOperation::INIT);
+- nsresult rv = initEvent->Dispatch();
+- mScheduled = NS_SUCCEEDED(rv);
++ initEvent->Dispatch();
+ }
+
+ bool
+ AudioCallbackDriver::StartStream()
+ {
++ mShouldFallbackIfError = true;
+ if (cubeb_stream_start(mAudioStream) != CUBEB_OK) {
+ NS_WARNING("Could not start cubeb stream for MSG.");
+ return false;
+@@ -1015,6 +1008,10 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
+ mSampleRate, mOutputChannels);
+
+ if (!stillProcessing) {
++ // About to hand over control of the graph. Do not start a new driver if
++ // StateCallback() receives an error for this stream while the main thread
++ // or another driver has control of the graph.
++ mShouldFallbackIfError = false;
+ // Enter shutdown mode. The stable-state handler will detect this
+ // and complete shutdown if the graph does not get restarted.
+ mGraphImpl->SignalMainThreadCleanup();
+@@ -1028,6 +1025,7 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
+ }
+
+ if (switching) {
++ mShouldFallbackIfError = false;
+ // If the audio stream has not been started by the previous driver or
+ // the graph itself, keep it alive.
+ MonitorAutoLock mon(mGraphImpl->GetMonitor());
+@@ -1052,22 +1050,8 @@ AudioCallbackDriver::StateCallback(cubeb_state aState)
+ {
+ LOG(LogLevel::Debug, ("AudioCallbackDriver State: %d", aState));
+
+- if (aState == CUBEB_STATE_ERROR) {
+- if (!mAudioStream) {
+- // If we don't have an audio stream here, this means that the stream
+- // initialization has failed. A fallback on a SystemCallDriver will happen at
+- // the callsite of `cubeb_stream_init`.
+- return;
+- }
+-
++ if (aState == CUBEB_STATE_ERROR && mShouldFallbackIfError) {
+ MonitorAutoLock lock(GraphImpl()->GetMonitor());
+-
+- if (NextDriver() && NextDriver()->Scheduled()) {
+- // We are switching to another driver that has already been scheduled
+- // to be initialized and started. There's nothing for us to do here.
+- return;
+- }
+-
+ // Fall back to a driver using a normal thread. If needed,
+ // the graph will try to re-open an audio stream later.
+ SystemClockDriver* nextDriver = new SystemClockDriver(GraphImpl());
+diff --git dom/media/GraphDriver.h dom/media/GraphDriver.h
+index 4857d74b114a..1f8b9386c6fa 100644
+--- dom/media/GraphDriver.h
++++ dom/media/GraphDriver.h
+@@ -146,9 +146,6 @@ public:
+ void SetNextDriver(GraphDriver* aNextDriver);
+ void SetPreviousDriver(GraphDriver* aPreviousDriver);
+
+- /* Return whether we have been scheduled to start. */
+- bool Scheduled();
+-
+ /**
+ * If we are running a real time graph, get the current time stamp to schedule
+ * video frames. This has to be reimplemented by real time drivers.
+@@ -252,9 +249,6 @@ protected:
+ // driver at the end of this iteration.
+ // This must be accessed using the {Set,Get}NextDriver methods.
+ RefPtr<GraphDriver> mNextDriver;
+- // This is initially false, but set to true as soon the driver has been
+- // scheduled to start through GraphDriver::Start().
+- bool mScheduled;
+ virtual ~GraphDriver()
+ { }
+ };
+@@ -558,6 +552,14 @@ private:
+ * True if microphone is being used by this process. This is synchronized by
+ * the graph's monitor. */
+ Atomic<bool> mMicrophoneActive;
++ /* Indication of whether a fallback SystemClockDriver should be started if
++ * StateCallback() receives an error. No mutex need be held during access.
++ * The transition to true happens before cubeb_stream_start() is called.
++ * After transitioning to false on the last DataCallback(), the stream is
++ * not accessed from another thread until the graph thread either signals
++ * main thread cleanup or dispatches an event to switch to another
++ * driver. */
++ bool mShouldFallbackIfError;
+ /* True if this driver was created from a driver created because of a previous
+ * AudioCallbackDriver failure. */
+ bool mFromFallback;