merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 27 Jun 2017 10:56:41 +0200
changeset 417255 53477d584130945864c4491632f88da437353356
parent 417211 bda394665daaaf0899717f220aa8345fe697e5dc (current diff)
parent 417254 6419ffd3458f1addf65bf0c11842009cf219a7c4 (diff)
child 417256 23d5ed7817c902c19b8ebb385ac72a94dffb3789
child 417291 4cc568cad60e565289647cc55df2a3049c3943ae
child 417371 336e17ace58e198ba3254e3ced39fcbbfa5220fb
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone56.0a1
first release with
nightly linux32
53477d584130 / 56.0a1 / 20170627100221 / files
nightly linux64
53477d584130 / 56.0a1 / 20170627100221 / files
nightly mac
53477d584130 / 56.0a1 / 20170627100238 / files
nightly win32
53477d584130 / 56.0a1 / 20170627030209 / files
nightly win64
53477d584130 / 56.0a1 / 20170627030209 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
dom/base/nsContentSink.cpp
dom/base/nsContentUtils.cpp
dom/base/nsDocument.cpp
dom/base/nsFrameLoader.cpp
dom/base/nsGlobalWindow.cpp
dom/html/nsHTMLDocument.cpp
dom/presentation/PresentationRequest.cpp
dom/script/ScriptLoader.cpp
dom/xhr/XMLHttpRequestMainThread.cpp
dom/xml/XMLStylesheetProcessingInstruction.cpp
dom/xml/nsXMLContentSink.cpp
dom/xul/XULDocument.cpp
editor/libeditor/EditorBase.cpp
image/RasterImage.cpp
layout/base/nsPresContext.cpp
layout/tables/nsTableFrame.cpp
layout/xul/nsXULPopupManager.h
media/webrtc/signaling/test/mediapipeline_unittest.cpp
parser/html/nsHtml5StreamParser.cpp
parser/html/nsHtml5TreeOpExecutor.cpp
parser/htmlparser/nsParser.cpp
toolkit/components/telemetry/Telemetry.cpp
widget/cocoa/nsChildView.mm
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -1798,18 +1798,23 @@ Accessible::GetNativeInterface(void** aN
 }
 
 void
 Accessible::DoCommand(nsIContent *aContent, uint32_t aActionIndex)
 {
   class Runnable final : public mozilla::Runnable
   {
   public:
-    Runnable(Accessible* aAcc, nsIContent* aContent, uint32_t aIdx) :
-      mAcc(aAcc), mContent(aContent), mIdx(aIdx) { }
+    Runnable(Accessible* aAcc, nsIContent* aContent, uint32_t aIdx)
+      : mozilla::Runnable("Runnable")
+      , mAcc(aAcc)
+      , mContent(aContent)
+      , mIdx(aIdx)
+    {
+    }
 
     NS_IMETHOD Run() override
     {
       if (mAcc)
         mAcc->DispatchClickEvent(mContent, mIdx);
 
       return NS_OK;
     }
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -644,19 +644,22 @@ DocAccessible::ScrollPositionDidChange(n
   const uint32_t kScrollPosCheckWait = 50;
   if (mScrollWatchTimer) {
     mScrollWatchTimer->SetDelay(kScrollPosCheckWait);  // Create new timer, to avoid leaks
   }
   else {
     mScrollWatchTimer = do_CreateInstance("@mozilla.org/timer;1");
     if (mScrollWatchTimer) {
       NS_ADDREF_THIS(); // Kung fu death grip
-      mScrollWatchTimer->InitWithFuncCallback(ScrollTimerCallback, this,
-                                              kScrollPosCheckWait,
-                                              nsITimer::TYPE_REPEATING_SLACK);
+      mScrollWatchTimer->InitWithNamedFuncCallback(
+        ScrollTimerCallback,
+        this,
+        kScrollPosCheckWait,
+        nsITimer::TYPE_REPEATING_SLACK,
+        "a11y::DocAccessible::ScrollPositionDidChange");
     }
   }
   mScrollPositionChangedTicks = 1;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIObserver
 
@@ -2095,22 +2098,22 @@ DocAccessible::DoARIAOwnsRelocation(Acce
 #ifdef A11Y_LOG
   logging::TreeInfo("aria owns traversal", logging::eVerbose,
                     "candidate", child, nullptr);
 #endif
 
     // Same child on same position, no change.
     if (child->Parent() == aOwner &&
         child->IndexInParent() == static_cast<int32_t>(insertIdx)) {
-      NS_ASSERTION(child == children->ElementAt(arrayIdx), "Not in sync!");
+      MOZ_ASSERT(child == children->ElementAt(arrayIdx), "Not in sync!");
       insertIdx++; arrayIdx++;
       continue;
     }
 
-    NS_ASSERTION(children->SafeElementAt(arrayIdx) != child, "Already in place!");
+    MOZ_ASSERT(children->SafeElementAt(arrayIdx) != child, "Already in place!");
 
     nsTArray<RefPtr<Accessible> >::index_type idx = children->IndexOf(child);
     if (idx < arrayIdx) {
       continue; // ignore second entry of same ID
     }
 
     // A new child is found, check for loops.
     if (child->Parent() != aOwner) {
@@ -2197,18 +2200,20 @@ DocAccessible::MoveChild(Accessible* aCh
   Accessible* curParent = aChild->Parent();
 
 #ifdef A11Y_LOG
   logging::TreeInfo("move child", 0,
                     "old parent", curParent, "new parent", aNewParent,
                     "child", aChild, nullptr);
 #endif
 
-  // If the child was taken from from an ARIA owns element.
+  // Forget aria-owns info in case of ARIA owned element. The caller is expected
+  // to update it if needed.
   if (aChild->IsRelocated()) {
+    aChild->SetRelocated(false);
     nsTArray<RefPtr<Accessible> >* owned = mARIAOwnsHash.Get(curParent);
     MOZ_ASSERT(owned, "IsRelocated flag is out of sync with mARIAOwnsHash");
     owned->RemoveElement(aChild);
     if (owned->Length() == 0) {
       mARIAOwnsHash.Remove(curParent);
     }
   }
 
@@ -2315,16 +2320,17 @@ DocAccessible::UncacheChildrenInSubtree(
   for (uint32_t idx = 0; idx < count; idx++) {
     Accessible* child = aRoot->ContentChildAt(idx);
 
     if (child->IsRelocated()) {
       MOZ_ASSERT(owned, "IsRelocated flag is out of sync with mARIAOwnsHash");
       owned->RemoveElement(child);
       if (owned->Length() == 0) {
         mARIAOwnsHash.Remove(aRoot);
+        owned = nullptr;
       }
     }
 
     // Removing this accessible from the document doesn't mean anything about
     // accessibles for subdocuments, so skip removing those from the tree.
     if (!child->IsDoc()) {
       UncacheChildrenInSubtree(child);
     }
--- a/accessible/ipc/win/HandlerProvider.cpp
+++ b/accessible/ipc/win/HandlerProvider.cpp
@@ -90,17 +90,18 @@ HandlerProvider::GetAndSerializePayload(
   MOZ_ASSERT(mscom::IsCurrentThreadMTA());
 
   if (mSerializer) {
     return;
   }
 
   IA2Payload payload{};
 
-  if (!mscom::InvokeOnMainThread(this, &HandlerProvider::BuildIA2Data,
+  if (!mscom::InvokeOnMainThread("HandlerProvider::BuildIA2Data",
+                                 this, &HandlerProvider::BuildIA2Data,
                                  &payload.mData) ||
       !payload.mData.mUniqueId) {
     return;
   }
 
   // But we set mGeckoBackChannel on the current thread which resides in the
   // MTA. This is important to ensure that COM always invokes
   // IGeckoBackChannel methods in an MTA background thread.
@@ -231,31 +232,33 @@ HandlerProvider::put_HandlerControl(long
   MOZ_ASSERT(mscom::IsCurrentThreadMTA());
 
   if (!aCtrl) {
     return E_INVALIDARG;
   }
 
   auto ptrProxy = mscom::ToProxyUniquePtr(aCtrl);
 
-  if (!mscom::InvokeOnMainThread(this,
+  if (!mscom::InvokeOnMainThread("HandlerProvider::SetHandlerControlOnMainThread",
+                                 this,
                                  &HandlerProvider::SetHandlerControlOnMainThread,
                                  static_cast<DWORD>(aPid), Move(ptrProxy))) {
     return E_FAIL;
   }
 
   return S_OK;
 }
 
 HRESULT
 HandlerProvider::Refresh(IA2Data* aOutData)
 {
   MOZ_ASSERT(mscom::IsCurrentThreadMTA());
 
-  if (!mscom::InvokeOnMainThread(this, &HandlerProvider::BuildIA2Data,
+  if (!mscom::InvokeOnMainThread("HandlerProvider::BuildIA2Data",
+                                 this, &HandlerProvider::BuildIA2Data,
                                  aOutData)) {
     return E_FAIL;
   }
 
   return S_OK;
 }
 
 } // namespace a11y
--- a/accessible/mac/mozAccessible.mm
+++ b/accessible/mac/mozAccessible.mm
@@ -28,16 +28,17 @@
 #include "nsCoord.h"
 #include "nsObjCExceptions.h"
 #include "nsWhitespaceTokenizer.h"
 #include <prdtoa.h>
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
+#define NSAccessibilityDOMIdentifierAttribute @"AXDOMIdentifier"
 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"
 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"
 #define NSAccessibilityMathBaseAttribute @"AXMathBase"
 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"
 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"
@@ -154,16 +155,17 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
   return true;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
 }
 
 - (NSArray*)additionalAccessibilityAttributeNames
 {
   NSMutableArray* additional = [NSMutableArray array];
+  [additional addObject:NSAccessibilityDOMIdentifierAttribute];
   switch (mRole) {
     case roles::MATHML_ROOT:
       [additional addObject:NSAccessibilityMathRootIndexAttribute];
       [additional addObject:NSAccessibilityMathRootRadicandAttribute];
       break;
     case roles::MATHML_SQUARE_ROOT:
       [additional addObject:NSAccessibilityMathRootRadicandAttribute];
       break;
@@ -316,16 +318,24 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return tempAcc ? GetNativeFromGeckoAccessible(tempAcc) : nil;
     }
     nsTArray<ProxyAccessible*> rel = proxy->RelationByType(RelationType::LABELLED_BY);
     ProxyAccessible* tempProxy = rel.SafeElementAt(0);
     return tempProxy ? GetNativeFromProxy(tempProxy) : nil;
   }
   if ([attribute isEqualToString:NSAccessibilityHelpAttribute])
     return [self help];
+  if ([attribute isEqualToString:NSAccessibilityDOMIdentifierAttribute]) {
+    nsAutoString id;
+    if (accWrap)
+      nsCoreUtils::GetID(accWrap->GetContent(), id);
+    else
+      proxy->DOMNodeID(id);
+    return nsCocoaUtils::ToNSString(id);
+  }
 
   switch (mRole) {
   case roles::MATHML_ROOT:
     if ([attribute isEqualToString:NSAccessibilityMathRootRadicandAttribute])
       return [self childAt:0];
     if ([attribute isEqualToString:NSAccessibilityMathRootIndexAttribute])
       return [self childAt:1];
     break;
@@ -881,19 +891,16 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return @"AXMathMultiscript";
 
     case roles::SWITCH:
       return @"AXSwitch";
 
     case roles::ALERT:
       return @"AXApplicationAlert";
 
-    case roles::SEPARATOR:
-      return @"AXContentSeparator";
-
     case roles::PROPERTYPAGE:
       return @"AXTabPanel";
 
     case roles::DETAILS:
       return @"AXDetails";
 
     case roles::SUMMARY:
       return @"AXSummary";
@@ -905,16 +912,17 @@ ConvertToNSArray(nsTArray<ProxyAccessibl
       return @"AXOutlineRow";
 
     case roles::ARTICLE:
       return @"AXDocumentArticle";
 
     // macOS added an AXSubrole value to distinguish generic AXGroup objects
     // from those which are AXGroups as a result of an explicit ARIA role,
     // such as the non-landmark, non-listitem text containers in DPub ARIA.
+    case roles::FOOTNOTE:
     case roles::SECTION:
       if (roleAtom)
         return @"AXApplicationGroup";
       break;
 
     default:
       break;
   }
@@ -943,16 +951,17 @@ static const RoleDescrMap sRoleDescrMap[
   { @"AXDocumentNote", NS_LITERAL_STRING("note") },
   { @"AXDocumentRegion", NS_LITERAL_STRING("region") },
   { @"AXLandmarkApplication", NS_LITERAL_STRING("application") },
   { @"AXLandmarkBanner", NS_LITERAL_STRING("banner") },
   { @"AXLandmarkComplementary", NS_LITERAL_STRING("complementary") },
   { @"AXLandmarkContentInfo", NS_LITERAL_STRING("content") },
   { @"AXLandmarkMain", NS_LITERAL_STRING("main") },
   { @"AXLandmarkNavigation", NS_LITERAL_STRING("navigation") },
+  { @"AXLandmarkRegion", NS_LITERAL_STRING("region") },
   { @"AXLandmarkSearch", NS_LITERAL_STRING("search") },
   { @"AXSearchField", NS_LITERAL_STRING("searchTextField") },
   { @"AXTabPanel", NS_LITERAL_STRING("tabPanel") },
   { @"AXTerm", NS_LITERAL_STRING("term") },
   { @"AXUserInterfaceTooltip", NS_LITERAL_STRING("tooltip") }
 };
 
 struct RoleDescrComparator
@@ -964,16 +973,19 @@ struct RoleDescrComparator
   }
 };
 
 - (NSString*)roleDescription
 {
   if (mRole == roles::DOCUMENT)
     return utils::LocalizedString(NS_LITERAL_STRING("htmlContent"));
 
+  if (mRole == roles::HEADING)
+    return utils::LocalizedString(NS_LITERAL_STRING("heading"));
+
   NSString* subrole = [self subrole];
 
   if (subrole) {
     size_t idx = 0;
     if (BinarySearchIf(sRoleDescrMap, 0, ArrayLength(sRoleDescrMap),
                        RoleDescrComparator(subrole), &idx)) {
       return utils::LocalizedString(sRoleDescrMap[idx].description);
     }
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -836,17 +836,18 @@ AccessibleWrap::accSelect(
 
   if (flagsSelect & SELFLAG_TAKEFOCUS) {
     if (XRE_IsContentProcess()) {
       // In this case we might have been invoked while the IPC MessageChannel is
       // waiting on a sync reply. We cannot dispatch additional IPC while that
       // is happening, so we dispatch TakeFocus from the main thread to
       // guarantee that we are outside any IPC.
       nsCOMPtr<nsIRunnable> runnable =
-        mozilla::NewRunnableMethod(this, &Accessible::TakeFocus);
+        mozilla::NewRunnableMethod("Accessible::TakeFocus",
+                                   this, &Accessible::TakeFocus);
       NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
       return S_OK;
     }
     TakeFocus();
     return S_OK;
   }
 
   if (flagsSelect & SELFLAG_TAKESELECTION) {
--- a/accessible/windows/msaa/LazyInstantiator.cpp
+++ b/accessible/windows/msaa/LazyInstantiator.cpp
@@ -259,16 +259,17 @@ LazyInstantiator::ShouldInstantiate(cons
   */
 
 #if defined(MOZ_TELEMETRY_REPORTING)
   if (!mTelemetryThread) {
     // Call GatherTelemetry on a background thread because it does I/O on
     // the executable file to retrieve version information.
     nsCOMPtr<nsIRunnable> runnable(
         NewRunnableMethod<nsCOMPtr<nsIFile>, RefPtr<AccumulateRunnable>>(
+                                             "LazyInstantiator::GatherTelemetry",
                                              this,
                                              &LazyInstantiator::GatherTelemetry,
                                              clientExe,
                                              new AccumulateRunnable(this)));
     NS_NewThread(getter_AddRefs(mTelemetryThread), runnable);
   }
 #endif // defined(MOZ_TELEMETRY_REPORTING)
   return true;
--- a/accessible/xpcom/xpcAccessibilityService.cpp
+++ b/accessible/xpcom/xpcAccessibilityService.cpp
@@ -74,18 +74,22 @@ xpcAccessibilityService::Release(void)
 
   // When ref count goes down to 1 (held internally as a static reference),
   // it means that there are no more external references to the
   // xpcAccessibilityService and we can attempt to shut down acceessiblity
   // service.
   if (count == 1 && !mShutdownTimer) {
     mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     if (mShutdownTimer) {
-      mShutdownTimer->InitWithFuncCallback(ShutdownCallback, this, 100,
-                                           nsITimer::TYPE_ONE_SHOT);
+      mShutdownTimer->InitWithNamedFuncCallback(
+        ShutdownCallback,
+        this,
+        100,
+        nsITimer::TYPE_ONE_SHOT,
+        "xpcAccessibilityService::Release");
     }
   }
 
   return count;
 }
 
 NS_IMPL_QUERY_INTERFACE(xpcAccessibilityService, nsIAccessibilityService,
                                                  nsIAccessibleRetrieval)
--- a/browser/base/content/test/alerts/browser.ini
+++ b/browser/base/content/test/alerts/browser.ini
@@ -1,11 +1,12 @@
 [DEFAULT]
 support-files =
   head.js
   file_dom_notifications.html
 
 [browser_notification_close.js]
+skip-if = os == 'win' # Bug 1227785
 [browser_notification_do_not_disturb.js]
 [browser_notification_open_settings.js]
 [browser_notification_remove_permission.js]
 [browser_notification_replace.js]
 [browser_notification_tab_switching.js]
--- a/browser/extensions/e10srollout/bootstrap.js
+++ b/browser/extensions/e10srollout/bootstrap.js
@@ -5,16 +5,17 @@
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/UpdateUtils.jsm");
 Cu.import("resource://gre/modules/AppConstants.jsm");
+Cu.import("resource://gre/modules/TelemetryEnvironment.jsm");
 
 // The amount of people to be part of e10s
 const TEST_THRESHOLD = {
   "beta": 0.9,  // 90%
   "release": 1.0,  // 100%
   "esr": 1.0,  // 100%
 };
 
@@ -234,16 +235,19 @@ function getUserSample(multi) {
   }
 
   Preferences.set(pref, value.toString().substr(0, 8));
   return value;
 }
 
 function setCohort(cohortName) {
   Preferences.set(PREF_COHORT_NAME, cohortName);
+  if (cohortName != "unsupportedChannel") {
+    TelemetryEnvironment.setExperimentActive("e10sCohort", cohortName);
+  }
   try {
     if (Ci.nsICrashReporter) {
       Services.appinfo.QueryInterface(Ci.nsICrashReporter).annotateCrashReport("E10SCohort", cohortName);
     }
   } catch (e) {}
 }
 
 function optedIn() {
--- a/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js
+++ b/devtools/client/shared/widgets/tooltip/ImageTooltipHelper.js
@@ -90,17 +90,17 @@ function setImageTooltip(tooltip, doc, i
     <div style="flex: 1;
                 display: flex;
                 padding: ${IMAGE_PADDING}px;
                 align-items: center;
                 justify-content: center;
                 min-height: 1px;">
       <img class="${imageClass}"
            style="height: ${imgHeight}px; max-height: 100%;"
-           src="${imageUrl}"/>
+           src="${encodeURI(imageUrl)}"/>
     </div>`;
 
   if (!hideDimensionLabel) {
     let label = naturalWidth + " \u00D7 " + naturalHeight;
     html += `
       <div style="height: ${LABEL_HEIGHT}px;
                   text-align: center;">
         <span class="theme-comment devtools-tooltip-caption">${label}</span>
--- a/devtools/server/actors/highlighters/css-grid.js
+++ b/devtools/server/actors/highlighters/css-grid.js
@@ -1156,17 +1156,21 @@ CssGridHighlighter.prototype = extend(Au
    */
   renderGridAreaOverlay() {
     let padding = 1;
 
     for (let i = 0; i < this.gridData.length; i++) {
       let fragment = this.gridData[i];
 
       for (let area of fragment.areas) {
-        let { rowStart, rowEnd, columnStart, columnEnd } = area;
+        let { rowStart, rowEnd, columnStart, columnEnd, type } = area;
+
+        if (type === "implicit") {
+          continue;
+        }
 
         // Draw the line edges for the grid area
         const areaColStart = fragment.cols.lines[columnStart - 1];
         const areaColEnd = fragment.cols.lines[columnEnd - 1];
 
         const areaRowStart = fragment.rows.lines[rowStart - 1];
         const areaRowEnd = fragment.rows.lines[rowEnd - 1];
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -450,19 +450,22 @@ nsresult
 nsPingListener::StartTimeout(DocGroup* aDocGroup)
 {
   NS_ENSURE_ARG(aDocGroup);
 
   nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
   timer->SetTarget(aDocGroup->EventTargetFor(TaskCategory::Network));
 
   if (timer) {
-    nsresult rv = timer->InitWithFuncCallback(OnPingTimeout, mLoadGroup,
-                                              PING_TIMEOUT,
-                                              nsITimer::TYPE_ONE_SHOT);
+    nsresult rv =
+      timer->InitWithNamedFuncCallback(OnPingTimeout,
+                                       mLoadGroup,
+                                       PING_TIMEOUT,
+                                       nsITimer::TYPE_ONE_SHOT,
+                                       "nsPingListener::StartTimeout");
     if (NS_SUCCEEDED(rv)) {
       mTimer = timer;
       return NS_OK;
     }
   }
 
   return NS_ERROR_OUT_OF_MEMORY;
 }
@@ -1765,20 +1768,22 @@ nsDocShell::DispatchToTabGroup(const cha
 
   RefPtr<mozilla::dom::TabGroup> tabGroup = win->TabGroup();
   return tabGroup->Dispatch(aName, aCategory, runnable.forget());
 }
 
 NS_IMETHODIMP
 nsDocShell::DispatchLocationChangeEvent()
 {
-  return DispatchToTabGroup("nsDocShell::FireDummyOnLocationChange",
-                            TaskCategory::Other,
-                            NewRunnableMethod(this,
-                              &nsDocShell::FireDummyOnLocationChange));
+  return DispatchToTabGroup(
+    "nsDocShell::FireDummyOnLocationChange",
+    TaskCategory::Other,
+    NewRunnableMethod("nsDocShell::FireDummyOnLocationChange",
+                      this,
+                      &nsDocShell::FireDummyOnLocationChange));
 }
 
 bool
 nsDocShell::MaybeInitTiming()
 {
   if (mTiming && !mBlankTiming) {
     return false;
   }
@@ -9642,23 +9647,30 @@ class InternalLoadEvent : public Runnabl
 public:
   InternalLoadEvent(nsDocShell* aDocShell,
                     nsIURI* aURI,
                     nsIURI* aOriginalURI,
                     Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
                     bool aLoadReplace,
                     nsIURI* aReferrer, uint32_t aReferrerPolicy,
                     nsIPrincipal* aTriggeringPrincipal,
-                    nsIPrincipal* aPrincipalToInherit, uint32_t aFlags,
-                    const char* aTypeHint, nsIInputStream* aPostData,
-                    nsIInputStream* aHeadersData, uint32_t aLoadType,
-                    nsISHEntry* aSHEntry, bool aFirstParty,
-                    const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell,
-                    nsIURI* aBaseURI, bool aCheckForPrerender)
-    : mSrcdoc(aSrcdoc)
+                    nsIPrincipal* aPrincipalToInherit,
+                    uint32_t aFlags,
+                    const char* aTypeHint,
+                    nsIInputStream* aPostData,
+                    nsIInputStream* aHeadersData,
+                    uint32_t aLoadType,
+                    nsISHEntry* aSHEntry,
+                    bool aFirstParty,
+                    const nsAString& aSrcdoc,
+                    nsIDocShell* aSourceDocShell,
+                    nsIURI* aBaseURI,
+                    bool aCheckForPrerender)
+    : mozilla::Runnable("InternalLoadEvent")
+    , mSrcdoc(aSrcdoc)
     , mDocShell(aDocShell)
     , mURI(aURI)
     , mOriginalURI(aOriginalURI)
     , mResultPrincipalURI(aResultPrincipalURI)
     , mLoadReplace(aLoadReplace)
     , mReferrer(aReferrer)
     , mReferrerPolicy(aReferrerPolicy)
     , mTriggeringPrincipal(aTriggeringPrincipal)
@@ -14041,17 +14053,18 @@ OnLinkClickEvent::OnLinkClickEvent(nsDoc
                                    nsIURI* aURI,
                                    const char16_t* aTargetSpec,
                                    const nsAString& aFileName,
                                    nsIInputStream* aPostDataStream,
                                    nsIInputStream* aHeadersDataStream,
                                    bool aNoOpenerImplied,
                                    bool aIsTrusted,
                                    nsIPrincipal* aTriggeringPrincipal)
-  : mHandler(aHandler)
+  : mozilla::Runnable("OnLinkClickEvent")
+  , mHandler(aHandler)
   , mURI(aURI)
   , mTargetSpec(aTargetSpec)
   , mFileName(aFileName)
   , mPostDataStream(aPostDataStream)
   , mHeadersDataStream(aHeadersDataStream)
   , mContent(aContent)
   , mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
   , mNoOpenerImplied(aNoOpenerImplied)
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -776,17 +776,21 @@ protected:
   }
 
 public:
   // Event type dispatched by RestorePresentation
   class RestorePresentationEvent : public mozilla::Runnable
   {
   public:
     NS_DECL_NSIRUNNABLE
-    explicit RestorePresentationEvent(nsDocShell* aDs) : mDocShell(aDs) {}
+    explicit RestorePresentationEvent(nsDocShell* aDs)
+      : mozilla::Runnable("nsDocShell::RestorePresentationEvent")
+      , mDocShell(aDs)
+    {
+    }
     void Revoke() { mDocShell = nullptr; }
   private:
     RefPtr<nsDocShell> mDocShell;
   };
 
 protected:
   bool JustStartedNetworkLoad();
 
--- a/docshell/base/nsDocShellTreeOwner.cpp
+++ b/docshell/base/nsDocShellTreeOwner.cpp
@@ -1255,20 +1255,22 @@ ChromeTooltipListener::MouseMove(nsIDOME
       if (eventTarget) {
         mPossibleTooltipNode = do_QueryInterface(eventTarget);
         nsCOMPtr<nsIGlobalObject> global(eventTarget->GetOwnerGlobal());
         if (global) {
           mTooltipTimer->SetTarget(global->EventTargetFor(TaskCategory::UI));
         }
       }
       if (mPossibleTooltipNode) {
-        nsresult rv = mTooltipTimer->InitWithFuncCallback(
-          sTooltipCallback, this,
+        nsresult rv = mTooltipTimer->InitWithNamedFuncCallback(
+          sTooltipCallback,
+          this,
           LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
-          nsITimer::TYPE_ONE_SHOT);
+          nsITimer::TYPE_ONE_SHOT,
+          "ChromeTooltipListener::MouseMove");
         if (NS_FAILED(rv)) {
           mPossibleTooltipNode = nullptr;
         }
       }
     } else {
       NS_WARNING("Could not create a timer for tooltip tracking");
     }
   } else {
--- a/docshell/shistory/nsSHEntryShared.cpp
+++ b/docshell/shistory/nsSHEntryShared.cpp
@@ -180,17 +180,18 @@ nsSHEntryShared::RemoveFromBFCacheSync()
 
   return NS_OK;
 }
 
 class DestroyViewerEvent : public mozilla::Runnable
 {
 public:
   DestroyViewerEvent(nsIContentViewer* aViewer, nsIDocument* aDocument)
-    : mViewer(aViewer)
+    : mozilla::Runnable("DestroyViewerEvent")
+    , mViewer(aViewer)
     , mDocument(aDocument)
   {
   }
 
   NS_IMETHOD Run() override
   {
     if (mViewer) {
       mViewer->Destroy();
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -1448,17 +1448,19 @@ void
 Animation::DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag)
 {
   CycleCollectedJSContext* context = CycleCollectedJSContext::Get();
 
   if (aSyncNotifyFlag == SyncNotifyFlag::Sync) {
     DoFinishNotificationImmediately();
   } else if (!mFinishNotificationTask.IsPending()) {
     RefPtr<nsRunnableMethod<Animation>> runnable =
-      NewRunnableMethod(this, &Animation::DoFinishNotificationImmediately);
+      NewRunnableMethod("dom::Animation::DoFinishNotificationImmediately",
+                        this,
+                        &Animation::DoFinishNotificationImmediately);
     context->DispatchToMicroTask(do_AddRef(runnable));
     mFinishNotificationTask = runnable.forget();
   }
 }
 
 void
 Animation::ResetFinishedPromise()
 {
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -237,21 +237,22 @@ EvictEntries(nsIFile* aDirectory, const 
 
 // FileDescriptorHolder owns a file descriptor and its memory mapping.
 // FileDescriptorHolder is derived by two runnable classes (that is,
 // (Parent|Child)Runnable.
 class FileDescriptorHolder : public Runnable
 {
 public:
   FileDescriptorHolder()
-  : mQuotaObject(nullptr),
-    mFileSize(INT64_MIN),
-    mFileDesc(nullptr),
-    mFileMap(nullptr),
-    mMappedMemory(nullptr)
+    : Runnable("dom::asmjscache::FileDescriptorHolder")
+    , mQuotaObject(nullptr)
+    , mFileSize(INT64_MIN)
+    , mFileDesc(nullptr)
+    , mFileMap(nullptr)
+    , mMappedMemory(nullptr)
   { }
 
   ~FileDescriptorHolder() override
   {
     // These resources should have already been released by Finish().
     MOZ_ASSERT(!mQuotaObject);
     MOZ_ASSERT(!mMappedMemory);
     MOZ_ASSERT(!mFileMap);
--- a/dom/audiochannel/AudioChannelService.cpp
+++ b/dom/audiochannel/AudioChannelService.cpp
@@ -80,19 +80,21 @@ public:
 private:
   const uint64_t mWindowID;
   const bool mActive;
 };
 
 class AudioPlaybackRunnable final : public Runnable
 {
 public:
-  AudioPlaybackRunnable(nsPIDOMWindowOuter* aWindow, bool aActive,
+  AudioPlaybackRunnable(nsPIDOMWindowOuter* aWindow,
+                        bool aActive,
                         AudioChannelService::AudibleChangedReasons aReason)
-    : mWindow(aWindow)
+    : mozilla::Runnable("AudioPlaybackRunnable")
+    , mWindow(aWindow)
     , mActive(aActive)
     , mReason(aReason)
   {}
 
  NS_IMETHOD Run() override
  {
     nsCOMPtr<nsIObserverService> observerService =
       services::GetObserverService();
@@ -869,28 +871,29 @@ AudioChannelService::AudioChannelWindow:
 }
 
 void
 AudioChannelService::AudioChannelWindow::NotifyMediaBlockStop(nsPIDOMWindowOuter* aWindow)
 {
   mShouldSendBlockStopEvent = false;
   // Can't use raw pointer for lamba variable capturing, use smart ptr.
   nsCOMPtr<nsPIDOMWindowOuter> window = aWindow;
-  NS_DispatchToCurrentThread(NS_NewRunnableFunction([window] () -> void {
+  NS_DispatchToCurrentThread(NS_NewRunnableFunction(
+    "dom::AudioChannelService::AudioChannelWindow::NotifyMediaBlockStop",
+    [window]() -> void {
       nsCOMPtr<nsIObserverService> observerService =
         services::GetObserverService();
       if (NS_WARN_IF(!observerService)) {
         return;
       }
 
       observerService->NotifyObservers(ToSupports(window),
                                        "audio-playback",
                                        u"blockStop");
-    })
-  );
+    }));
 }
 
 void
 AudioChannelService::AudioChannelWindow::AppendAgentAndIncreaseAgentsNum(AudioChannelAgent* aAgent)
 {
   MOZ_ASSERT(aAgent);
   MOZ_ASSERT(!mAgents.Contains(aAgent));
 
@@ -1044,26 +1047,27 @@ AudioChannelService::AudioChannelWindow:
 
   if (window->GetMediaSuspend() != nsISuspendedTypes::SUSPENDED_BLOCK ||
       !doc->Hidden()) {
     return;
   }
 
   if (!mShouldSendBlockStopEvent) {
       mShouldSendBlockStopEvent = true;
-      NS_DispatchToCurrentThread(NS_NewRunnableFunction([window] () -> void {
-        nsCOMPtr<nsIObserverService> observerService =
-          services::GetObserverService();
-        if (NS_WARN_IF(!observerService)) {
-          return;
-        }
+      NS_DispatchToCurrentThread(NS_NewRunnableFunction(
+        "dom::AudioChannelService::AudioChannelWindow::"
+        "MaybeNotifyMediaBlockStart",
+        [window]() -> void {
+          nsCOMPtr<nsIObserverService> observerService =
+            services::GetObserverService();
+          if (NS_WARN_IF(!observerService)) {
+            return;
+          }
 
-        observerService->NotifyObservers(ToSupports(window),
-                                         "audio-playback",
-                                         u"blockStart");
-      })
-    );
+          observerService->NotifyObservers(
+            ToSupports(window), "audio-playback", u"blockStart");
+        }));
   }
 }
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -449,18 +449,19 @@ CustomElementRegistry::EnqueueLifecycleC
 
     // Add a script runner to pop and process the element queue at
     // the top of the processing stack.
     if (shouldPushElementQueue) {
       // Lifecycle callbacks enqueued by user agent implementation
       // should be invoked prior to returning control back to script.
       // Create a script runner to process the top of the processing
       // stack as soon as it is safe to run script.
-      nsCOMPtr<nsIRunnable> runnable =
-        NS_NewRunnableFunction(&CustomElementRegistry::ProcessTopElementQueue);
+      nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
+        "dom::CustomElementRegistry::EnqueueLifecycleCallback",
+        &CustomElementRegistry::ProcessTopElementQueue);
       nsContentUtils::AddScriptRunner(runnable);
     }
   }
 }
 
 void
 CustomElementRegistry::GetCustomPrototype(nsIAtom* aAtom,
                                           JS::MutableHandle<JSObject*> aPrototype)
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -238,18 +238,21 @@ private:
    */
   void InvokeReactions(ElementQueue& aElementQueue);
 
   void Enqueue(Element* aElement, CustomElementReaction* aReaction);
 
 private:
   class ProcessBackupQueueRunnable : public mozilla::Runnable {
     public:
-      explicit ProcessBackupQueueRunnable(CustomElementReactionsStack* aReactionStack)
-        : mReactionStack(aReactionStack)
+      explicit ProcessBackupQueueRunnable(
+        CustomElementReactionsStack* aReactionStack)
+        : Runnable(
+            "dom::CustomElementReactionsStack::ProcessBackupQueueRunnable")
+        , mReactionStack(aReactionStack)
       {
         MOZ_ASSERT(!mReactionStack->mIsBackupQueueProcessing,
                    "mIsBackupQueueProcessing should be initially false");
         mReactionStack->mIsBackupQueueProcessing = true;
       }
 
       NS_IMETHOD Run() override
       {
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -145,41 +145,41 @@ void
 DOMIntersectionObserver::GetThresholds(nsTArray<double>& aRetVal)
 {
   aRetVal = mThresholds;
 }
 
 void
 DOMIntersectionObserver::Observe(Element& aTarget)
 {
-  if (mObservationTargets.EnsureInserted(&aTarget)) {
-    // A new entry was created.
-    aTarget.RegisterIntersectionObserver(this);
-    Connect();
+  if (mObservationTargets.Contains(&aTarget)) {
+    return;
   }
+  aTarget.RegisterIntersectionObserver(this);
+  mObservationTargets.AppendElement(&aTarget);
+  Connect();
 }
 
 void
 DOMIntersectionObserver::Unobserve(Element& aTarget)
 {
-  if (mObservationTargets.Count() == 1) {
+  if (mObservationTargets.Length() == 1) {
     Disconnect();
     return;
   }
-
-  mObservationTargets.RemoveEntry(&aTarget);
+ 
+  mObservationTargets.RemoveElement(&aTarget);
   aTarget.UnregisterIntersectionObserver(this);
 }
 
 void
 DOMIntersectionObserver::UnlinkTarget(Element& aTarget)
 {
-  if (mObservationTargets.EnsureRemoved(&aTarget) &&
-      mObservationTargets.Count() == 0) {
-    // We removed the last entry.
+  mObservationTargets.RemoveElement(&aTarget);
+  if (mObservationTargets.Length() == 0) {
     Disconnect();
   }
 }
 
 void
 DOMIntersectionObserver::Connect()
 {
   if (mConnected) {
@@ -195,18 +195,18 @@ DOMIntersectionObserver::Connect()
 void
 DOMIntersectionObserver::Disconnect()
 {
   if (!mConnected) {
     return;
   }
 
   mConnected = false;
-  for (auto iter = mObservationTargets.Iter(); !iter.Done(); iter.Next()) {
-    Element* target = iter.Get()->GetKey();
+  for (size_t i = 0; i < mObservationTargets.Length(); ++i) {
+    Element* target = mObservationTargets.ElementAt(i);
     target->UnregisterIntersectionObserver(this);
   }
   mObservationTargets.Clear();
   if (mDocument) {
     mDocument->RemoveIntersectionObserver(this);
   }
 }
 
@@ -320,18 +320,18 @@ DOMIntersectionObserver::Update(nsIDocum
     } else if (value.IsPercentLengthUnit()) {
       coord.SetPercentValue(value.GetPercentValue());
     } else {
       MOZ_ASSERT_UNREACHABLE("invalid length unit");
     }
     rootMargin.Side(side) = nsLayoutUtils::ComputeCBDependentValue(basis, coord);
   }
 
-  for (auto iter = mObservationTargets.Iter(); !iter.Done(); iter.Next()) {
-    Element* target = iter.Get()->GetKey();
+  for (size_t i = 0; i < mObservationTargets.Length(); ++i) {
+    Element* target = mObservationTargets.ElementAt(i);
     nsIFrame* targetFrame = target->GetPrimaryFrame();
     nsRect targetRect;
     Maybe<nsRect> intersectionRect;
     bool isSameDoc = root && root->GetComposedDoc() == target->GetComposedDoc();
 
     if (rootFrame && targetFrame) {
       // If mRoot is set we are testing intersection with a container element
       // instead of the implicit root.
@@ -496,17 +496,17 @@ DOMIntersectionObserver::QueueIntersecti
 void
 DOMIntersectionObserver::Notify()
 {
   if (!mQueuedEntries.Length()) {
     return;
   }
   mozilla::dom::Sequence<mozilla::OwningNonNull<DOMIntersectionObserverEntry>> entries;
   if (entries.SetCapacity(mQueuedEntries.Length(), mozilla::fallible)) {
-    for (uint32_t i = 0; i < mQueuedEntries.Length(); ++i) {
+    for (size_t i = 0; i < mQueuedEntries.Length(); ++i) {
       RefPtr<DOMIntersectionObserverEntry> next = mQueuedEntries[i];
       *entries.AppendElement(mozilla::fallible) = next;
     }
   }
   mQueuedEntries.Clear();
   mCallback->Call(this, entries, *this);
 }
 
--- a/dom/base/DOMIntersectionObserver.h
+++ b/dom/base/DOMIntersectionObserver.h
@@ -174,17 +174,20 @@ protected:
                                       double aIntersectionRatio);
 
   nsCOMPtr<nsPIDOMWindowInner>                    mOwner;
   RefPtr<nsIDocument>                             mDocument;
   RefPtr<mozilla::dom::IntersectionCallback>      mCallback;
   RefPtr<Element>                                 mRoot;
   nsCSSRect                                       mRootMargin;
   nsTArray<double>                                mThresholds;
-  nsTHashtable<nsPtrHashKey<Element>>             mObservationTargets;
+  
+  // Holds raw pointers which are explicitly cleared by UnlinkTarget().
+  nsTArray<Element*>                              mObservationTargets;
+  
   nsTArray<RefPtr<DOMIntersectionObserverEntry>>  mQueuedEntries;
   bool                                            mConnected;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(DOMIntersectionObserver, NS_DOM_INTERSECTION_OBSERVER_IID)
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/DOMRequest.cpp
+++ b/dom/base/DOMRequest.cpp
@@ -294,20 +294,20 @@ DOMRequestService::FireDetailedError(nsI
   static_cast<DOMRequest*>(aRequest)->FireDetailedError(err);
 
   return NS_OK;
 }
 
 class FireSuccessAsyncTask : public mozilla::Runnable
 {
 
-  FireSuccessAsyncTask(DOMRequest* aRequest,
-                       const JS::Value& aResult) :
-    mReq(aRequest),
-    mResult(RootingCx(), aResult)
+  FireSuccessAsyncTask(DOMRequest* aRequest, const JS::Value& aResult)
+    : mozilla::Runnable("FireSuccessAsyncTask")
+    , mReq(aRequest)
+    , mResult(RootingCx(), aResult)
   {
   }
 
 public:
 
   // Due to the fact that initialization can fail during shutdown (since we
   // can't fetch a js context), set up an initiatization function to make sure
   // we can return the failure appropriately
@@ -331,20 +331,20 @@ public:
 private:
   RefPtr<DOMRequest> mReq;
   JS::PersistentRooted<JS::Value> mResult;
 };
 
 class FireErrorAsyncTask : public mozilla::Runnable
 {
 public:
-  FireErrorAsyncTask(DOMRequest* aRequest,
-                     const nsAString& aError) :
-    mReq(aRequest),
-    mError(aError)
+  FireErrorAsyncTask(DOMRequest* aRequest, const nsAString& aError)
+    : mozilla::Runnable("FireErrorAsyncTask")
+    , mReq(aRequest)
+    , mError(aError)
   {
   }
 
   NS_IMETHOD
   Run() override
   {
     mReq->FireError(mError);
     return NS_OK;
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -608,17 +608,19 @@ Element::WrapObject(JSContext *aCx, JS::
       xblService->LoadBindings(this, uri, principal, getter_AddRefs(binding),
                                &dummy);
 
       if (binding) {
         if (nsContentUtils::IsSafeToRunScript()) {
           binding->ExecuteAttachedHandler();
         } else {
           nsContentUtils::AddScriptRunner(
-            NewRunnableMethod(binding, &nsXBLBinding::ExecuteAttachedHandler));
+            NewRunnableMethod("nsXBLBinding::ExecuteAttachedHandler",
+                              binding,
+                              &nsXBLBinding::ExecuteAttachedHandler));
         }
       }
     }
   }
 
   return obj;
 }
 
@@ -1783,20 +1785,24 @@ Element::BindToTree(nsIDocument* aDocume
   NS_POSTCONDITION(aDocument == GetUncomposedDoc(), "Bound to wrong document");
   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
   NS_POSTCONDITION(aBindingParent == GetBindingParent(),
                    "Bound to wrong binding parent");
 
   return NS_OK;
 }
 
-RemoveFromBindingManagerRunnable::RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
-                                                                   nsIContent* aContent,
-                                                                   nsIDocument* aDoc):
-  mManager(aManager), mContent(aContent), mDoc(aDoc)
+RemoveFromBindingManagerRunnable::RemoveFromBindingManagerRunnable(
+  nsBindingManager* aManager,
+  nsIContent* aContent,
+  nsIDocument* aDoc)
+  : mozilla::Runnable("dom::RemoveFromBindingManagerRunnable")
+  , mManager(aManager)
+  , mContent(aContent)
+  , mDoc(aDoc)
 {}
 
 RemoveFromBindingManagerRunnable::~RemoveFromBindingManagerRunnable() {}
 
 NS_IMETHODIMP
 RemoveFromBindingManagerRunnable::Run()
 {
   // It may be the case that the element was removed from the
--- a/dom/base/EventSource.cpp
+++ b/dom/base/EventSource.cpp
@@ -386,17 +386,19 @@ EventSourceImpl::Close()
 {
   if (IsClosed()) {
     return;
   }
   SetReadyState(CLOSED);
   // Asynchronously call CloseInternal to prevent EventSourceImpl from being
   // synchronously destoryed while dispatching DOM event.
   DebugOnly<nsresult> rv =
-    Dispatch(NewRunnableMethod(this, &EventSourceImpl::CloseInternal),
+    Dispatch(NewRunnableMethod("dom::EventSourceImpl::CloseInternal",
+                               this,
+                               &EventSourceImpl::CloseInternal),
              NS_DISPATCH_NORMAL);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
 void
 EventSourceImpl::CloseInternal()
 {
   AssertIsOnTargetThread();
@@ -678,17 +680,19 @@ EventSourceImpl::OnStartRequest(nsIReque
     nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(httpChannel);
     if (rr) {
       rv = rr->RetargetDeliveryTo(this);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         NS_WARNING("Retargeting failed");
       }
     }
   }
-  rv = Dispatch(NewRunnableMethod(this, &EventSourceImpl::AnnounceConnection),
+  rv = Dispatch(NewRunnableMethod("dom::EventSourceImpl::AnnounceConnection",
+                                  this,
+                                  &EventSourceImpl::AnnounceConnection),
                 NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS(rv, rv);
   mStatus = PARSE_STATE_BEGIN_OF_STREAM;
   return NS_OK;
 }
 
 // this method parses the characters as they become available instead of
 // buffering them.
@@ -747,17 +751,18 @@ class DataAvailableRunnable final : publ
   private:
     RefPtr<EventSourceImpl> mEventSourceImpl;
     UniquePtr<char[]> mData;
     uint32_t mLength;
   public:
     DataAvailableRunnable(EventSourceImpl* aEventSourceImpl,
                           UniquePtr<char[]> aData,
                           uint32_t aLength)
-      : mEventSourceImpl(aEventSourceImpl)
+      : Runnable("dom::DataAvailableRunnable")
+      , mEventSourceImpl(aEventSourceImpl)
       , mData(Move(aData))
       , mLength(aLength)
     {
     }
 
     NS_IMETHOD Run() override
     {
       mEventSourceImpl->ParseSegment(mData.get(), mLength);
@@ -835,19 +840,20 @@ EventSourceImpl::OnStopRequest(nsIReques
       aStatusCode != NS_ERROR_DNS_LOOKUP_QUEUE_FULL) {
     DispatchFailConnection();
     return NS_ERROR_ABORT;
   }
 
   nsresult rv = CheckHealthOfRequestCallback(aRequest);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = Dispatch(
-         NewRunnableMethod(this, &EventSourceImpl::ReestablishConnection),
-         NS_DISPATCH_NORMAL);
+  rv = Dispatch(NewRunnableMethod("dom::EventSourceImpl::ReestablishConnection",
+                                  this,
+                                  &EventSourceImpl::ReestablishConnection),
+                NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // EventSourceImpl::nsIChannelEventSink
 //-----------------------------------------------------------------------------
@@ -1240,19 +1246,22 @@ EventSourceImpl::SetReconnectionTimeout(
   }
 
   // the timer will be used whenever the requests are going finished.
   if (!mTimer) {
     mTimer = do_CreateInstance("@mozilla.org/timer;1");
     NS_ENSURE_STATE(mTimer);
   }
 
-  nsresult rv = mTimer->InitWithFuncCallback(TimerCallback, this,
-                                             mReconnectionTime,
-                                             nsITimer::TYPE_ONE_SHOT);
+  nsresult rv = mTimer->InitWithNamedFuncCallback(
+    TimerCallback,
+    this,
+    mReconnectionTime,
+    nsITimer::TYPE_ONE_SHOT,
+    "dom::EventSourceImpl::SetReconnectionTimeout");
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 EventSourceImpl::PrintErrorOnConsole(const char* aBundleURI,
                                      const char16_t* aError,
@@ -1336,17 +1345,19 @@ EventSourceImpl::DispatchFailConnection(
   AssertIsOnMainThread();
   if (IsClosed()) {
     return;
   }
   nsresult rv = ConsoleError();
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to print to the console error");
   }
-  rv = Dispatch(NewRunnableMethod(this, &EventSourceImpl::FailConnection),
+  rv = Dispatch(NewRunnableMethod("dom::EventSourceImpl::FailConnection",
+                                  this,
+                                  &EventSourceImpl::FailConnection),
                 NS_DISPATCH_NORMAL);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
 void
 EventSourceImpl::FailConnection()
 {
   AssertIsOnTargetThread();
@@ -1402,17 +1413,19 @@ EventSourceImpl::Thaw()
   }
 
   MOZ_ASSERT(!mHttpChannel, "the connection hasn't been closed!!!");
 
   SetFrozen(false);
   nsresult rv;
   if (!mGoingToDispatchAllMessages && mMessagesToDispatch.GetSize() > 0) {
     nsCOMPtr<nsIRunnable> event =
-      NewRunnableMethod(this, &EventSourceImpl::DispatchAllMessageEvents);
+      NewRunnableMethod("dom::EventSourceImpl::DispatchAllMessageEvents",
+                        this,
+                        &EventSourceImpl::DispatchAllMessageEvents);
     NS_ENSURE_STATE(event);
 
     mGoingToDispatchAllMessages = true;
 
     rv = Dispatch(event.forget(), NS_DISPATCH_NORMAL);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -1463,17 +1476,19 @@ EventSourceImpl::DispatchCurrentMessageE
   size_t sizeBefore = mMessagesToDispatch.GetSize();
   mMessagesToDispatch.Push(message.release());
   NS_ENSURE_TRUE(mMessagesToDispatch.GetSize() == sizeBefore + 1,
                  NS_ERROR_OUT_OF_MEMORY);
 
 
   if (!mGoingToDispatchAllMessages) {
     nsCOMPtr<nsIRunnable> event =
-      NewRunnableMethod(this, &EventSourceImpl::DispatchAllMessageEvents);
+      NewRunnableMethod("dom::EventSourceImpl::DispatchAllMessageEvents",
+                        this,
+                        &EventSourceImpl::DispatchAllMessageEvents);
     NS_ENSURE_STATE(event);
 
     mGoingToDispatchAllMessages = true;
 
     return Dispatch(event.forget(), NS_DISPATCH_NORMAL);
   }
 
   return NS_OK;
--- a/dom/base/ImageEncoder.cpp
+++ b/dom/base/ImageEncoder.cpp
@@ -547,19 +547,19 @@ RegisterEncoderThreadPoolTerminatorObser
 nsresult
 ImageEncoder::EnsureThreadPool()
 {
   if (!sThreadPool) {
     nsCOMPtr<nsIThreadPool> threadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID);
     sThreadPool = threadPool;
 
     if (!NS_IsMainThread()) {
-      NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
-        RegisterEncoderThreadPoolTerminatorObserver();
-      }));
+      NS_DispatchToMainThread(NS_NewRunnableFunction(
+        "dom::ImageEncoder::EnsureThreadPool",
+        []() -> void { RegisterEncoderThreadPoolTerminatorObserver(); }));
     } else {
       RegisterEncoderThreadPoolTerminatorObserver();
     }
 
     const uint32_t kThreadLimit = 2;
     const uint32_t kIdleThreadLimit = 1;
     const uint32_t kIdleThreadTimeoutMs = 30000;
 
--- a/dom/base/PostMessageEvent.cpp
+++ b/dom/base/PostMessageEvent.cpp
@@ -30,24 +30,26 @@ namespace mozilla {
 namespace dom {
 
 PostMessageEvent::PostMessageEvent(nsGlobalWindow* aSource,
                                    const nsAString& aCallerOrigin,
                                    nsGlobalWindow* aTargetWindow,
                                    nsIPrincipal* aProvidedPrincipal,
                                    nsIDocument* aSourceDocument,
                                    bool aTrustedCaller)
-: StructuredCloneHolder(CloningSupported, TransferringSupported,
-                        StructuredCloneScope::SameProcessSameThread),
-  mSource(aSource),
-  mCallerOrigin(aCallerOrigin),
-  mTargetWindow(aTargetWindow),
-  mProvidedPrincipal(aProvidedPrincipal),
-  mSourceDocument(aSourceDocument),
-  mTrustedCaller(aTrustedCaller)
+  : Runnable("dom::PostMessageEvent")
+  , StructuredCloneHolder(CloningSupported,
+                          TransferringSupported,
+                          StructuredCloneScope::SameProcessSameThread)
+  , mSource(aSource)
+  , mCallerOrigin(aCallerOrigin)
+  , mTargetWindow(aTargetWindow)
+  , mProvidedPrincipal(aProvidedPrincipal)
+  , mSourceDocument(aSourceDocument)
+  , mTrustedCaller(aTrustedCaller)
 {
 }
 
 PostMessageEvent::~PostMessageEvent()
 {
 }
 
 NS_IMETHODIMP
--- a/dom/base/ScreenOrientation.cpp
+++ b/dom/base/ScreenOrientation.cpp
@@ -548,18 +548,20 @@ ScreenOrientation::Notify(const hal::Scr
     doc->SetCurrentOrientation(mType, mAngle);
 
     Promise* pendingPromise = doc->GetOrientationPendingPromise();
     if (pendingPromise) {
       pendingPromise->MaybeResolveWithUndefined();
       doc->SetOrientationPendingPromise(nullptr);
     }
 
-    nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod(this,
-      &ScreenOrientation::DispatchChangeEvent);
+    nsCOMPtr<nsIRunnable> runnable =
+      NewRunnableMethod("dom::ScreenOrientation::DispatchChangeEvent",
+                        this,
+                        &ScreenOrientation::DispatchChangeEvent);
     rv = NS_DispatchToMainThread(runnable);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NS_DispatchToMainThread failed");
   }
 }
 
 void
 ScreenOrientation::UpdateActiveOrientationLock(ScreenOrientationInternal aOrientation)
 {
@@ -635,18 +637,20 @@ ScreenOrientation::VisibleEventListener:
 			       orientation->DeviceAngle(CallerType::System));
 
     Promise* pendingPromise = doc->GetOrientationPendingPromise();
     if (pendingPromise) {
       pendingPromise->MaybeResolveWithUndefined();
       doc->SetOrientationPendingPromise(nullptr);
     }
 
-    nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod(orientation,
-      &ScreenOrientation::DispatchChangeEvent);
+    nsCOMPtr<nsIRunnable> runnable =
+      NewRunnableMethod("dom::ScreenOrientation::DispatchChangeEvent",
+                        orientation,
+                        &ScreenOrientation::DispatchChangeEvent);
     rv = NS_DispatchToMainThread(runnable);
     if (NS_WARN_IF(rv.Failed())) {
       return rv.StealNSResult();
     }
   }
 
   return NS_OK;
 }
--- a/dom/base/Selection.h
+++ b/dom/base/Selection.h
@@ -318,21 +318,23 @@ private:
   class ScrollSelectionIntoViewEvent : public Runnable {
   public:
     NS_DECL_NSIRUNNABLE
     ScrollSelectionIntoViewEvent(Selection* aSelection,
                                  SelectionRegion aRegion,
                                  nsIPresShell::ScrollAxis aVertical,
                                  nsIPresShell::ScrollAxis aHorizontal,
                                  int32_t aFlags)
-      : mSelection(aSelection),
-        mRegion(aRegion),
-        mVerticalScroll(aVertical),
-        mHorizontalScroll(aHorizontal),
-        mFlags(aFlags) {
+      : Runnable("dom::Selection::ScrollSelectionIntoViewEvent")
+      , mSelection(aSelection)
+      , mRegion(aRegion)
+      , mVerticalScroll(aVertical)
+      , mHorizontalScroll(aHorizontal)
+      , mFlags(aFlags)
+    {
       NS_ASSERTION(aSelection, "null parameter");
     }
     void Revoke() { mSelection = nullptr; }
   private:
     Selection *mSelection;
     SelectionRegion mRegion;
     nsIPresShell::ScrollAxis mVerticalScroll;
     nsIPresShell::ScrollAxis mHorizontalScroll;
--- a/dom/base/TabGroup.cpp
+++ b/dom/base/TabGroup.cpp
@@ -21,16 +21,18 @@
 namespace mozilla {
 namespace dom {
 
 static StaticRefPtr<TabGroup> sChromeTabGroup;
 
 TabGroup::TabGroup(bool aIsChrome)
  : mLastWindowLeft(false)
  , mThrottledQueuesInitialized(false)
+ , mNumOfIndexedDBTransactions(0)
+ , mNumOfIndexedDBDatabases(0)
  , mIsChrome(aIsChrome)
  , mForegroundCount(0)
 {
   CreateEventTargets(/* aNeedValidation = */ !aIsChrome);
 
   // Do not throttle runnables from chrome windows.  In theory we should
   // not have abuse issues from these windows and many browser chrome
   // tests have races that fail if we do throttle chrome runnables.
--- a/dom/base/TabGroup.h
+++ b/dom/base/TabGroup.h
@@ -122,29 +122,43 @@ public:
   nsISerialEventTarget* EventTargetFor(TaskCategory aCategory) const override;
 
   void WindowChangedBackgroundStatus(bool aIsNowBackground);
 
   // Returns true if all of the TabGroup's top-level windows are in
   // the background.
   bool IsBackground() const override;
 
+  // Increase/Decrease the number of IndexedDB transactions/databases for the
+  // decision making of the preemption in the scheduler.
+  Atomic<uint32_t>& IndexedDBTransactionCounter()
+  {
+    return mNumOfIndexedDBTransactions;
+  }
+
+  Atomic<uint32_t>& IndexedDBDatabaseCounter()
+  {
+    return mNumOfIndexedDBDatabases;
+  }
+
 private:
   virtual AbstractThread*
   AbstractMainThreadForImpl(TaskCategory aCategory) override;
 
   TabGroup* AsTabGroup() override { return this; }
 
   void EnsureThrottledEventQueues();
 
   ~TabGroup();
 
   // Thread-safe members
   Atomic<bool> mLastWindowLeft;
   Atomic<bool> mThrottledQueuesInitialized;
+  Atomic<uint32_t> mNumOfIndexedDBTransactions;
+  Atomic<uint32_t> mNumOfIndexedDBDatabases;
   const bool mIsChrome;
 
   // Main thread only
   DocGroupMap mDocGroups;
   nsTArray<nsPIDOMWindowOuter*> mWindows;
   uint32_t mForegroundCount;
 };
 
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -263,17 +263,18 @@ NS_IMPL_ISUPPORTS(WebSocketImpl,
                   nsISupportsWeakReference,
                   nsIRequest,
                   nsIEventTarget)
 
 class CallDispatchConnectionCloseEvents final : public CancelableRunnable
 {
 public:
   explicit CallDispatchConnectionCloseEvents(WebSocketImpl* aWebSocketImpl)
-    : mWebSocketImpl(aWebSocketImpl)
+    : CancelableRunnable("dom::CallDispatchConnectionCloseEvents")
+    , mWebSocketImpl(aWebSocketImpl)
   {
     aWebSocketImpl->AssertIsOnTargetThread();
   }
 
   NS_IMETHOD Run() override
   {
     mWebSocketImpl->AssertIsOnTargetThread();
     mWebSocketImpl->DispatchConnectionCloseEvents();
@@ -399,19 +400,21 @@ WebSocketImpl::PrintErrorOnConsole(const
   NS_ENSURE_SUCCESS_VOID(rv);
 }
 
 namespace {
 
 class CancelWebSocketRunnable final : public Runnable
 {
 public:
-  CancelWebSocketRunnable(nsIWebSocketChannel* aChannel, uint16_t aReasonCode,
+  CancelWebSocketRunnable(nsIWebSocketChannel* aChannel,
+                          uint16_t aReasonCode,
                           const nsACString& aReasonString)
-    : mChannel(aChannel)
+    : Runnable("dom::CancelWebSocketRunnable")
+    , mChannel(aChannel)
     , mReasonCode(aReasonCode)
     , mReasonString(aReasonString)
   {}
 
   NS_IMETHOD Run() override
   {
     nsresult rv = mChannel->Close(mReasonCode, mReasonString);
     if (NS_FAILED(rv)) {
@@ -453,17 +456,18 @@ private:
 };
 
 class CloseConnectionRunnable final : public Runnable
 {
 public:
   CloseConnectionRunnable(WebSocketImpl* aImpl,
                           uint16_t aReasonCode,
                           const nsACString& aReasonString)
-    : mImpl(aImpl)
+    : Runnable("dom::CloseConnectionRunnable")
+    , mImpl(aImpl)
     , mReasonCode(aReasonCode)
     , mReasonString(aReasonString)
   {}
 
   NS_IMETHOD Run() override
   {
     return mImpl->CloseConnection(mReasonCode, mReasonString);
   }
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -280,18 +280,19 @@ nsContentSink::ProcessHTTPHeaders(nsICha
   if (NS_SUCCEEDED(rv) && !linkHeader.IsEmpty()) {
     mDocument->SetHeaderData(nsGkAtoms::link,
                              NS_ConvertASCIItoUTF16(linkHeader));
 
     NS_ASSERTION(!mProcessLinkHeaderEvent.get(),
                  "Already dispatched an event?");
 
     mProcessLinkHeaderEvent =
-      NewNonOwningRunnableMethod(this,
-        &nsContentSink::DoProcessLinkHeader);
+      NewNonOwningRunnableMethod("nsContentSink::DoProcessLinkHeader",
+                                 this,
+                                 &nsContentSink::DoProcessLinkHeader);
     rv = NS_DispatchToCurrentThread(mProcessLinkHeaderEvent.get());
     if (NS_FAILED(rv)) {
       mProcessLinkHeaderEvent.Forget();
     }
   }
   
   return NS_OK;
 }
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -296,16 +296,17 @@ bool nsContentUtils::sIsCustomElementsEn
 bool nsContentUtils::sSendPerformanceTimingNotifications = false;
 bool nsContentUtils::sUseActivityCursor = false;
 bool nsContentUtils::sAnimationsAPICoreEnabled = false;
 bool nsContentUtils::sAnimationsAPIElementAnimateEnabled = false;
 bool nsContentUtils::sGetBoxQuadsEnabled = false;
 bool nsContentUtils::sSkipCursorMoveForSameValueSet = false;
 bool nsContentUtils::sRequestIdleCallbackEnabled = false;
 bool nsContentUtils::sLowerNetworkPriority = false;
+bool nsContentUtils::sShowInputPlaceholderOnFocus = true;
 #ifndef RELEASE_OR_BETA
 bool nsContentUtils::sBypassCSSOMOriginCheck = false;
 #endif
 bool nsContentUtils::sIsScopedStyleEnabled = false;
 
 bool nsContentUtils::sIsBytecodeCacheEnabled = false;
 int32_t nsContentUtils::sBytecodeCacheStrategy = 0;
 nsCString* nsContentUtils::sJSBytecodeMimeType = nullptr;
@@ -708,16 +709,19 @@ nsContentUtils::Init()
 #endif
 
   Preferences::AddBoolVarCache(&sIsScopedStyleEnabled,
                                "layout.css.scoped-style.enabled", false);
 
   Preferences::AddBoolVarCache(&sLowerNetworkPriority,
                                "privacy.trackingprotection.lower_network_priority", false);
 
+  Preferences::AddBoolVarCache(&sShowInputPlaceholderOnFocus,
+                               "dom.placeholder.show_on_focus", true);
+
   Preferences::AddBoolVarCache(&sIsBytecodeCacheEnabled,
                                "dom.script_loader.bytecode_cache.enabled", false);
 
   Preferences::AddIntVarCache(&sBytecodeCacheStrategy,
                               "dom.script_loader.bytecode_cache.strategy", 0);
 
   nsDependentCString buildID(mozilla::PlatformBuildID());
   sJSBytecodeMimeType = new nsCString(NS_LITERAL_CSTRING("javascript/moz-bytecode-") + buildID);
@@ -5304,22 +5308,26 @@ nsContentUtils::IsInSameAnonymousTree(co
       aContent->GetContainingShadow();
   }
 
   return nodeAsContent->GetBindingParent() == aContent->GetBindingParent();
 }
 
 class AnonymousContentDestroyer : public Runnable {
 public:
-  explicit AnonymousContentDestroyer(nsCOMPtr<nsIContent>* aContent) {
+  explicit AnonymousContentDestroyer(nsCOMPtr<nsIContent>* aContent)
+    : mozilla::Runnable("AnonymousContentDestroyer")
+  {
     mContent.swap(*aContent);
     mParent = mContent->GetParent();
     mDoc = mContent->OwnerDoc();
   }
-  explicit AnonymousContentDestroyer(nsCOMPtr<Element>* aElement) {
+  explicit AnonymousContentDestroyer(nsCOMPtr<Element>* aElement)
+    : mozilla::Runnable("AnonymousContentDestroyer")
+  {
     mContent = aElement->forget();
     mParent = mContent->GetParent();
     mDoc = mContent->OwnerDoc();
   }
   NS_IMETHOD Run() override {
     mContent->UnbindFromTree();
     return NS_OK;
   }
@@ -10542,19 +10550,19 @@ nsContentUtils::UserInteractionObserver:
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   obs->AddObserver(this, kUserInteractionInactive, false);
   obs->AddObserver(this, kUserInteractionActive, false);
 
   // We can't register ourselves as an annotator yet, as the HangMonitor hasn't
   // started yet. It will have started by the time we have the chance to spin
   // the event loop.
   RefPtr<UserInteractionObserver> self = this;
-  NS_DispatchToMainThread(NS_NewRunnableFunction([=] () {
-        HangMonitor::RegisterAnnotator(*self);
-      }));
+  NS_DispatchToMainThread(
+    NS_NewRunnableFunction("nsContentUtils::UserInteractionObserver::Init",
+                           [=]() { HangMonitor::RegisterAnnotator(*self); }));
 }
 
 void
 nsContentUtils::UserInteractionObserver::Shutdown()
 {
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->RemoveObserver(this, kUserInteractionInactive);
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -3033,16 +3033,21 @@ public:
    */
   static bool
   GetUserIsInteracting();
 
   // Check pref "privacy.trackingprotection.lower_network_priority" to see
   // if we want to lower the priority of the channel.
   static bool IsLowerNetworkPriority() { return sLowerNetworkPriority; }
 
+  // Check pref "dom.placeholder.show_on_focus" to see
+  // if we want to show the placeholder inside input elements
+  // when they have focus.
+  static bool ShowInputPlaceholderOnFocus() { return sShowInputPlaceholderOnFocus; }
+
   // Check pref "dom.script_loader.bytecode_cache.enabled" to see
   // if we want to cache JS bytecode on the cache entry.
   static bool IsBytecodeCacheEnabled() { return sIsBytecodeCacheEnabled; }
 
   // Check pref "dom.script_loader.bytecode_cache.strategy" to see which
   // heuristic strategy should be used to trigger the caching of the bytecode.
   static int32_t BytecodeCacheStrategy() { return sBytecodeCacheStrategy; }
 
@@ -3192,16 +3197,17 @@ private:
   static bool sSendPerformanceTimingNotifications;
   static bool sUseActivityCursor;
   static bool sAnimationsAPICoreEnabled;
   static bool sAnimationsAPIElementAnimateEnabled;
   static bool sGetBoxQuadsEnabled;
   static bool sSkipCursorMoveForSameValueSet;
   static bool sRequestIdleCallbackEnabled;
   static bool sLowerNetworkPriority;
+  static bool sShowInputPlaceholderOnFocus;
 #ifndef RELEASE_OR_BETA
   static bool sBypassCSSOMOriginCheck;
 #endif
   static bool sIsScopedStyleEnabled;
   static bool sIsBytecodeCacheEnabled;
   static int32_t sBytecodeCacheStrategy;
   static uint32_t sCookiesLifetimePolicy;
   static uint32_t sCookiesBehavior;
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -862,16 +862,17 @@ nsDOMMutationObserver::HandleMutation()
   ClearPendingRecords();
 
   mCallback->Call(this, mutations, *this);
 }
 
 class AsyncMutationHandler : public mozilla::Runnable
 {
 public:
+  AsyncMutationHandler() : mozilla::Runnable("AsyncMutationHandler") {}
   NS_IMETHOD Run() override
   {
     nsDOMMutationObserver::HandleMutations();
     return NS_OK;
   }
 };
 
 void
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1101,59 +1101,76 @@ nsDOMWindowUtils::SendNativeKeyEvent(int
                                      const nsAString& aUnmodifiedCharacters,
                                      nsIObserver* aObserver)
 {
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
     return NS_ERROR_FAILURE;
 
-  NS_DispatchToMainThread(NewRunnableMethod
-    <int32_t, int32_t, uint32_t, nsString, nsString, nsIObserver*>
-    (widget, &nsIWidget::SynthesizeNativeKeyEvent, aNativeKeyboardLayout,
-    aNativeKeyCode, aModifiers, aCharacters, aUnmodifiedCharacters, aObserver));
+  NS_DispatchToMainThread(
+    NewRunnableMethod<int32_t,
+                      int32_t,
+                      uint32_t,
+                      nsString,
+                      nsString,
+                      nsIObserver*>("nsIWidget::SynthesizeNativeKeyEvent",
+                                    widget,
+                                    &nsIWidget::SynthesizeNativeKeyEvent,
+                                    aNativeKeyboardLayout,
+                                    aNativeKeyCode,
+                                    aModifiers,
+                                    aCharacters,
+                                    aUnmodifiedCharacters,
+                                    aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX,
                                        int32_t aScreenY,
                                        int32_t aNativeMessage,
                                        int32_t aModifierFlags,
                                        nsIDOMElement* aElement,
                                        nsIObserver* aObserver)
 {
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
   if (!widget)
     return NS_ERROR_FAILURE;
 
-  NS_DispatchToMainThread(NewRunnableMethod
-    <LayoutDeviceIntPoint, int32_t, int32_t, nsIObserver*>
-    (widget, &nsIWidget::SynthesizeNativeMouseEvent,
-    LayoutDeviceIntPoint(aScreenX, aScreenY), aNativeMessage, aModifierFlags,
-    aObserver));
+  NS_DispatchToMainThread(
+    NewRunnableMethod<LayoutDeviceIntPoint, int32_t, int32_t, nsIObserver*>(
+      "nsIWidget::SynthesizeNativeMouseEvent",
+      widget,
+      &nsIWidget::SynthesizeNativeMouseEvent,
+      LayoutDeviceIntPoint(aScreenX, aScreenY),
+      aNativeMessage,
+      aModifierFlags,
+      aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendNativeMouseMove(int32_t aScreenX,
                                       int32_t aScreenY,
                                       nsIDOMElement* aElement,
                                       nsIObserver* aObserver)
 {
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
   if (!widget)
     return NS_ERROR_FAILURE;
 
-  NS_DispatchToMainThread(NewRunnableMethod
-    <LayoutDeviceIntPoint, nsIObserver*>
-    (widget, &nsIWidget::SynthesizeNativeMouseMove,
-    LayoutDeviceIntPoint(aScreenX, aScreenY), aObserver));
+  NS_DispatchToMainThread(NewRunnableMethod<LayoutDeviceIntPoint, nsIObserver*>(
+    "nsIWidget::SynthesizeNativeMouseMove",
+    widget,
+    &nsIWidget::SynthesizeNativeMouseMove,
+    LayoutDeviceIntPoint(aScreenX, aScreenY),
+    aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendNativeMouseScrollEvent(int32_t aScreenX,
                                              int32_t aScreenY,
                                              uint32_t aNativeMessage,
                                              double aDeltaX,
@@ -1165,21 +1182,35 @@ nsDOMWindowUtils::SendNativeMouseScrollE
                                              nsIObserver* aObserver)
 {
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
   if (!widget) {
     return NS_ERROR_FAILURE;
   }
 
-  NS_DispatchToMainThread(NewRunnableMethod
-    <mozilla::LayoutDeviceIntPoint, uint32_t, double, double, double, uint32_t, uint32_t, nsIObserver*>
-    (widget, &nsIWidget::SynthesizeNativeMouseScrollEvent,
-    LayoutDeviceIntPoint(aScreenX, aScreenY), aNativeMessage, aDeltaX, aDeltaY,
-    aDeltaZ, aModifierFlags, aAdditionalFlags, aObserver));
+  NS_DispatchToMainThread(NewRunnableMethod<mozilla::LayoutDeviceIntPoint,
+                                            uint32_t,
+                                            double,
+                                            double,
+                                            double,
+                                            uint32_t,
+                                            uint32_t,
+                                            nsIObserver*>(
+    "nsIWidget::SynthesizeNativeMouseScrollEvent",
+    widget,
+    &nsIWidget::SynthesizeNativeMouseScrollEvent,
+    LayoutDeviceIntPoint(aScreenX, aScreenY),
+    aNativeMessage,
+    aDeltaX,
+    aDeltaY,
+    aDeltaZ,
+    aModifierFlags,
+    aAdditionalFlags,
+    aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId,
                                        uint32_t aTouchState,
                                        int32_t aScreenX,
                                        int32_t aScreenY,
@@ -1191,53 +1222,69 @@ nsDOMWindowUtils::SendNativeTouchPoint(u
   if (!widget) {
     return NS_ERROR_FAILURE;
   }
 
   if (aPressure < 0 || aPressure > 1 || aOrientation > 359) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  NS_DispatchToMainThread(NewRunnableMethod
-    <uint32_t, nsIWidget::TouchPointerState, LayoutDeviceIntPoint, double, uint32_t, nsIObserver*>
-    (widget, &nsIWidget::SynthesizeNativeTouchPoint, aPointerId,
-    (nsIWidget::TouchPointerState)aTouchState,
-    LayoutDeviceIntPoint(aScreenX, aScreenY),
-    aPressure, aOrientation, aObserver));
+  NS_DispatchToMainThread(
+    NewRunnableMethod<uint32_t,
+                      nsIWidget::TouchPointerState,
+                      LayoutDeviceIntPoint,
+                      double,
+                      uint32_t,
+                      nsIObserver*>("nsIWidget::SynthesizeNativeTouchPoint",
+                                    widget,
+                                    &nsIWidget::SynthesizeNativeTouchPoint,
+                                    aPointerId,
+                                    (nsIWidget::TouchPointerState)aTouchState,
+                                    LayoutDeviceIntPoint(aScreenX, aScreenY),
+                                    aPressure,
+                                    aOrientation,
+                                    aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX,
                                      int32_t aScreenY,
                                      bool aLongTap,
                                      nsIObserver* aObserver)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return NS_ERROR_FAILURE;
   }
 
-  NS_DispatchToMainThread(NewRunnableMethod
-    <LayoutDeviceIntPoint, bool, nsIObserver*>
-    (widget, &nsIWidget::SynthesizeNativeTouchTap,
-    LayoutDeviceIntPoint(aScreenX, aScreenY), aLongTap, aObserver));
+  NS_DispatchToMainThread(
+    NewRunnableMethod<LayoutDeviceIntPoint, bool, nsIObserver*>(
+      "nsIWidget::SynthesizeNativeTouchTap",
+      widget,
+      &nsIWidget::SynthesizeNativeTouchTap,
+      LayoutDeviceIntPoint(aScreenX, aScreenY),
+      aLongTap,
+      aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ClearNativeTouchSequence(nsIObserver* aObserver)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return NS_ERROR_FAILURE;
   }
 
-  NS_DispatchToMainThread(NewRunnableMethod<nsIObserver*>
-    (widget, &nsIWidget::ClearNativeTouchSequence, aObserver));
+  NS_DispatchToMainThread(
+    NewRunnableMethod<nsIObserver*>("nsIWidget::ClearNativeTouchSequence",
+                                    widget,
+                                    &nsIWidget::ClearNativeTouchSequence,
+                                    aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ActivateNativeMenuItemAt(const nsAString& indexString)
 {
   // get the widget to send the event to
   nsCOMPtr<nsIWidget> widget = GetWidget();
--- a/dom/base/nsDocElementCreatedNotificationRunner.h
+++ b/dom/base/nsDocElementCreatedNotificationRunner.h
@@ -13,17 +13,18 @@
 #include "nsContentSink.h"
 #include "nsCOMPtr.h"
 #include "nsIDocument.h"
 
 class nsDocElementCreatedNotificationRunner : public mozilla::Runnable
 {
 public:
   explicit nsDocElementCreatedNotificationRunner(nsIDocument* aDoc)
-    : mDoc(aDoc)
+    : mozilla::Runnable("nsDocElementCreatedNotificationRunner")
+    , mDoc(aDoc)
   {
   }
 
   NS_IMETHOD Run() override
   {
     nsContentSink::NotifyDocElementCreated(mDoc);
     return NS_OK;
   }
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -4438,18 +4438,20 @@ nsDocument::SetStyleSheetApplicableState
     DO_STYLESHEET_NOTIFICATION(StyleSheetApplicableStateChangeEvent,
                                "StyleSheetApplicableStateChanged",
                                mApplicable,
                                aApplicable);
   }
 
   if (!mSSApplicableStateNotificationPending) {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
-    nsCOMPtr<nsIRunnable> notification = NewRunnableMethod(this,
-      &nsDocument::NotifyStyleSheetApplicableStateChanged);
+    nsCOMPtr<nsIRunnable> notification =
+      NewRunnableMethod("nsDocument::NotifyStyleSheetApplicableStateChanged",
+                        this,
+                        &nsDocument::NotifyStyleSheetApplicableStateChanged);
     mSSApplicableStateNotificationPending =
       NS_SUCCEEDED(
         Dispatch("nsDocument::NotifyStyleSheetApplicableStateChanged",
                  TaskCategory::Other, notification.forget()));
   }
 }
 
 void
@@ -5054,17 +5056,19 @@ nsDocument::MaybeEndOutermostXBLUpdate()
   // we're not in an update and it is safe to run scripts.
   if (mUpdateNestLevel == 0 && mInXBLUpdate) {
     if (nsContentUtils::IsSafeToRunScript()) {
       mInXBLUpdate = false;
       BindingManager()->EndOutermostUpdate();
     } else if (!mInDestructor) {
       if (!mMaybeEndOutermostXBLUpdateRunner) {
         mMaybeEndOutermostXBLUpdateRunner =
-          NewRunnableMethod(this, &nsDocument::MaybeEndOutermostXBLUpdate);
+          NewRunnableMethod("nsDocument::MaybeEndOutermostXBLUpdate",
+                            this,
+                            &nsDocument::MaybeEndOutermostXBLUpdate);
       }
       nsContentUtils::AddScriptRunner(mMaybeEndOutermostXBLUpdateRunner);
     }
   }
 }
 
 void
 nsDocument::BeginUpdate(nsUpdateType aUpdateType)
@@ -5385,17 +5389,19 @@ nsDocument::UnblockDOMContentLoaded()
     return;
   }
   mDidFireDOMContentLoaded = true;
 
   MOZ_ASSERT(mReadyState == READYSTATE_INTERACTIVE);
   if (!mSynchronousDOMContentLoaded) {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIRunnable> ev =
-      NewRunnableMethod(this, &nsDocument::DispatchContentLoadedEvents);
+      NewRunnableMethod("nsDocument::DispatchContentLoadedEvents",
+                        this,
+                        &nsDocument::DispatchContentLoadedEvents);
     Dispatch("nsDocument::DispatchContentLoadedEvents", TaskCategory::Other, ev.forget());
   } else {
     DispatchContentLoadedEvents();
   }
 }
 
 void
 nsDocument::ContentStateChanged(nsIContent* aContent, EventStates aStateMask)
@@ -7022,17 +7028,19 @@ nsDocument::NotifyPossibleTitleChange(bo
   if (aBoundTitleElement) {
     mMayHaveTitleElement = true;
   }
   if (mPendingTitleChangeEvent.IsPending())
     return;
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   RefPtr<nsRunnableMethod<nsDocument, void, false>> event =
-    NewNonOwningRunnableMethod(this, &nsDocument::DoNotifyPossibleTitleChange);
+    NewNonOwningRunnableMethod("nsDocument::DoNotifyPossibleTitleChange",
+                               this,
+                               &nsDocument::DoNotifyPossibleTitleChange);
   nsresult rv = Dispatch("nsDocument::DoNotifyPossibleTitleChange",
                          TaskCategory::Other, do_AddRef(event));
   if (NS_SUCCEEDED(rv)) {
     mPendingTitleChangeEvent = event;
   }
 }
 
 void
@@ -7168,17 +7176,19 @@ nsDocument::InitializeFrameLoader(nsFram
     NS_WARNING("Trying to initialize a frame loader while"
                "document is being deleted");
     return NS_ERROR_FAILURE;
   }
 
   mInitializableFrameLoaders.AppendElement(aLoader);
   if (!mFrameLoaderRunner) {
     mFrameLoaderRunner =
-      NewRunnableMethod(this, &nsDocument::MaybeInitializeFinalizeFrameLoaders);
+      NewRunnableMethod("nsDocument::MaybeInitializeFinalizeFrameLoaders",
+                        this,
+                        &nsDocument::MaybeInitializeFinalizeFrameLoaders);
     NS_ENSURE_TRUE(mFrameLoaderRunner, NS_ERROR_OUT_OF_MEMORY);
     nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
   }
   return NS_OK;
 }
 
 nsresult
 nsDocument::FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer)
@@ -7186,17 +7196,19 @@ nsDocument::FinalizeFrameLoader(nsFrameL
   mInitializableFrameLoaders.RemoveElement(aLoader);
   if (mInDestructor) {
     return NS_ERROR_FAILURE;
   }
 
   mFrameLoaderFinalizers.AppendElement(aFinalizer);
   if (!mFrameLoaderRunner) {
     mFrameLoaderRunner =
-      NewRunnableMethod(this, &nsDocument::MaybeInitializeFinalizeFrameLoaders);
+      NewRunnableMethod("nsDocument::MaybeInitializeFinalizeFrameLoaders",
+                        this,
+                        &nsDocument::MaybeInitializeFinalizeFrameLoaders);
     NS_ENSURE_TRUE(mFrameLoaderRunner, NS_ERROR_OUT_OF_MEMORY);
     nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
   }
   return NS_OK;
 }
 
 void
 nsDocument::MaybeInitializeFinalizeFrameLoaders()
@@ -7210,17 +7222,19 @@ nsDocument::MaybeInitializeFinalizeFrame
 
   // We're not in an update, but it is not safe to run scripts, so
   // postpone frameloader initialization and finalization.
   if (!nsContentUtils::IsSafeToRunScript()) {
     if (!mInDestructor && !mFrameLoaderRunner &&
         (mInitializableFrameLoaders.Length() ||
          mFrameLoaderFinalizers.Length())) {
       mFrameLoaderRunner =
-        NewRunnableMethod(this, &nsDocument::MaybeInitializeFinalizeFrameLoaders);
+        NewRunnableMethod("nsDocument::MaybeInitializeFinalizeFrameLoaders",
+                          this,
+                          &nsDocument::MaybeInitializeFinalizeFrameLoaders);
       nsContentUtils::AddScriptRunner(mFrameLoaderRunner);
     }
     return;
   }
   mFrameLoaderRunner = nullptr;
 
   // Don't use a temporary array for mInitializableFrameLoaders, because
   // loading a frame may cause some other frameloader to be removed from the
@@ -8787,18 +8801,18 @@ nsDocument::BlockOnload()
   // If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
   // -- it's not ours.
   if (mOnloadBlockCount == 0 && mScriptGlobalObject) {
     if (!nsContentUtils::IsSafeToRunScript()) {
       // Because AddRequest may lead to OnStateChange calls in chrome,
       // block onload only when there are no script blockers.
       ++mAsyncOnloadBlockCount;
       if (mAsyncOnloadBlockCount == 1) {
-        nsContentUtils::AddScriptRunner(
-          NewRunnableMethod(this, &nsDocument::AsyncBlockOnload));
+        nsContentUtils::AddScriptRunner(NewRunnableMethod(
+          "nsDocument::AsyncBlockOnload", this, &nsDocument::AsyncBlockOnload));
       }
       return;
     }
     nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
     if (loadGroup) {
       loadGroup->AddRequest(mOnloadBlocker, nullptr);
     }
   }
@@ -8845,17 +8859,21 @@ nsDocument::UnblockOnload(bool aFireSync
                                  false);
       asyncDispatcher->PostDOMEvent();
     }
   }
 }
 
 class nsUnblockOnloadEvent : public Runnable {
 public:
-  explicit nsUnblockOnloadEvent(nsDocument* aDoc) : mDoc(aDoc) {}
+  explicit nsUnblockOnloadEvent(nsDocument* aDoc)
+    : mozilla::Runnable("nsUnblockOnloadEvent")
+    , mDoc(aDoc)
+  {
+  }
   NS_IMETHOD Run() override {
     mDoc->DoUnblockOnload();
     return NS_OK;
   }
 private:
   RefPtr<nsDocument> mDoc;
 };
 
@@ -9727,16 +9745,17 @@ nsDocument::LoadChromeSheetSync(nsIURI* 
                  : css::eAuthorSheetFeatures;
   return CSSLoader()->LoadSheetSync(uri, mode, isAgentSheet, aSheet);
 }
 
 class nsDelayedEventDispatcher : public Runnable
 {
 public:
   explicit nsDelayedEventDispatcher(nsTArray<nsCOMPtr<nsIDocument>>& aDocuments)
+    : mozilla::Runnable("nsDelayedEventDispatcher")
   {
     mDocuments.SwapElements(aDocuments);
   }
   virtual ~nsDelayedEventDispatcher() {}
 
   NS_IMETHOD Run() override
   {
     FireOrClearDelayedEvents(mDocuments, true);
@@ -9972,17 +9991,19 @@ nsIDocument::RegisterPendingLinkUpdate(L
   if (aLink->HasPendingLinkUpdate()) {
     return;
   }
 
   aLink->SetHasPendingLinkUpdate();
 
   if (!mHasLinksToUpdateRunnable) {
     nsCOMPtr<nsIRunnable> event =
-      NewRunnableMethod(this, &nsIDocument::FlushPendingLinkUpdatesFromRunnable);
+      NewRunnableMethod("nsIDocument::FlushPendingLinkUpdatesFromRunnable",
+                        this,
+                        &nsIDocument::FlushPendingLinkUpdatesFromRunnable);
     // Do this work in a second in the worst case.
     nsresult rv =
       NS_IdleDispatchToCurrentThread(event.forget(), 1000);
     if (NS_FAILED(rv)) {
       // If during shutdown posting a runnable doesn't succeed, we probably
       // don't need to update link states.
       return;
     }
@@ -10894,17 +10915,20 @@ AskWindowToExitFullscreen(nsIDocument* a
     }
   }
 }
 
 class nsCallExitFullscreen : public Runnable
 {
 public:
   explicit nsCallExitFullscreen(nsIDocument* aDoc)
-    : mDoc(aDoc) {}
+    : mozilla::Runnable("nsCallExitFullscreen")
+    , mDoc(aDoc)
+  {
+  }
 
   NS_IMETHOD Run() override final
   {
     if (!mDoc) {
       FullscreenRoots::ForEach(&AskWindowToExitFullscreen);
     } else {
       AskWindowToExitFullscreen(mDoc);
     }
@@ -10974,17 +10998,20 @@ ResetFullScreen(nsIDocument* aDocument, 
 
 // Since nsIDocument::ExitFullscreenInDocTree() could be called from
 // Element::UnbindFromTree() where it is not safe to synchronously run
 // script. This runnable is the script part of that function.
 class ExitFullscreenScriptRunnable : public Runnable
 {
 public:
   explicit ExitFullscreenScriptRunnable(nsCOMArray<nsIDocument>&& aDocuments)
-    : mDocuments(Move(aDocuments)) { }
+    : mozilla::Runnable("ExitFullscreenScriptRunnable")
+    , mDocuments(Move(aDocuments))
+  {
+  }
 
   NS_IMETHOD Run() override
   {
     // Dispatch MozDOMFullscreen:Exited to the last document in
     // the list since we want this event to follow the same path
     // MozDOMFullscreen:Entered dispatched.
     nsIDocument* lastDocument = mDocuments[mDocuments.Length() - 1];
     nsContentUtils::DispatchEventOnlyToChrome(
@@ -11168,17 +11195,20 @@ nsDocument::RestorePreviousFullScreenSta
       /* Bubbles */ true, /* ChromeOnly */ true);
   }
 }
 
 class nsCallRequestFullScreen : public Runnable
 {
 public:
   explicit nsCallRequestFullScreen(UniquePtr<FullscreenRequest>&& aRequest)
-    : mRequest(Move(aRequest)) { }
+    : mozilla::Runnable("nsCallRequestFullScreen")
+    , mRequest(Move(aRequest))
+  {
+  }
 
   NS_IMETHOD Run() override
   {
     mRequest->GetDocument()->RequestFullScreen(Move(mRequest));
     return NS_OK;
   }
 
   UniquePtr<FullscreenRequest> mRequest;
@@ -11898,17 +11928,18 @@ DispatchPointerLockError(nsIDocument* aT
                                   nsContentUtils::eDOM_PROPERTIES,
                                   aMessage);
 }
 
 class PointerLockRequest final : public Runnable
 {
 public:
   PointerLockRequest(Element* aElement, bool aUserInputOrChromeCaller)
-    : mElement(do_GetWeakReference(aElement))
+    : mozilla::Runnable("PointerLockRequest")
+    , mElement(do_GetWeakReference(aElement))
     , mDocument(do_GetWeakReference(aElement->OwnerDoc()))
     , mUserInputOrChromeCaller(aUserInputOrChromeCaller)
   {}
 
   NS_IMETHOD Run() final;
 
 private:
   nsWeakPtr mElement;
@@ -12249,17 +12280,19 @@ nsDocument::GetVisibilityState() const
 
   return dom::VisibilityState::Visible;
 }
 
 /* virtual */ void
 nsDocument::PostVisibilityUpdateEvent()
 {
   nsCOMPtr<nsIRunnable> event =
-    NewRunnableMethod(this, &nsDocument::UpdateVisibilityState);
+    NewRunnableMethod("nsDocument::UpdateVisibilityState",
+                      this,
+                      &nsDocument::UpdateVisibilityState);
   Dispatch("nsDocument::UpdateVisibilityState", TaskCategory::Other, event.forget());
 }
 
 void
 nsDocument::MaybeActiveMediaComponents()
 {
   if (!mWindow) {
     return;
@@ -12794,17 +12827,19 @@ nsDocument::UpdateIntersectionObservatio
 void
 nsDocument::ScheduleIntersectionObserverNotification()
 {
   if (mIntersectionObservers.IsEmpty()) {
     return;
   }
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   nsCOMPtr<nsIRunnable> notification =
-    NewRunnableMethod(this, &nsDocument::NotifyIntersectionObservers);
+    NewRunnableMethod("nsDocument::NotifyIntersectionObservers",
+                      this,
+                      &nsDocument::NotifyIntersectionObservers);
   Dispatch("nsDocument::IntersectionObserverNotification", TaskCategory::Other,
            notification.forget());
 }
 
 void
 nsDocument::NotifyIntersectionObservers()
 {
   nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
@@ -13084,17 +13119,19 @@ nsIDocument::RebuildUserFontSet()
   // and lazily rebuilding it isn't sufficient, since it is only the act
   // of rebuilding it that will trigger the style change reflow that
   // calls GetUserFontSet.  (This reflow causes rebuilding of text runs,
   // which starts font loads, whose completion causes another style
   // change reflow).
   if (!mPostedFlushUserFontSet) {
     MOZ_RELEASE_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIRunnable> ev =
-      NewRunnableMethod(this, &nsIDocument::HandleRebuildUserFontSet);
+      NewRunnableMethod("nsIDocument::HandleRebuildUserFontSet",
+                        this,
+                        &nsIDocument::HandleRebuildUserFontSet);
     if (NS_SUCCEEDED(Dispatch("nsIDocument::HandleRebuildUserFontSet",
                               TaskCategory::Other, ev.forget()))) {
       mPostedFlushUserFontSet = true;
     }
   }
 }
 
 FontFaceSet*
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -2016,20 +2016,24 @@ nsFocusManager::Focus(nsPIDOMWindowOuter
 
   if (clearFirstFocusEvent)
     mFirstFocusEvent = nullptr;
 }
 
 class FocusBlurEvent : public Runnable
 {
 public:
-  FocusBlurEvent(nsISupports* aTarget, EventMessage aEventMessage,
-                 nsPresContext* aContext, bool aWindowRaised,
-                 bool aIsRefocus, EventTarget* aRelatedTarget)
-    : mTarget(aTarget)
+  FocusBlurEvent(nsISupports* aTarget,
+                 EventMessage aEventMessage,
+                 nsPresContext* aContext,
+                 bool aWindowRaised,
+                 bool aIsRefocus,
+                 EventTarget* aRelatedTarget)
+    : mozilla::Runnable("FocusBlurEvent")
+    , mTarget(aTarget)
     , mContext(aContext)
     , mEventMessage(aEventMessage)
     , mWindowRaised(aWindowRaised)
     , mIsRefocus(aIsRefocus)
     , mRelatedTarget(aRelatedTarget)
   {
   }
 
@@ -2050,22 +2054,24 @@ public:
   bool                    mWindowRaised;
   bool                    mIsRefocus;
   nsCOMPtr<EventTarget>   mRelatedTarget;
 };
 
 class FocusInOutEvent : public Runnable
 {
 public:
-  FocusInOutEvent(nsISupports* aTarget, EventMessage aEventMessage,
-                 nsPresContext* aContext,
-                 nsPIDOMWindowOuter* aOriginalFocusedWindow,
-                 nsIContent* aOriginalFocusedContent,
-                 EventTarget* aRelatedTarget)
-    : mTarget(aTarget)
+  FocusInOutEvent(nsISupports* aTarget,
+                  EventMessage aEventMessage,
+                  nsPresContext* aContext,
+                  nsPIDOMWindowOuter* aOriginalFocusedWindow,
+                  nsIContent* aOriginalFocusedContent,
+                  EventTarget* aRelatedTarget)
+    : mozilla::Runnable("FocusInOutEvent")
+    , mTarget(aTarget)
     , mContext(aContext)
     , mEventMessage(aEventMessage)
     , mOriginalFocusedWindow(aOriginalFocusedWindow)
     , mOriginalFocusedContent(aOriginalFocusedContent)
     , mRelatedTarget(aRelatedTarget)
   {
   }
 
@@ -2259,18 +2265,18 @@ nsFocusManager::RaiseWindow(nsPIDOMWindo
 
   if (sTestMode) {
     // In test mode, emulate the existing window being lowered and the new
     // window being raised. This happens in a separate runnable to avoid
     // touching multiple windows in the current runnable.
     nsCOMPtr<nsPIDOMWindowOuter> active(mActiveWindow);
     nsCOMPtr<nsPIDOMWindowOuter> window(aWindow);
     RefPtr<nsFocusManager> self(this);
-    NS_DispatchToCurrentThread(
-      NS_NewRunnableFunction([self, active, window] () -> void {
+    NS_DispatchToCurrentThread(NS_NewRunnableFunction(
+      "nsFocusManager::RaiseWindow", [self, active, window]() -> void {
         if (active) {
           self->WindowLowered(active);
         }
         self->WindowRaised(window);
       }));
     return;
   }
 
@@ -3618,16 +3624,17 @@ nsFocusManager::GetFocusInSelection(nsPI
   }
   while (selectionNode && selectionNode != endSelectionNode);
 }
 
 class PointerUnlocker : public Runnable
 {
 public:
   PointerUnlocker()
+    : mozilla::Runnable("PointerUnlocker")
   {
     MOZ_ASSERT(!PointerUnlocker::sActiveUnlocker);
     PointerUnlocker::sActiveUnlocker = this;
   }
 
   ~PointerUnlocker()
   {
     if (PointerUnlocker::sActiveUnlocker == this) {
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -1980,17 +1980,21 @@ class nsFrameLoaderDestroyRunnable : pub
     eDestroyComplete
   };
 
   RefPtr<nsFrameLoader> mFrameLoader;
   DestroyPhase mPhase;
 
 public:
   explicit nsFrameLoaderDestroyRunnable(nsFrameLoader* aFrameLoader)
-   : mFrameLoader(aFrameLoader), mPhase(eDestroyDocShell) {}
+    : mozilla::Runnable("nsFrameLoaderDestroyRunnable")
+    , mFrameLoader(aFrameLoader)
+    , mPhase(eDestroyDocShell)
+  {
+  }
 
   NS_IMETHOD Run() override;
 };
 
 void
 nsFrameLoader::StartDestroy()
 {
   // nsFrameLoader::StartDestroy is called just before the frameloader is
@@ -2065,19 +2069,20 @@ nsFrameLoader::StartDestroy()
   }
 
   // Destroy the other frame loader owners now that we are being destroyed.
   if (mPartialSHistory &&
       mPartialSHistory->GetActiveState() == nsIPartialSHistory::STATE_ACTIVE) {
     nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
     GetGroupedSHistory(getter_AddRefs(groupedSHistory));
     if (groupedSHistory) {
-      NS_DispatchToCurrentThread(NS_NewRunnableFunction([groupedSHistory] () {
-        groupedSHistory->CloseInactiveFrameLoaderOwners();
-      }));
+      NS_DispatchToCurrentThread(NS_NewRunnableFunction(
+        "nsFrameLoader::StartDestroy", [groupedSHistory]() {
+          groupedSHistory->CloseInactiveFrameLoaderOwners();
+        }));
     }
   }
 
   nsCOMPtr<nsIRunnable> destroyRunnable = new nsFrameLoaderDestroyRunnable(this);
   if (mNeedsAsyncDestroy || !doc ||
       NS_FAILED(doc->FinalizeFrameLoader(this, destroyRunnable))) {
     NS_DispatchToCurrentThread(destroyRunnable);
   }
@@ -3161,16 +3166,17 @@ nsFrameLoader::DoLoadMessageManagerScrip
 class nsAsyncMessageToChild : public nsSameProcessAsyncMessageBase,
                               public Runnable
 {
 public:
   nsAsyncMessageToChild(JS::RootingContext* aRootingCx,
                         JS::Handle<JSObject*> aCpows,
                         nsFrameLoader* aFrameLoader)
     : nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
+    , mozilla::Runnable("nsAsyncMessageToChild")
     , mFrameLoader(aFrameLoader)
   {
   }
 
   NS_IMETHOD Run() override
   {
     nsInProcessTabChildGlobal* tabChild =
       static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -1747,16 +1747,17 @@ nsFrameMessageManager* nsFrameMessageMan
 
 class nsAsyncMessageToSameProcessChild : public nsSameProcessAsyncMessageBase,
                                          public Runnable
 {
 public:
   nsAsyncMessageToSameProcessChild(JS::RootingContext* aRootingCx,
                                    JS::Handle<JSObject*> aCpows)
     : nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
+    , mozilla::Runnable("nsAsyncMessageToSameProcessChild")
   { }
   NS_IMETHOD Run() override
   {
     nsFrameMessageManager* ppm = nsFrameMessageManager::GetChildProcessManager();
     ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm), nullptr, ppm);
     return NS_OK;
   }
 };
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1008,17 +1008,19 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMW
     nsISuspendedTypes::SUSPENDED_BLOCK : nsISuspendedTypes::NONE_SUSPENDED),
   mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false),
   mDesktopModeViewport(false), mIsRootOuterWindow(false), mInnerWindow(nullptr),
   mOuterWindow(aOuterWindow),
   // Make sure no actual window ends up with mWindowID == 0
   mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
   mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
   mLargeAllocStatus(LargeAllocStatus::NONE),
-  mShouldResumeOnFirstActiveMediaComponent(false)
+  mShouldResumeOnFirstActiveMediaComponent(false),
+  mHasTriedToCacheTopInnerWindow(false),
+  mNumOfIndexedDBDatabases(0)
 {
   if (aOuterWindow) {
     mTimeoutManager =
       MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindow::Cast(AsInner()));
   }
 }
 
 template<class T>
@@ -2292,16 +2294,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerRegistrationTable)
 
 #ifdef MOZ_WEBSPEECH
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)
 #endif
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)
 
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopInnerWindow)
+
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
 
   if (tmp->mTimeoutManager) {
     tmp->mTimeoutManager->ForEachUnorderedTimeout([&cb](Timeout* timeout) {
       cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(Timeout));
     });
   }
 
@@ -2382,16 +2386,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mOuterWindow)
   }
 
   if (tmp->mListenerManager) {
     tmp->mListenerManager->Disconnect();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
   }
 
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTopInnerWindow)
+
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
   if (tmp->mApplicationCache) {
     static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())->Disconnect();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
@@ -3030,18 +3036,18 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       nsXBLService::AttachGlobalKeyHandler(mChromeEventHandler);
     }
   }
 
   /* No mDocShell means we're already been partially closed down.  When that
      happens, setting status isn't a big requirement, so don't. (Doesn't happen
      under normal circumstances, but bug 49615 describes a case.) */
 
-  nsContentUtils::AddScriptRunner(
-    NewRunnableMethod(this, &nsGlobalWindow::ClearStatus));
+  nsContentUtils::AddScriptRunner(NewRunnableMethod(
+    "nsGlobalWindow::ClearStatus", this, &nsGlobalWindow::ClearStatus));
 
   // Sometimes, WouldReuseInnerWindow() returns true even if there's no inner
   // window (see bug 776497). Be safe.
   bool reUseInnerWindow = (aForceReuseInnerWindow || wouldReuseInnerWindow) &&
                           GetCurrentInnerWindowInternal();
 
   nsresult rv = NS_OK;
 
@@ -3180,16 +3186,18 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       // Don't free objects on our current inner window if it's going to be
       // held in the bfcache.
       if (!currentInner->IsFrozen()) {
         currentInner->FreeInnerObjects();
       }
     }
 
     mInnerWindow = newInnerWindow->AsInner();
+    MOZ_ASSERT(mInnerWindow);
+    mInnerWindow->TryToCacheTopInnerWindow();
 
     if (!GetWrapperPreserveColor()) {
       JS::Rooted<JSObject*> outer(cx,
         NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
       NS_ENSURE_TRUE(outer, NS_ERROR_FAILURE);
 
       js::SetProxyReservedSlot(outer, 0, js::PrivateValue(ToSupports(this)));
 
@@ -3341,31 +3349,34 @@ nsGlobalWindow::SetNewDocument(nsIDocume
   }
 
   kungFuDeathGrip->DidInitializeContext();
 
   // We wait to fire the debugger hook until the window is all set up and hooked
   // up with the outer. See bug 969156.
   if (createdInnerWindow) {
     nsContentUtils::AddScriptRunner(
-      NewRunnableMethod(newInnerWindow,
+      NewRunnableMethod("nsGlobalWindow::FireOnNewGlobalObject",
+                        newInnerWindow,
                         &nsGlobalWindow::FireOnNewGlobalObject));
   }
 
   if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
     // We should probably notify. However if this is the, arguably bad,
     // situation when we're creating a temporary non-chrome-about-blank
     // document in a chrome docshell, don't notify just yet. Instead wait
     // until we have a real chrome doc.
     if (!mDocShell ||
         mDocShell->ItemType() != nsIDocShellTreeItem::typeChrome ||
         nsContentUtils::IsSystemPrincipal(mDoc->NodePrincipal())) {
       newInnerWindow->mHasNotifiedGlobalCreated = true;
       nsContentUtils::AddScriptRunner(
-        NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated));
+        NewRunnableMethod("nsGlobalWindow::DispatchDOMWindowCreated",
+                          this,
+                          &nsGlobalWindow::DispatchDOMWindowCreated));
     }
   }
 
   PreloadLocalStorage();
 
   // If we have a recorded interesting Large-Allocation header status, report it
   // to the newly attached document.
   ReportLargeAllocStatus();
@@ -4417,16 +4428,77 @@ nsPIDOMWindowInner::TimeoutManager()
 
 bool
 nsPIDOMWindowInner::IsRunningTimeout()
 {
   return TimeoutManager().IsRunningTimeout();
 }
 
 void
+nsPIDOMWindowInner::TryToCacheTopInnerWindow()
+{
+  if (mHasTriedToCacheTopInnerWindow) {
+    return;
+  }
+
+  MOZ_ASSERT(!mInnerObjectsFreed);
+
+  mHasTriedToCacheTopInnerWindow = true;
+
+  nsGlobalWindow* window = nsGlobalWindow::Cast(AsInner());
+
+  MOZ_ASSERT(window);
+
+  if (nsCOMPtr<nsPIDOMWindowOuter> topOutter = window->GetScriptableTop()) {
+    mTopInnerWindow = topOutter->GetCurrentInnerWindow();
+  }
+}
+
+void
+nsPIDOMWindowInner::UpdateActiveIndexedDBTransactionCount(int32_t aDelta)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (aDelta == 0) {
+    return;
+  }
+
+  TabGroup()->IndexedDBTransactionCounter() += aDelta;
+}
+
+void
+nsPIDOMWindowInner::UpdateActiveIndexedDBDatabaseCount(int32_t aDelta)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (aDelta == 0) {
+    return;
+  }
+
+  // We count databases but not transactions because only active databases
+  // could block throttling.
+  uint32_t& counter = mTopInnerWindow ?
+    mTopInnerWindow->mNumOfIndexedDBDatabases : mNumOfIndexedDBDatabases;
+
+  counter+= aDelta;
+
+  TabGroup()->IndexedDBDatabaseCounter() += aDelta;
+}
+
+bool
+nsPIDOMWindowInner::HasActiveIndexedDBDatabases()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  return mTopInnerWindow ?
+    mTopInnerWindow->mNumOfIndexedDBDatabases > 0 :
+    mNumOfIndexedDBDatabases > 0;
+}
+
+void
 nsPIDOMWindowOuter::NotifyCreatedNewMediaComponent()
 {
   // We would only active media component when there is any alive one.
   mShouldResumeOnFirstActiveMediaComponent = true;
 
   // If the document is already on the foreground but the suspend state is still
   // suspend-block, that means the media component was created after calling
   // MaybeActiveMediaComponents, so the window's suspend state doesn't be
@@ -6866,20 +6938,23 @@ GetFullscreenTransitionDuration(bool aEn
            &aDuration->mFadeIn, &aDuration->mFadeOut);
   }
 }
 
 class FullscreenTransitionTask : public Runnable
 {
 public:
   FullscreenTransitionTask(const FullscreenTransitionDuration& aDuration,
-                           nsGlobalWindow* aWindow, bool aFullscreen,
-                           nsIWidget* aWidget, nsIScreen* aScreen,
+                           nsGlobalWindow* aWindow,
+                           bool aFullscreen,
+                           nsIWidget* aWidget,
+                           nsIScreen* aScreen,
                            nsISupports* aTransitionData)
-    : mWindow(aWindow)
+    : mozilla::Runnable("FullscreenTransitionTask")
+    , mWindow(aWindow)
     , mWidget(aWidget)
     , mScreen(aScreen)
     , mTransitionData(aTransitionData)
     , mDuration(aDuration)
     , mStage(eBeforeToggle)
     , mFullscreen(aFullscreen)
   {
   }
@@ -9205,18 +9280,19 @@ nsGlobalWindow::PostMessageMoz(JSContext
                  aSubjectPrincipal, aRv);
 }
 
 class nsCloseEvent : public Runnable {
 
   RefPtr<nsGlobalWindow> mWindow;
   bool mIndirect;
 
-  nsCloseEvent(nsGlobalWindow *aWindow, bool aIndirect)
-    : mWindow(aWindow)
+  nsCloseEvent(nsGlobalWindow* aWindow, bool aIndirect)
+    : mozilla::Runnable("nsCloseEvent")
+    , mWindow(aWindow)
     , mIndirect(aIndirect)
   {}
 
 public:
 
   static nsresult
   PostCloseEvent(nsGlobalWindow* aWindow, bool aIndirect) {
     nsCOMPtr<nsIRunnable> ev = new nsCloseEvent(aWindow, aIndirect);
@@ -9635,21 +9711,21 @@ struct BrowserCompartmentMatcher : publi
     return nsContentUtils::IsSystemOrExpandedPrincipal(pc);
   }
 };
 
 
 class WindowDestroyedEvent final : public Runnable
 {
 public:
-  WindowDestroyedEvent(nsIDOMWindow* aWindow, uint64_t aID,
-                       const char* aTopic) :
-    mID(aID),
-    mPhase(Phase::Destroying),
-    mTopic(aTopic)
+  WindowDestroyedEvent(nsIDOMWindow* aWindow, uint64_t aID, const char* aTopic)
+    : mozilla::Runnable("WindowDestroyedEvent")
+    , mID(aID)
+    , mPhase(Phase::Destroying)
+    , mTopic(aTopic)
   {
     mWindow = do_GetWeakReference(aWindow);
   }
 
   enum class Phase
   {
     Destroying,
     Nuking
@@ -10132,17 +10208,22 @@ nsGlobalWindow::ShowModalDialog(JSContex
 }
 
 class ChildCommandDispatcher : public Runnable
 {
 public:
   ChildCommandDispatcher(nsGlobalWindow* aWindow,
                          nsITabChild* aTabChild,
                          const nsAString& aAction)
-  : mWindow(aWindow), mTabChild(aTabChild), mAction(aAction) {}
+    : mozilla::Runnable("ChildCommandDispatcher")
+    , mWindow(aWindow)
+    , mTabChild(aTabChild)
+    , mAction(aAction)
+  {
+  }
 
   NS_IMETHOD Run() override
   {
     nsCOMPtr<nsPIWindowRoot> root = mWindow->GetTopWindowRoot();
     if (!root) {
       return NS_OK;
     }
 
@@ -10161,17 +10242,21 @@ private:
   nsString                             mAction;
 };
 
 class CommandDispatcher : public Runnable
 {
 public:
   CommandDispatcher(nsIDOMXULCommandDispatcher* aDispatcher,
                     const nsAString& aAction)
-  : mDispatcher(aDispatcher), mAction(aAction) {}
+    : mozilla::Runnable("CommandDispatcher")
+    , mDispatcher(aDispatcher)
+    , mAction(aAction)
+  {
+  }
 
   NS_IMETHOD Run() override
   {
     return mDispatcher->UpdateCommands(mAction);
   }
 
   nsCOMPtr<nsIDOMXULCommandDispatcher> mDispatcher;
   nsString                             mAction;
@@ -10953,20 +11038,21 @@ nsGlobalWindow::PageHidden()
   }
 
   mNeedsFocus = true;
 }
 
 class HashchangeCallback : public Runnable
 {
 public:
-  HashchangeCallback(const nsAString &aOldURL,
-                     const nsAString &aNewURL,
+  HashchangeCallback(const nsAString& aOldURL,
+                     const nsAString& aNewURL,
                      nsGlobalWindow* aWindow)
-    : mWindow(aWindow)
+    : mozilla::Runnable("HashchangeCallback")
+    , mWindow(aWindow)
   {
     MOZ_ASSERT(mWindow);
     MOZ_ASSERT(mWindow->IsInnerWindow());
     mOldURL.Assign(aOldURL);
     mNewURL.Assign(aNewURL);
   }
 
   NS_IMETHOD Run() override
@@ -11569,18 +11655,21 @@ nsGlobalWindow::FireOfflineStatusEventIf
 
 class NotifyIdleObserverRunnable : public Runnable
 {
 public:
   NotifyIdleObserverRunnable(nsIIdleObserver* aIdleObserver,
                              uint32_t aTimeInS,
                              bool aCallOnidle,
                              nsGlobalWindow* aIdleWindow)
-    : mIdleObserver(aIdleObserver), mTimeInS(aTimeInS), mIdleWindow(aIdleWindow),
-      mCallOnidle(aCallOnidle)
+    : mozilla::Runnable("NotifyIdleObserverRunnable")
+    , mIdleObserver(aIdleObserver)
+    , mTimeInS(aTimeInS)
+    , mIdleWindow(aIdleWindow)
+    , mCallOnidle(aCallOnidle)
   { }
 
   NS_IMETHOD Run() override
   {
     if (mIdleWindow->ContainsIdleObserver(mIdleObserver, mTimeInS)) {
       return mCallOnidle ? mIdleObserver->Onidle() : mIdleObserver->Onactive();
     }
     return NS_OK;
@@ -11678,20 +11767,22 @@ nsGlobalWindow::ScheduleNextIdleObserver
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t callbackTimeMS = 0;
   if (idleObserver.mTimeInS * 1000 + mIdleFuzzFactor > userIdleTimeMS) {
     callbackTimeMS = idleObserver.mTimeInS * 1000 - userIdleTimeMS + mIdleFuzzFactor;
   }
 
   mIdleTimer->Cancel();
-  rv = mIdleTimer->InitWithFuncCallback(IdleObserverTimerCallback,
-                                        this,
-                                        callbackTimeMS,
-                                        nsITimer::TYPE_ONE_SHOT);
+  rv = mIdleTimer->InitWithNamedFuncCallback(
+    IdleObserverTimerCallback,
+    this,
+    callbackTimeMS,
+    nsITimer::TYPE_ONE_SHOT,
+    "nsGlobalWindow::ScheduleNextIdleObserverCallback");
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 uint32_t
 nsGlobalWindow::GetFuzzTimeMS()
 {
@@ -11723,20 +11814,22 @@ nsGlobalWindow::ScheduleActiveTimerCallb
   if (!mAddActiveEventFuzzTime) {
     return HandleIdleActiveEvent();
   }
 
   MOZ_ASSERT(mIdleTimer);
   mIdleTimer->Cancel();
 
   uint32_t fuzzFactorInMS = GetFuzzTimeMS();
-  nsresult rv = mIdleTimer->InitWithFuncCallback(IdleActiveTimerCallback,
-                                                 this,
-                                                 fuzzFactorInMS,
-                                                 nsITimer::TYPE_ONE_SHOT);
+  nsresult rv = mIdleTimer->InitWithNamedFuncCallback(
+    IdleActiveTimerCallback,
+    this,
+    fuzzFactorInMS,
+    nsITimer::TYPE_ONE_SHOT,
+    "nsGlobalWindow::ScheduleActiveTimerCallback");
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 nsresult
 nsGlobalWindow::HandleIdleActiveEvent()
 {
   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
@@ -12815,17 +12908,18 @@ public:
     : mWin(aWin)
   {
     MOZ_ASSERT(mWin);
     MOZ_ASSERT(mWin->IsOuterWindow());
   }
   ~AutoUnblockScriptClosing()
   {
     void (nsGlobalWindow::*run)() = &nsGlobalWindow::UnblockScriptedClosing;
-    nsCOMPtr<nsIRunnable> caller = NewRunnableMethod(mWin, run);
+    nsCOMPtr<nsIRunnable> caller = NewRunnableMethod(
+      "AutoUnblockScriptClosing::~AutoUnblockScriptClosing", mWin, run);
     mWin->Dispatch("nsGlobalWindow::UnblockScriptedClosing",
                    TaskCategory::Other, caller.forget());
   }
 };
 
 nsresult
 nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
                              const nsAString& aOptions, bool aDialog,
--- a/dom/base/nsIGlobalObject.cpp
+++ b/dom/base/nsIGlobalObject.cpp
@@ -38,16 +38,17 @@ nsIGlobalObject::UnregisterHostObjectURI
 }
 
 namespace {
 
 class UnlinkHostObjectURIsRunnable final : public mozilla::Runnable
 {
 public:
   explicit UnlinkHostObjectURIsRunnable(nsTArray<nsCString>& aURIs)
+    : mozilla::Runnable("UnlinkHostObjectURIsRunnable")
   {
     mURIs.SwapElements(aURIs);
   }
 
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(NS_IsMainThread());
 
--- a/dom/base/nsInProcessTabChildGlobal.cpp
+++ b/dom/base/nsInProcessTabChildGlobal.cpp
@@ -304,19 +304,25 @@ nsInProcessTabChildGlobal::InitTabChildG
   nsISupports* scopeSupports = NS_ISUPPORTS_CAST(EventTarget*, this);
   NS_ENSURE_STATE(InitChildGlobalInternal(scopeSupports, id));
   return NS_OK;
 }
 
 class nsAsyncScriptLoad : public Runnable
 {
 public:
-    nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild, const nsAString& aURL,
-                      bool aRunInGlobalScope)
-      : mTabChild(aTabChild), mURL(aURL), mRunInGlobalScope(aRunInGlobalScope) {}
+  nsAsyncScriptLoad(nsInProcessTabChildGlobal* aTabChild,
+                    const nsAString& aURL,
+                    bool aRunInGlobalScope)
+    : mozilla::Runnable("nsAsyncScriptLoad")
+    , mTabChild(aTabChild)
+    , mURL(aURL)
+    , mRunInGlobalScope(aRunInGlobalScope)
+  {
+  }
 
   NS_IMETHOD Run() override
   {
     mTabChild->LoadFrameScript(mURL, mRunInGlobalScope);
     return NS_OK;
   }
   RefPtr<nsInProcessTabChildGlobal> mTabChild;
   nsString mURL;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -609,17 +609,18 @@ NS_HandleScriptError(nsIScriptGlobalObje
 
 class ScriptErrorEvent : public Runnable
 {
 public:
   ScriptErrorEvent(nsPIDOMWindowInner* aWindow,
                    JS::RootingContext* aRootingCx,
                    xpc::ErrorReport* aReport,
                    JS::Handle<JS::Value> aError)
-    : mWindow(aWindow)
+    : mozilla::Runnable("ScriptErrorEvent")
+    , mWindow(aWindow)
     , mReport(aReport)
     , mError(aRootingCx, aError)
   {}
 
   NS_IMETHOD Run() override
   {
     nsEventStatus status = nsEventStatus_eIgnore;
     nsPIDOMWindowInner* win = mWindow;
@@ -2389,17 +2390,21 @@ nsJSContext::KillICCRunner()
   }
 }
 
 class NotifyGCEndRunnable : public Runnable
 {
   nsString mMessage;
 
 public:
-  explicit NotifyGCEndRunnable(const nsString& aMessage) : mMessage(aMessage) {}
+  explicit NotifyGCEndRunnable(const nsString& aMessage)
+    : mozilla::Runnable("NotifyGCEndRunnable")
+    , mMessage(aMessage)
+  {
+  }
 
   NS_DECL_NSIRUNNABLE
 };
 
 NS_IMETHODIMP
 NotifyGCEndRunnable::Run()
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -2714,17 +2719,18 @@ class AsyncTaskRunnable final : public R
 {
   ~AsyncTaskRunnable()
   {
     MOZ_ASSERT(!mTask);
   }
 
 public:
   explicit AsyncTaskRunnable(JS::AsyncTask* aTask)
-    : mTask(aTask)
+    : mozilla::Runnable("AsyncTaskRunnable")
+    , mTask(aTask)
   {
     MOZ_ASSERT(mTask);
   }
 
 protected:
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(NS_IsMainThread());
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -174,17 +174,18 @@ nsScriptNameSpaceManager* GetNameSpaceMa
 nsScriptNameSpaceManager* PeekNameSpaceManager();
 
 // Runnable that's used to do async error reporting
 class AsyncErrorReporter final : public mozilla::Runnable
 {
 public:
   // aWindow may be null if this error report is not associated with a window
   explicit AsyncErrorReporter(xpc::ErrorReport* aReport)
-    : mReport(aReport)
+    : Runnable("dom::AsyncErrorReporter")
+    , mReport(aReport)
   {}
 
   NS_IMETHOD Run() override
   {
     mReport->LogToConsole();
     return NS_OK;
   }
 
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -274,27 +274,29 @@ public:
     , mTarget(aTarget)
     , mDocument(aTarget->GetComposedDoc())
     , mEvent(aEvent)
   {
     MOZ_ASSERT(aTarget && mDocument);
   }
 
   nsSimplePluginEvent(nsIDocument* aTarget, const nsAString& aEvent)
-    : mTarget(aTarget)
+    : mozilla::Runnable("nsSimplePluginEvent")
+    , mTarget(aTarget)
     , mDocument(aTarget)
     , mEvent(aEvent)
   {
     MOZ_ASSERT(aTarget);
   }
 
   nsSimplePluginEvent(nsIContent* aTarget,
                       nsIDocument* aDocument,
                       const nsAString& aEvent)
-    : mTarget(aTarget)
+    : mozilla::Runnable("nsSimplePluginEvent")
+    , mTarget(aTarget)
     , mDocument(aDocument)
     , mEvent(aEvent)
   {
     MOZ_ASSERT(aTarget && aDocument);
   }
 
   ~nsSimplePluginEvent() override = default;
 
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -759,16 +759,28 @@ protected:
   // testing.
   bool mServiceWorkersTestingEnabled;
 
   mozilla::dom::LargeAllocStatus mLargeAllocStatus; // Outer window only
 
   // When there is any created alive media component, we can consider to resume
   // the media content in the window.
   bool mShouldResumeOnFirstActiveMediaComponent;
+
+  // mTopInnerWindow is only used on inner windows for tab-wise check by timeout
+  // throttling. It could be null.
+  nsCOMPtr<nsPIDOMWindowInner> mTopInnerWindow;
+
+  // The evidence that we have tried to cache mTopInnerWindow only once from
+  // SetNewDocument(). Note: We need this extra flag because mTopInnerWindow
+  // could be null and we don't want it to be set multiple times.
+  bool mHasTriedToCacheTopInnerWindow;
+
+  // The number of active IndexedDB databases. Inner window only.
+  uint32_t mNumOfIndexedDBDatabases;
 };
 
 #define NS_PIDOMWINDOWINNER_IID \
 { 0x775dabc9, 0x8f43, 0x4277, \
   { 0x9a, 0xdb, 0xf1, 0x99, 0x0d, 0x77, 0xcf, 0xfb } }
 
 #define NS_PIDOMWINDOWOUTER_IID \
   { 0x769693d4, 0xb009, 0x4fe2, \
@@ -909,16 +921,29 @@ public:
   bool IsPlayingAudio();
 
   bool IsDocumentLoaded() const;
 
   mozilla::dom::TimeoutManager& TimeoutManager();
 
   bool IsRunningTimeout();
 
+  // To cache top inner-window if available after constructed for tab-wised
+  // indexedDB counters.
+  void TryToCacheTopInnerWindow();
+
+  // Increase/Decrease the number of active IndexedDB transactions/databases for
+  // the decision making of TabGroup scheduling and timeout-throttling.
+  void UpdateActiveIndexedDBTransactionCount(int32_t aDelta);
+  void UpdateActiveIndexedDBDatabaseCount(int32_t aDelta);
+
+  // Return true if there is any active IndexedDB databases which could block
+  // timeout-throttling.
+  bool HasActiveIndexedDBDatabases();
+
 protected:
   void CreatePerformanceObjectIfNeeded();
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowInner, NS_PIDOMWINDOWINNER_IID)
 
 // NB: It's very very important that these two classes have identical vtables
 // and memory layout!
--- a/dom/base/nsReferencedElement.h
+++ b/dom/base/nsReferencedElement.h
@@ -124,18 +124,22 @@ private:
     nsReferencedElement* mTarget;
   };
 
   class ChangeNotification : public mozilla::Runnable,
                              public Notification
   {
   public:
     ChangeNotification(nsReferencedElement* aTarget,
-                       Element* aFrom, Element* aTo)
-      : Notification(aTarget), mFrom(aFrom), mTo(aTo)
+                       Element* aFrom,
+                       Element* aTo)
+      : mozilla::Runnable("nsReferencedElement::ChangeNotification")
+      , Notification(aTarget)
+      , mFrom(aFrom)
+      , mTo(aTo)
     {}
 
     NS_DECL_ISUPPORTS_INHERITED
     NS_IMETHOD Run() override {
       if (mTarget) {
         mTarget->mPendingNotification = nullptr;
         mTarget->ElementChanged(mFrom, mTo);
       }
--- a/dom/base/nsTextNode.cpp
+++ b/dom/base/nsTextNode.cpp
@@ -268,17 +268,18 @@ nsAttributeTextNode::AttributeChanged(ns
                                       const nsAttrValue* aOldValue)
 {
   if (aNameSpaceID == mNameSpaceID && aAttribute == mAttrName &&
       aElement == mGrandparent) {
     // Since UpdateText notifies, do it when it's safe to run script.  Note
     // that if we get unbound while the event is up that's ok -- we'll just
     // have no grandparent when it fires, and will do nothing.
     void (nsAttributeTextNode::*update)() = &nsAttributeTextNode::UpdateText;
-    nsContentUtils::AddScriptRunner(NewRunnableMethod(this, update));
+    nsContentUtils::AddScriptRunner(
+      NewRunnableMethod("nsAttributeTextNode::AttributeChanged", this, update));
   }
 }
 
 void
 nsAttributeTextNode::NodeWillBeDestroyed(const nsINode* aNode)
 {
   NS_ASSERTION(aNode == static_cast<nsINode*>(mGrandparent), "Wrong node!");
   mGrandparent = nullptr;
--- a/dom/bindings/TypedArray.h
+++ b/dom/bindings/TypedArray.h
@@ -40,17 +40,17 @@ protected:
     aOther.mTypedObj = nullptr;
     aOther.mWrappedObj = nullptr;
   }
 
 public:
   inline void TraceSelf(JSTracer* trc)
   {
     JS::UnsafeTraceRoot(trc, &mTypedObj, "TypedArray.mTypedObj");
-    JS::UnsafeTraceRoot(trc, &mTypedObj, "TypedArray.mWrappedObj");
+    JS::UnsafeTraceRoot(trc, &mWrappedObj, "TypedArray.mWrappedObj");
   }
 
 private:
   TypedArrayObjectStorage(const TypedArrayObjectStorage&) = delete;
 };
 
 /*
  * Various typed array classes for argument conversion.  We have a base class
--- a/dom/cache/Context.cpp
+++ b/dom/cache/Context.cpp
@@ -731,34 +731,39 @@ Context::ThreadsafeHandle::AllowToClose(
 {
   if (mOwningEventTarget->IsOnCurrentThread()) {
     AllowToCloseOnOwningThread();
     return;
   }
 
   // Dispatch is guaranteed to succeed here because we block shutdown until
   // all Contexts have been destroyed.
-  nsCOMPtr<nsIRunnable> runnable =
-    NewRunnableMethod(this, &ThreadsafeHandle::AllowToCloseOnOwningThread);
+  nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod(
+    "dom::cache::Context::ThreadsafeHandle::AllowToCloseOnOwningThread",
+    this,
+    &ThreadsafeHandle::AllowToCloseOnOwningThread);
   MOZ_ALWAYS_SUCCEEDS(
     mOwningEventTarget->Dispatch(runnable.forget(), nsIThread::DISPATCH_NORMAL));
 }
 
 void
 Context::ThreadsafeHandle::InvalidateAndAllowToClose()
 {
   if (mOwningEventTarget->IsOnCurrentThread()) {
     InvalidateAndAllowToCloseOnOwningThread();
     return;
   }
 
   // Dispatch is guaranteed to succeed here because we block shutdown until
   // all Contexts have been destroyed.
-  nsCOMPtr<nsIRunnable> runnable =
-    NewRunnableMethod(this, &ThreadsafeHandle::InvalidateAndAllowToCloseOnOwningThread);
+  nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod(
+    "dom::cache::Context::ThreadsafeHandle::"
+    "InvalidateAndAllowToCloseOnOwningThread",
+    this,
+    &ThreadsafeHandle::InvalidateAndAllowToCloseOnOwningThread);
   MOZ_ALWAYS_SUCCEEDS(
     mOwningEventTarget->Dispatch(runnable.forget(), nsIThread::DISPATCH_NORMAL));
 }
 
 Context::ThreadsafeHandle::ThreadsafeHandle(Context* aContext)
   : mStrongRef(aContext)
   , mWeakRef(aContext)
   , mOwningEventTarget(GetCurrentThreadSerialEventTarget())
--- a/dom/cache/Manager.cpp
+++ b/dom/cache/Manager.cpp
@@ -907,17 +907,20 @@ private:
 
   void
   CallOnAsyncCopyCompleteOnTargetThread(nsresult aRv)
   {
     // May be on any thread, including STS event target.  Non-owning runnable
     // here since we are guaranteed the Action will survive until
     // CompleteOnInitiatingThread is called.
     nsCOMPtr<nsIRunnable> runnable = NewNonOwningRunnableMethod<nsresult>(
-      this, &CachePutAllAction::OnAsyncCopyComplete, aRv);
+      "dom::cache::Manager::CachePutAllAction::OnAsyncCopyComplete",
+      this,
+      &CachePutAllAction::OnAsyncCopyComplete,
+      aRv);
     MOZ_ALWAYS_SUCCEEDS(
       mTarget->Dispatch(runnable.forget(), nsIThread::DISPATCH_NORMAL));
   }
 
   void
   DoResolve(nsresult aRv)
   {
     MOZ_ASSERT(mTarget->IsOnCurrentThread());
@@ -1761,17 +1764,18 @@ Manager::~Manager()
   MOZ_DIAGNOSTIC_ASSERT(mState == Closing);
   MOZ_DIAGNOSTIC_ASSERT(!mContext);
 
   nsCOMPtr<nsIThread> ioThread;
   mIOThread.swap(ioThread);
 
   // Don't spin the event loop in the destructor waiting for the thread to
   // shutdown.  Defer this to the main thread, instead.
-  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(NewRunnableMethod(ioThread, &nsIThread::Shutdown)));
+  MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(NewRunnableMethod("nsIThread::Shutdown",
+                                                                ioThread, &nsIThread::Shutdown)));
 }
 
 void
 Manager::Init(Manager* aOldManager)
 {
   NS_ASSERT_OWNINGTHREAD(Manager);
 
   RefPtr<Context> oldContext;
--- a/dom/cache/PrincipalVerifier.cpp
+++ b/dom/cache/PrincipalVerifier.cpp
@@ -60,17 +60,18 @@ PrincipalVerifier::RemoveListener(Listen
   AssertIsOnBackgroundThread();
   MOZ_DIAGNOSTIC_ASSERT(aListener);
   MOZ_ALWAYS_TRUE(mListenerList.RemoveElement(aListener));
 }
 
 PrincipalVerifier::PrincipalVerifier(Listener* aListener,
                                      PBackgroundParent* aActor,
                                      const PrincipalInfo& aPrincipalInfo)
-  : mActor(BackgroundParent::GetContentParent(aActor))
+  : Runnable("dom::cache::PrincipalVerifier")
+  , mActor(BackgroundParent::GetContentParent(aActor))
   , mPrincipalInfo(aPrincipalInfo)
   , mInitiatingEventTarget(GetCurrentThreadSerialEventTarget())
   , mResult(NS_OK)
 {
   AssertIsOnBackgroundThread();
   MOZ_DIAGNOSTIC_ASSERT(mInitiatingEventTarget);
   MOZ_DIAGNOSTIC_ASSERT(aListener);
 
--- a/dom/cache/ReadStream.cpp
+++ b/dom/cache/ReadStream.cpp
@@ -127,17 +127,18 @@ private:
 // Runnable to notify actors that the ReadStream has closed.  This must
 // be done on the thread associated with the PBackground actor.  Must be
 // cancelable to execute on Worker threads (which can occur when the
 // ReadStream is constructed on a child process Worker thread).
 class ReadStream::Inner::NoteClosedRunnable final : public CancelableRunnable
 {
 public:
   explicit NoteClosedRunnable(ReadStream::Inner* aStream)
-    : mStream(aStream)
+    : CancelableRunnable("dom::cache::ReadStream::Inner::NoteClosedRunnable")
+    , mStream(aStream)
   { }
 
   NS_IMETHOD Run() override
   {
     mStream->NoteClosedOnOwningThread();
     mStream = nullptr;
     return NS_OK;
   }
@@ -162,17 +163,18 @@ private:
 // closed.  Since this can trigger actor destruction, we need to do
 // it on the thread associated with the PBackground actor.  Must be
 // cancelable to execute on Worker threads (which can occur when the
 // ReadStream is constructed on a child process Worker thread).
 class ReadStream::Inner::ForgetRunnable final : public CancelableRunnable
 {
 public:
   explicit ForgetRunnable(ReadStream::Inner* aStream)
-    : mStream(aStream)
+    : CancelableRunnable("dom::cache::ReadStream::Inner::ForgetRunnable")
+    , mStream(aStream)
   { }
 
   NS_IMETHOD Run() override
   {
     mStream->ForgetOnOwningThread();
     mStream = nullptr;
     return NS_OK;
   }
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1571,18 +1571,19 @@ void
 CanvasRenderingContext2D::ScheduleStableStateCallback()
 {
   if (mHasPendingStableStateCallback) {
     return;
   }
   mHasPendingStableStateCallback = true;
 
   nsContentUtils::RunInStableState(
-    NewRunnableMethod(this, &CanvasRenderingContext2D::OnStableState)
-  );
+    NewRunnableMethod("dom::CanvasRenderingContext2D::OnStableState",
+                      this,
+                      &CanvasRenderingContext2D::OnStableState));
 }
 
 void
 CanvasRenderingContext2D::OnStableState()
 {
   if (!mHasPendingStableStateCallback) {
     return;
   }
--- a/dom/canvas/ImageBitmap.cpp
+++ b/dom/canvas/ImageBitmap.cpp
@@ -1071,17 +1071,18 @@ private:
   RefPtr<ImageBitmap> mImageBitmap;
 };
 
 class FulfillImageBitmapPromiseTask final : public Runnable,
                                             public FulfillImageBitmapPromise
 {
 public:
   FulfillImageBitmapPromiseTask(Promise* aPromise, ImageBitmap* aImageBitmap)
-  : FulfillImageBitmapPromise(aPromise, aImageBitmap)
+    : Runnable("dom::FulfillImageBitmapPromiseTask")
+    , FulfillImageBitmapPromise(aPromise, aImageBitmap)
   {
   }
 
   NS_IMETHOD Run() override
   {
     DoFulfillImageBitmapPromise();
     return NS_OK;
   }
@@ -1273,17 +1274,18 @@ protected:
 class CreateImageBitmapFromBlobTask final : public Runnable,
                                             public CreateImageBitmapFromBlob
 {
 public:
   CreateImageBitmapFromBlobTask(Promise* aPromise,
                                 nsIGlobalObject* aGlobal,
                                 Blob& aBlob,
                                 const Maybe<IntRect>& aCropRect)
-  :CreateImageBitmapFromBlob(aPromise, aGlobal, aBlob, aCropRect)
+    : Runnable("dom::CreateImageBitmapFromBlobTask")
+    , CreateImageBitmapFromBlob(aPromise, aGlobal, aBlob, aCropRect)
   {
   }
 
   NS_IMETHOD Run() override
   {
     DoCreateImageBitmapFromBlob();
     return NS_OK;
   }
@@ -1727,22 +1729,28 @@ protected:
 };
 
 template<typename T>
 class MapDataIntoBufferSourceTask final : public Runnable,
                                           public MapDataIntoBufferSource<T>
 {
 public:
   MapDataIntoBufferSourceTask(JSContext* aCx,
-                              Promise *aPromise,
-                              ImageBitmap *aImageBitmap,
+                              Promise* aPromise,
+                              ImageBitmap* aImageBitmap,
                               const T& aBuffer,
                               int32_t aOffset,
                               ImageBitmapFormat aFormat)
-  : MapDataIntoBufferSource<T>(aCx, aPromise, aImageBitmap, aBuffer, aOffset, aFormat)
+    : Runnable("dom::MapDataIntoBufferSourceTask")
+    , MapDataIntoBufferSource<T>(aCx,
+                                 aPromise,
+                                 aImageBitmap,
+                                 aBuffer,
+                                 aOffset,
+                                 aFormat)
   {
   }
 
   virtual ~MapDataIntoBufferSourceTask() = default;
 
   NS_IMETHOD Run() override
   {
     MapDataIntoBufferSource<T>::DoMapDataIntoBufferSource();
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1732,19 +1732,20 @@ WebGLContext::RunContextLossTimer()
     mContextLossHandler.RunTimer();
 }
 
 class UpdateContextLossStatusTask : public CancelableRunnable
 {
     RefPtr<WebGLContext> mWebGL;
 
 public:
-    explicit UpdateContextLossStatusTask(WebGLContext* webgl)
-        : mWebGL(webgl)
-    {
+  explicit UpdateContextLossStatusTask(WebGLContext* webgl)
+    : CancelableRunnable("UpdateContextLossStatusTask")
+    , mWebGL(webgl)
+  {
     }
 
     NS_IMETHOD Run() override {
         if (mWebGL)
             mWebGL->UpdateContextLossStatus();
 
         return NS_OK;
     }
--- a/dom/canvas/WebGLQuery.cpp
+++ b/dom/canvas/WebGLQuery.cpp
@@ -13,23 +13,26 @@
 
 namespace mozilla {
 
 class AvailableRunnable final : public Runnable
 {
     const RefPtr<WebGLQuery> mQuery;
 
 public:
-    explicit AvailableRunnable(WebGLQuery* query)
-        : mQuery(query)
-    { }
+  explicit AvailableRunnable(WebGLQuery* query)
+    : Runnable("AvailableRunnable")
+    , mQuery(query)
+  {
+  }
 
-    NS_IMETHOD Run() override {
-        mQuery->mCanBeAvailable = true;
-        return NS_OK;
+  NS_IMETHOD Run() override
+  {
+    mQuery->mCanBeAvailable = true;
+    return NS_OK;
     }
 };
 
 ////
 
 static GLuint
 GenQuery(gl::GLContext* gl)
 {
--- a/dom/events/AsyncEventDispatcher.cpp
+++ b/dom/events/AsyncEventDispatcher.cpp
@@ -17,18 +17,19 @@ namespace mozilla {
 using namespace dom;
 
 /******************************************************************************
  * mozilla::AsyncEventDispatcher
  ******************************************************************************/
 
 AsyncEventDispatcher::AsyncEventDispatcher(EventTarget* aTarget,
                                            WidgetEvent& aEvent)
-  : mTarget(aTarget),
-    mEventMessage(eUnidentifiedEvent)
+  : CancelableRunnable("AsyncEventDispatcher")
+  , mTarget(aTarget)
+  , mEventMessage(eUnidentifiedEvent)
 {
   MOZ_ASSERT(mTarget);
   RefPtr<Event> event =
     EventDispatcher::CreateEvent(aTarget, nullptr, &aEvent, EmptyString());
   mEvent = event.forget();
   mEventType.SetIsVoid(true);
   NS_ASSERTION(mEvent, "Should never fail to create an event");
   mEvent->DuplicatePrivateData();
--- a/dom/events/AsyncEventDispatcher.h
+++ b/dom/events/AsyncEventDispatcher.h
@@ -29,66 +29,73 @@ class AsyncEventDispatcher : public Canc
 {
 public:
   /**
    * If aOnlyChromeDispatch is true, the event is dispatched to only
    * chrome node. In that case, if aTarget is already a chrome node,
    * the event is dispatched to it, otherwise the dispatch path starts
    * at the first chrome ancestor of that target.
    */
-  AsyncEventDispatcher(nsINode* aTarget, const nsAString& aEventType,
-                       bool aBubbles, bool aOnlyChromeDispatch)
-    : mTarget(aTarget)
+  AsyncEventDispatcher(nsINode* aTarget,
+                       const nsAString& aEventType,
+                       bool aBubbles,
+                       bool aOnlyChromeDispatch)
+    : CancelableRunnable("AsyncEventDispatcher")
+    , mTarget(aTarget)
     , mEventType(aEventType)
     , mEventMessage(eUnidentifiedEvent)
     , mBubbles(aBubbles)
     , mOnlyChromeDispatch(aOnlyChromeDispatch)
   {
   }
 
   /**
    * If aOnlyChromeDispatch is true, the event is dispatched to only
    * chrome node. In that case, if aTarget is already a chrome node,
    * the event is dispatched to it, otherwise the dispatch path starts
    * at the first chrome ancestor of that target.
    */
   AsyncEventDispatcher(nsINode* aTarget,
                        mozilla::EventMessage aEventMessage,
                        bool aBubbles, bool aOnlyChromeDispatch)
-    : mTarget(aTarget)
+    : CancelableRunnable("AsyncEventDispatcher")
+    , mTarget(aTarget)
     , mEventMessage(aEventMessage)
     , mBubbles(aBubbles)
     , mOnlyChromeDispatch(aOnlyChromeDispatch)
   {
     mEventType.SetIsVoid(true);
     MOZ_ASSERT(mEventMessage != eUnidentifiedEvent);
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, const nsAString& aEventType,
                        bool aBubbles)
-    : mTarget(aTarget)
+    : CancelableRunnable("AsyncEventDispatcher")
+    , mTarget(aTarget)
     , mEventType(aEventType)
     , mEventMessage(eUnidentifiedEvent)
     , mBubbles(aBubbles)
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget,
                        mozilla::EventMessage aEventMessage,
                        bool aBubbles)
-    : mTarget(aTarget)
+    : CancelableRunnable("AsyncEventDispatcher")
+    , mTarget(aTarget)
     , mEventMessage(aEventMessage)
     , mBubbles(aBubbles)
   {
     mEventType.SetIsVoid(true);
     MOZ_ASSERT(mEventMessage != eUnidentifiedEvent);
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, nsIDOMEvent* aEvent)
-    : mTarget(aTarget)
+    : CancelableRunnable("AsyncEventDispatcher")
+    , mTarget(aTarget)
     , mEvent(aEvent)
     , mEventMessage(eUnidentifiedEvent)
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, WidgetEvent& aEvent);
 
   NS_IMETHOD Run() override;
--- a/dom/events/DataTransferItem.cpp
+++ b/dom/events/DataTransferItem.cpp
@@ -441,19 +441,20 @@ DataTransferItem::GetAsString(FunctionSt
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   // Dispatch the callback to the main thread
   class GASRunnable final : public Runnable
   {
   public:
-    GASRunnable(FunctionStringCallback* aCallback,
-                const nsAString& aStringData)
-      : mCallback(aCallback), mStringData(aStringData)
+    GASRunnable(FunctionStringCallback* aCallback, const nsAString& aStringData)
+      : mozilla::Runnable("GASRunnable")
+      , mCallback(aCallback)
+      , mStringData(aStringData)
     {}
 
     NS_IMETHOD Run() override
     {
       ErrorResult rv;
       mCallback->Call(mStringData, rv);
       NS_WARNING_ASSERTION(!rv.Failed(), "callback failed");
       return rv.StealNSResult();
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1407,19 +1407,22 @@ EventStateManager::CreateClickHoldTimer(
       return;
   }
 
   mClickHoldTimer = do_CreateInstance("@mozilla.org/timer;1");
   if (mClickHoldTimer) {
     int32_t clickHoldDelay =
       Preferences::GetInt("ui.click_hold_context_menus.delay", 500);
     mClickHoldTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::Other));
-    mClickHoldTimer->InitWithFuncCallback(sClickHoldCallback, this,
-                                          clickHoldDelay,
-                                          nsITimer::TYPE_ONE_SHOT);
+    mClickHoldTimer->InitWithNamedFuncCallback(
+      sClickHoldCallback,
+      this,
+      clickHoldDelay,
+      nsITimer::TYPE_ONE_SHOT,
+      "EventStateManager::CreateClickHoldTimer");
   }
 } // CreateClickHoldTimer
 
 //
 // KillClickHoldTimer
 //
 // Stop the timer that would show the context menu dead in its tracks
 //
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -708,22 +708,23 @@ TextComposition::HasEditor() const
   return mEditorBaseWeak && mEditorBaseWeak->IsAlive();
 }
 
 /******************************************************************************
  * TextComposition::CompositionEventDispatcher
  ******************************************************************************/
 
 TextComposition::CompositionEventDispatcher::CompositionEventDispatcher(
-                                               TextComposition* aComposition,
-                                               nsINode* aEventTarget,
-                                               EventMessage aEventMessage,
-                                               const nsAString& aData,
-                                               bool aIsSynthesizedEvent)
-  : mTextComposition(aComposition)
+  TextComposition* aComposition,
+  nsINode* aEventTarget,
+  EventMessage aEventMessage,
+  const nsAString& aData,
+  bool aIsSynthesizedEvent)
+  : Runnable("TextComposition::CompositionEventDispatcher")
+  , mTextComposition(aComposition)
   , mEventTarget(aEventTarget)
   , mData(aData)
   , mEventMessage(aEventMessage)
   , mIsSynthesizedEvent(aIsSynthesizedEvent)
 {
 }
 
 NS_IMETHODIMP
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -428,17 +428,19 @@ private:
 
   private:
     RefPtr<TextComposition> mTextComposition;
     nsCOMPtr<nsINode> mEventTarget;
     nsString mData;
     EventMessage mEventMessage;
     bool mIsSynthesizedEvent;
 
-    CompositionEventDispatcher() : mIsSynthesizedEvent(false) {};
+    CompositionEventDispatcher()
+      : Runnable("TextComposition::CompositionEventDispatcher")
+      , mIsSynthesizedEvent(false){};
   };
 
   /**
    * DispatchCompositionEventRunnable() dispatches a composition event to the
    * content.  Be aware, if you use this method, nsPresShellEventCB isn't used.
    * That means that nsIFrame::HandleEvent() is never called.
    * WARNING: The instance which is managed by IMEStateManager may be
    *          destroyed by this method call.
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -327,18 +327,21 @@ WheelTransaction::SetTimeout()
     nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
     if (!timer) {
       return;
     }
     timer.swap(sTimer);
   }
   sTimer->Cancel();
   DebugOnly<nsresult> rv =
-    sTimer->InitWithFuncCallback(OnTimeout, nullptr, GetTimeoutTime(),
-                                 nsITimer::TYPE_ONE_SHOT);
+    sTimer->InitWithNamedFuncCallback(OnTimeout,
+                                      nullptr,
+                                      GetTimeoutTime(),
+                                      nsITimer::TYPE_ONE_SHOT,
+                                      "WheelTransaction::SetTimeout");
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                        "nsITimer::InitWithFuncCallback failed");
 }
 
 /* static */ LayoutDeviceIntPoint
 WheelTransaction::GetScreenPoint(WidgetGUIEvent* aEvent)
 {
   NS_ASSERTION(aEvent, "aEvent is null");
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -70,17 +70,18 @@ class FetchSignalProxy final : public Fe
   // This runnable propagates changes from the FetchSignal on workers to the
   // FetchSignal on main-thread.
   class FetchSignalProxyRunnable final : public Runnable
   {
     RefPtr<FetchSignalProxy> mProxy;
 
   public:
     explicit FetchSignalProxyRunnable(FetchSignalProxy* aProxy)
-      : mProxy(aProxy)
+      : Runnable("dom::FetchSignalProxy::FetchSignalProxyRunnable")
+      , mProxy(aProxy)
     {}
 
     NS_IMETHOD
     Run() override
     {
       MOZ_ASSERT(NS_IsMainThread());
       FetchSignal* signal = mProxy->GetOrCreateSignalForMainThread();
       signal->Abort();
@@ -259,17 +260,18 @@ private:
 class MainThreadFetchRunnable : public Runnable
 {
   RefPtr<WorkerFetchResolver> mResolver;
   RefPtr<InternalRequest> mRequest;
 
 public:
   MainThreadFetchRunnable(WorkerFetchResolver* aResolver,
                           InternalRequest* aRequest)
-    : mResolver(aResolver)
+    : Runnable("dom::MainThreadFetchRunnable")
+    , mResolver(aResolver)
     , mRequest(aRequest)
   {
     MOZ_ASSERT(mResolver);
   }
 
   NS_IMETHOD
   Run() override
   {
--- a/dom/fetch/FetchConsumer.cpp
+++ b/dom/fetch/FetchConsumer.cpp
@@ -53,17 +53,18 @@ public:
 
 template <class Derived>
 class BeginConsumeBodyRunnable final : public Runnable
 {
   RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer;
 
 public:
   explicit BeginConsumeBodyRunnable(FetchBodyConsumer<Derived>* aConsumer)
-    : mFetchBodyConsumer(aConsumer)
+    : Runnable("BeginConsumeBodyRunnable")
+    , mFetchBodyConsumer(aConsumer)
   { }
 
   NS_IMETHOD
   Run() override
   {
     mFetchBodyConsumer->BeginConsumeBodyMainThread();
     return NS_OK;
   }
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -638,17 +638,18 @@ namespace {
 
 // Runnable to call the observer OnDataAvailable on the main-thread.
 class DataAvailableRunnable final : public Runnable
 {
   RefPtr<FetchDriverObserver> mObserver;
 
 public:
   explicit DataAvailableRunnable(FetchDriverObserver* aObserver)
-    : mObserver(aObserver)
+    : Runnable("dom::DataAvailableRunnable")
+    , mObserver(aObserver)
   {
      MOZ_ASSERT(aObserver);
   }
 
   NS_IMETHOD
   Run() override
   {
     mObserver->OnDataAvailable();
--- a/dom/file/MutableBlobStorage.cpp
+++ b/dom/file/MutableBlobStorage.cpp
@@ -26,17 +26,18 @@ namespace {
 // error must be propagated.
 class BlobCreationDoneRunnable final : public Runnable
 {
 public:
   BlobCreationDoneRunnable(MutableBlobStorage* aBlobStorage,
                            MutableBlobStorageCallback* aCallback,
                            Blob* aBlob,
                            nsresult aRv)
-    : mBlobStorage(aBlobStorage)
+    : Runnable("dom::BlobCreationDoneRunnable")
+    , mBlobStorage(aBlobStorage)
     , mCallback(aCallback)
     , mBlob(aBlob)
     , mRv(aRv)
   {
     MOZ_ASSERT(aBlobStorage);
     MOZ_ASSERT(aCallback);
     MOZ_ASSERT((NS_FAILED(aRv) && !aBlob) ||
                (NS_SUCCEEDED(aRv) && aBlob));
@@ -74,17 +75,18 @@ private:
 };
 
 // This runnable goes back to the main-thread and informs the BlobStorage about
 // the temporary file.
 class FileCreatedRunnable final : public Runnable
 {
 public:
   FileCreatedRunnable(MutableBlobStorage* aBlobStorage, PRFileDesc* aFD)
-    : mBlobStorage(aBlobStorage)
+    : Runnable("dom::FileCreatedRunnable")
+    , mBlobStorage(aBlobStorage)
     , mFD(aFD)
   {
     MOZ_ASSERT(aBlobStorage);
     MOZ_ASSERT(aFD);
   }
 
   NS_IMETHOD
   Run() override
@@ -109,17 +111,18 @@ private:
 };
 
 // This runnable creates the temporary file. When done, FileCreatedRunnable is
 // dispatched back to the main-thread.
 class CreateTemporaryFileRunnable final : public Runnable
 {
 public:
   explicit CreateTemporaryFileRunnable(MutableBlobStorage* aBlobStorage)
-    : mBlobStorage(aBlobStorage)
+    : Runnable("dom::CreateTemporaryFileRunnable")
+    , mBlobStorage(aBlobStorage)
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(XRE_IsParentProcess());
     MOZ_ASSERT(aBlobStorage);
   }
 
   NS_IMETHOD
   Run() override
@@ -143,17 +146,18 @@ private:
   RefPtr<MutableBlobStorage> mBlobStorage;
 };
 
 // Simple runnable to propagate the error to the BlobStorage.
 class ErrorPropagationRunnable final : public Runnable
 {
 public:
   ErrorPropagationRunnable(MutableBlobStorage* aBlobStorage, nsresult aRv)
-    : mBlobStorage(aBlobStorage)
+    : Runnable("dom::ErrorPropagationRunnable")
+    , mBlobStorage(aBlobStorage)
     , mRv(aRv)
   {}
 
   NS_IMETHOD
   Run() override
   {
     mBlobStorage->ErrorPropagated(mRv);
     return NS_OK;
@@ -212,19 +216,22 @@ public:
         new ErrorPropagationRunnable(mBlobStorage, NS_ERROR_FAILURE),
         NS_DISPATCH_NORMAL);
     }
 
     return NS_OK;
   }
 
 private:
-  WriteRunnable(MutableBlobStorage* aBlobStorage, PRFileDesc* aFD,
-                void* aData, uint32_t aLength)
-    : mBlobStorage(aBlobStorage)
+  WriteRunnable(MutableBlobStorage* aBlobStorage,
+                PRFileDesc* aFD,
+                void* aData,
+                uint32_t aLength)
+    : Runnable("dom::WriteRunnable")
+    , mBlobStorage(aBlobStorage)
     , mFD(aFD)
     , mData(aData)
     , mLength(aLength)
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(mBlobStorage);
     MOZ_ASSERT(aFD);
     MOZ_ASSERT(aData);
@@ -242,17 +249,18 @@ private:
 };
 
 // This runnable closes the FD in case something goes wrong or the temporary
 // file is not needed anymore.
 class CloseFileRunnable final : public Runnable
 {
 public:
   explicit CloseFileRunnable(PRFileDesc* aFD)
-    : mFD(aFD)
+    : Runnable("dom::CloseFileRunnable")
+    , mFD(aFD)
   {}
 
   NS_IMETHOD
   Run() override
   {
     MOZ_ASSERT(!NS_IsMainThread());
     PR_Close(mFD);
     mFD = nullptr;
@@ -274,17 +282,18 @@ private:
 // task is to create the blob and inform the callback.
 class CreateBlobRunnable final : public Runnable
 {
 public:
   CreateBlobRunnable(MutableBlobStorage* aBlobStorage,
                      already_AddRefed<nsISupports> aParent,
                      const nsACString& aContentType,
                      already_AddRefed<MutableBlobStorageCallback> aCallback)
-    : mBlobStorage(aBlobStorage)
+    : Runnable("dom::CreateBlobRunnable")
+    , mBlobStorage(aBlobStorage)
     , mParent(aParent)
     , mContentType(aContentType)
     , mCallback(aCallback)
   {
     MOZ_ASSERT(!NS_IsMainThread());
     MOZ_ASSERT(aBlobStorage);
   }
 
@@ -322,17 +331,18 @@ private:
 // it dispatches a CreateBlobRunnable to the main-thread.
 class LastRunnable final : public Runnable
 {
 public:
   LastRunnable(MutableBlobStorage* aBlobStorage,
                nsISupports* aParent,
                const nsACString& aContentType,
                MutableBlobStorageCallback* aCallback)
-    : mBlobStorage(aBlobStorage)
+    : Runnable("dom::LastRunnable")
+    , mBlobStorage(aBlobStorage)
     , mParent(aParent)
     , mContentType(aContentType)
     , mCallback(aCallback)
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(mBlobStorage);
     MOZ_ASSERT(aCallback);
   }
--- a/dom/file/ipc/IPCBlobInputStream.cpp
+++ b/dom/file/ipc/IPCBlobInputStream.cpp
@@ -41,17 +41,18 @@ public:
     mCallback = nullptr;
     mStream = nullptr;
     return NS_OK;
   }
 
 private:
   CallbackRunnable(nsIInputStreamCallback* aCallback,
                    IPCBlobInputStream* aStream)
-    : mCallback(aCallback)
+    : CancelableRunnable("dom::CallbackRunnable")
+    , mCallback(aCallback)
     , mStream(aStream)
   {
     MOZ_ASSERT(mCallback);
     MOZ_ASSERT(mStream);
   }
 
   nsCOMPtr<nsIInputStreamCallback> mCallback;
   RefPtr<IPCBlobInputStream> mStream;
--- a/dom/file/ipc/IPCBlobInputStreamChild.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamChild.cpp
@@ -20,17 +20,18 @@ using namespace workers;
 namespace {
 
 // This runnable is used in case the last stream is forgotten on the 'wrong'
 // thread.
 class ShutdownRunnable final : public CancelableRunnable
 {
 public:
   explicit ShutdownRunnable(IPCBlobInputStreamChild* aActor)
-    : mActor(aActor)
+    : CancelableRunnable("dom::ShutdownRunnable")
+    , mActor(aActor)
   {}
 
   NS_IMETHOD
   Run() override
   {
     mActor->Shutdown();
     return NS_OK;
   }
@@ -40,17 +41,18 @@ private:
 };
 
 // This runnable is used in case StreamNeeded() has been called on a non-owning
 // thread.
 class StreamNeededRunnable final : public CancelableRunnable
 {
 public:
   explicit StreamNeededRunnable(IPCBlobInputStreamChild* aActor)
-    : mActor(aActor)
+    : CancelableRunnable("dom::StreamNeededRunnable")
+    , mActor(aActor)
   {}
 
   NS_IMETHOD
   Run() override
   {
     MOZ_ASSERT(mActor->State() != IPCBlobInputStreamChild::eActiveMigrating &&
                mActor->State() != IPCBlobInputStreamChild::eInactiveMigrating);
     if (mActor->State() == IPCBlobInputStreamChild::eActive) {
@@ -65,17 +67,18 @@ private:
 
 // When the stream has been received from the parent, we inform the
 // IPCBlobInputStream.
 class StreamReadyRunnable final : public CancelableRunnable
 {
 public:
   StreamReadyRunnable(IPCBlobInputStream* aDestinationStream,
                       nsIInputStream* aCreatedStream)
-    : mDestinationStream(aDestinationStream)
+    : CancelableRunnable("dom::StreamReadyRunnable")
+    , mDestinationStream(aDestinationStream)
     , mCreatedStream(aCreatedStream)
   {
     MOZ_ASSERT(mDestinationStream);
     // mCreatedStream can be null.
   }
 
   NS_IMETHOD
   Run() override
@@ -97,18 +100,20 @@ public:
     // We must keep the worker alive until the migration is completed.
     return true;
   }
 };
 
 class ReleaseWorkerHolderRunnable final : public CancelableRunnable
 {
 public:
-  explicit ReleaseWorkerHolderRunnable(UniquePtr<workers::WorkerHolder>&& aWorkerHolder)
-    : mWorkerHolder(Move(aWorkerHolder))
+  explicit ReleaseWorkerHolderRunnable(
+    UniquePtr<workers::WorkerHolder>&& aWorkerHolder)
+    : CancelableRunnable("dom::ReleaseWorkerHolderRunnable")
+    , mWorkerHolder(Move(aWorkerHolder))
   {}
 
   NS_IMETHOD
   Run() override
   {
     mWorkerHolder = nullptr;
     return NS_OK;
   }
--- a/dom/file/ipc/IPCBlobInputStreamThread.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamThread.cpp
@@ -24,16 +24,18 @@ namespace {
 
 StaticMutex gIPCBlobThreadMutex;
 StaticRefPtr<IPCBlobInputStreamThread> gIPCBlobThread;
 bool gShutdownHasStarted = false;
 
 class ThreadInitializeRunnable final : public Runnable
 {
 public:
+  ThreadInitializeRunnable() : Runnable("dom::ThreadInitializeRunnable") {}
+
   NS_IMETHOD
   Run() override
   {
      mozilla::StaticMutexAutoLock lock(gIPCBlobThreadMutex);
      MOZ_ASSERT(gIPCBlobThread);
      gIPCBlobThread->Initialize();
      return NS_OK;
   }
@@ -41,17 +43,18 @@ public:
 
 class MigrateActorRunnable final : public Runnable
                                  , public nsIIPCBackgroundChildCreateCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   explicit MigrateActorRunnable(IPCBlobInputStreamChild* aActor)
-    : mActor(aActor)
+    : Runnable("dom::MigrateActorRunnable")
+    , mActor(aActor)
   {
     MOZ_ASSERT(mActor);
   }
 
   NS_IMETHOD
   Run() override
   {
     BackgroundChild::GetOrCreateForCurrentThread(this);
--- a/dom/filehandle/ActorsParent.cpp
+++ b/dom/filehandle/ActorsParent.cpp
@@ -583,17 +583,18 @@ class CopyFileHandleOp::ProgressRunnable
   RefPtr<CopyFileHandleOp> mCopyFileHandleOp;
   uint64_t mProgress;
   uint64_t mProgressMax;
 
 public:
   ProgressRunnable(CopyFileHandleOp* aCopyFileHandleOp,
                    uint64_t aProgress,
                    uint64_t aProgressMax)
-    : mCopyFileHandleOp(aCopyFileHandleOp)
+    : Runnable("dom::CopyFileHandleOp::ProgressRunnable")
+    , mCopyFileHandleOp(aCopyFileHandleOp)
     , mProgress(aProgress)
     , mProgressMax(aProgressMax)
   { }
 
 private:
   ~ProgressRunnable() {}
 
   NS_DECL_NSIRUNNABLE
@@ -1076,20 +1077,21 @@ FileHandleThreadPool::MaybeFireCallback(
       return false;
     }
   }
 
   aCallback->mCallback->Run();
   return true;
 }
 
-FileHandleThreadPool::
-FileHandleQueue::FileHandleQueue(FileHandleThreadPool* aFileHandleThreadPool,
-                                 FileHandle* aFileHandle)
-  : mOwningFileHandleThreadPool(aFileHandleThreadPool)
+FileHandleThreadPool::FileHandleQueue::FileHandleQueue(
+  FileHandleThreadPool* aFileHandleThreadPool,
+  FileHandle* aFileHandle)
+  : Runnable("dom::FileHandleThreadPool::FileHandleQueue")
+  , mOwningFileHandleThreadPool(aFileHandleThreadPool)
   , mFileHandle(aFileHandle)
   , mShouldFinish(false)
 {
   MOZ_ASSERT(aFileHandleThreadPool);
   aFileHandleThreadPool->AssertIsOnOwningThread();
   MOZ_ASSERT(aFileHandle);
 }
 
--- a/dom/filesystem/FileSystemRequestParent.cpp
+++ b/dom/filesystem/FileSystemRequestParent.cpp
@@ -77,17 +77,18 @@ namespace {
 
 class CheckPermissionRunnable final : public Runnable
 {
 public:
   CheckPermissionRunnable(already_AddRefed<ContentParent> aParent,
                           FileSystemRequestParent* aActor,
                           FileSystemTaskParentBase* aTask,
                           const nsAString& aPath)
-    : mContentParent(aParent)
+    : Runnable("dom::CheckPermissionRunnable")
+    , mContentParent(aParent)
     , mActor(aActor)
     , mTask(aTask)
     , mPath(aPath)
     , mBackgroundEventTarget(GetCurrentThreadEventTarget())
   {
     AssertIsInMainProcess();
     AssertIsOnBackgroundThread();
 
--- a/dom/filesystem/FileSystemTaskBase.cpp
+++ b/dom/filesystem/FileSystemTaskBase.cpp
@@ -226,20 +226,22 @@ FileSystemTaskChildBase::SetError(const 
 {
   mErrorValue = FileSystemErrorFromNsError(aErrorValue);
 }
 
 /**
  * FileSystemTaskParentBase class
  */
 
-FileSystemTaskParentBase::FileSystemTaskParentBase(FileSystemBase* aFileSystem,
-                                                   const FileSystemParams& aParam,
-                                                   FileSystemRequestParent* aParent)
-  : mErrorValue(NS_OK)
+FileSystemTaskParentBase::FileSystemTaskParentBase(
+  FileSystemBase* aFileSystem,
+  const FileSystemParams& aParam,
+  FileSystemRequestParent* aParent)
+  : Runnable("dom::FileSystemTaskParentBase")
+  , mErrorValue(NS_OK)
   , mFileSystem(aFileSystem)
   , mRequestParent(aParent)
   , mBackgroundEventTarget(GetCurrentThreadEventTarget())
 {
   MOZ_ASSERT(XRE_IsParentProcess(),
              "Only call from parent process!");
   MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
   MOZ_ASSERT(aParent);
--- a/dom/filesystem/GetFilesHelper.cpp
+++ b/dom/filesystem/GetFilesHelper.cpp
@@ -52,17 +52,17 @@ public:
     return NS_OK;
   }
 
 private:
   ReleaseRunnable(nsTArray<RefPtr<Promise>>& aPromises,
                   nsTArray<RefPtr<GetFilesCallback>>& aCallbacks,
                   Sequence<RefPtr<File>>& aFiles,
                   already_AddRefed<nsIGlobalObject> aGlobal)
-    : Runnable("ReleaseRunnable")
+    : Runnable("dom::ReleaseRunnable")
   {
     mPromises.SwapElements(aPromises);
     mCallbacks.SwapElements(aCallbacks);
     mFiles.SwapElements(aFiles);
     mGlobal = aGlobal;
   }
 
   nsTArray<RefPtr<Promise>> mPromises;
--- a/dom/flyweb/HttpServer.cpp
+++ b/dom/flyweb/HttpServer.cpp
@@ -84,20 +84,19 @@ HttpServer::HandleCert(nsIX509Cert* aCer
 
   return NS_OK;
 }
 
 void
 HttpServer::NotifyStarted(nsresult aStatus)
 {
   RefPtr<HttpServerListener> listener = mListener;
-  nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction([listener, aStatus] ()
-  {
-    listener->OnServerStarted(aStatus);
-  });
+  nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
+    "dom::HttpServer::NotifyStarted",
+    [listener, aStatus]() { listener->OnServerStarted(aStatus); });
   NS_DispatchToCurrentThread(event);
 }
 
 nsresult
 HttpServer::StartServerSocket(nsIX509Cert* aCert)
 {
   nsresult rv;
   mServerSocket =
@@ -283,22 +282,22 @@ HttpServer::TransportProvider::SetTransp
   MaybeNotify();
 }
 
 void
 HttpServer::TransportProvider::MaybeNotify()
 {
   if (mTransport && mListener) {
     RefPtr<TransportProvider> self = this;
-    nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction([self, this] ()
-    {
-      DebugOnly<nsresult> rv = mListener->OnTransportAvailable(mTransport,
-                                                               mInput, mOutput);
-      MOZ_ASSERT(NS_SUCCEEDED(rv));
-    });
+    nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
+      "dom::HttpServer::TransportProvider::MaybeNotify", [self, this]() {
+        DebugOnly<nsresult> rv =
+          mListener->OnTransportAvailable(mTransport, mInput, mOutput);
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+      });
     NS_DispatchToCurrentThread(event);
   }
 }
 
 NS_IMPL_ISUPPORTS(HttpServer::Connection,
                   nsIInputStreamCallback,
                   nsIOutputStreamCallback)
 
@@ -628,21 +627,19 @@ HttpServer::Connection::ConsumeLine(cons
       LOG_V("HttpServer::Connection::ConsumeLine(%p) - Fire OnWebSocket", this);
 
       mState = ePause;
       mPendingWebSocketRequest = mPendingReq.forget();
       mPendingReqVersion = 0;
 
       RefPtr<HttpServerListener> listener = mServer->mListener;
       RefPtr<InternalRequest> request = mPendingWebSocketRequest;
-      nsCOMPtr<nsIRunnable> event =
-        NS_NewRunnableFunction([listener, request] ()
-      {
-        listener->OnWebSocket(request);
-      });
+      nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
+        "dom::HttpServer::Connection::ConsumeLine",
+        [listener, request]() { listener->OnWebSocket(request); });
       NS_DispatchToCurrentThread(event);
 
       return NS_OK;
     }
 
     nsAutoCString header;
     mPendingReq->Headers()->GetFirst(NS_LITERAL_CSTRING("connection"),
                                      header,
@@ -697,21 +694,19 @@ HttpServer::Connection::ConsumeLine(cons
     }
 
     mPendingRequests.AppendElement(PendingRequest(mPendingReq, nullptr));
 
     LOG_V("HttpServer::Connection::ConsumeLine(%p) - Fire OnRequest", this);
 
     RefPtr<HttpServerListener> listener = mServer->mListener;
     RefPtr<InternalRequest> request = mPendingReq.forget();
-    nsCOMPtr<nsIRunnable> event =
-      NS_NewRunnableFunction([listener, request] ()
-    {
-      listener->OnRequest(request);
-    });
+    nsCOMPtr<nsIRunnable> event = NS_NewRunnableFunction(
+      "dom::HttpServer::Connection::ConsumeLine",
+      [listener, request]() { listener->OnRequest(request); });
     NS_DispatchToCurrentThread(event);
 
     mPendingReqVersion = 0;
 
     return NS_OK;
   }
 
   // Parse header line
--- a/dom/gamepad/cocoa/CocoaGamepad.cpp
+++ b/dom/gamepad/cocoa/CocoaGamepad.cpp
@@ -230,17 +230,17 @@ class DarwinGamepadServiceStartupRunnabl
  private:
   ~DarwinGamepadServiceStartupRunnable() {}
   // This Runnable schedules startup of DarwinGamepadService
   // in a new thread, pointer to DarwinGamepadService is only
   // used by this Runnable within its thread.
   DarwinGamepadService MOZ_NON_OWNING_REF *mService;
  public:
   explicit DarwinGamepadServiceStartupRunnable(DarwinGamepadService *service)
-             : mService(service) {}
+    : Runnable("DarwinGamepadServiceStartupRunnable"), mService(service) {}
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(mService);
     mService->StartupInternal();
     return NS_OK;
   }
 };
 
--- a/dom/gamepad/ipc/GamepadEventChannelChild.cpp
+++ b/dom/gamepad/ipc/GamepadEventChannelChild.cpp
@@ -7,25 +7,28 @@
 namespace mozilla {
 namespace dom{
 
 namespace {
 
 class GamepadUpdateRunnable final : public Runnable
 {
  public:
-  explicit GamepadUpdateRunnable(const GamepadChangeEvent& aGamepadEvent)
-             : mEvent(aGamepadEvent) {}
-  NS_IMETHOD Run() override
-  {
-    RefPtr<GamepadManager> svc(GamepadManager::GetService());
-    if (svc) {
-      svc->Update(mEvent);
-    }
-    return NS_OK;
+   explicit GamepadUpdateRunnable(const GamepadChangeEvent& aGamepadEvent)
+     : Runnable("dom::GamepadUpdateRunnable")
+     , mEvent(aGamepadEvent)
+   {
+   }
+   NS_IMETHOD Run() override
+   {
+     RefPtr<GamepadManager> svc(GamepadManager::GetService());
+     if (svc) {
+       svc->Update(mEvent);
+     }
+     return NS_OK;
   }
  protected:
   GamepadChangeEvent mEvent;
 };
 
 } // namespace
 
 mozilla::ipc::IPCResult
--- a/dom/gamepad/ipc/GamepadEventChannelParent.cpp
+++ b/dom/gamepad/ipc/GamepadEventChannelParent.cpp
@@ -15,22 +15,23 @@ namespace {
 
 class SendGamepadUpdateRunnable final : public Runnable
 {
  private:
   ~SendGamepadUpdateRunnable() {}
   RefPtr<GamepadEventChannelParent> mParent;
   GamepadChangeEvent mEvent;
  public:
-  SendGamepadUpdateRunnable(GamepadEventChannelParent* aParent,
-                            GamepadChangeEvent aEvent)
-    : mEvent(aEvent)
-  {
-    MOZ_ASSERT(aParent);
-    mParent = aParent;
+   SendGamepadUpdateRunnable(GamepadEventChannelParent* aParent,
+                             GamepadChangeEvent aEvent)
+     : Runnable("dom::SendGamepadUpdateRunnable")
+     , mEvent(aEvent)
+   {
+     MOZ_ASSERT(aParent);
+     mParent = aParent;
   }
   NS_IMETHOD Run() override
   {
     AssertIsOnBackgroundThread();
     if(mParent->HasGamepadListener()) {
       Unused << mParent->SendGamepadUpdate(mEvent);
     }
     return NS_OK;
--- a/dom/gamepad/windows/WindowsGamepad.cpp
+++ b/dom/gamepad/windows/WindowsGamepad.cpp
@@ -997,17 +997,19 @@ GamepadWindowProc(HWND hwnd, UINT msg, W
     break;
   }
   return DefWindowProc(hwnd, msg, wParam, lParam);
 }
 
 class StartWindowsGamepadServiceRunnable final : public Runnable
 {
 public:
-  StartWindowsGamepadServiceRunnable() {}
+  StartWindowsGamepadServiceRunnable()
+    : Runnable("StartWindowsGamepadServiceRunnable")
+  {}
 
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(NS_GetCurrentThread() == gMonitorThread);
     gService = new WindowsGamepadService();
     gService->Startup();
 
     if (sHWnd == nullptr) {
@@ -1035,17 +1037,19 @@ public:
   }
 private:
   ~StartWindowsGamepadServiceRunnable() {}
 };
 
 class StopWindowsGamepadServiceRunnable final : public Runnable
 {
  public:
-  StopWindowsGamepadServiceRunnable() {}
+  StopWindowsGamepadServiceRunnable()
+    : Runnable("StopWindowsGamepadServiceRunnable")
+  {}
 
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(NS_GetCurrentThread() == gMonitorThread);
     if (sHWnd) {
       RegisterRawInput(sHWnd, false);
       DestroyWindow(sHWnd);
       sHWnd = nullptr;
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/nsGeolocation.cpp
@@ -142,17 +142,18 @@ CreatePositionOptionsCopy(const Position
 
   return geoOptions;
 }
 
 class RequestPromptEvent : public Runnable
 {
 public:
   RequestPromptEvent(nsGeolocationRequest* aRequest, nsWeakPtr aWindow)
-    : mRequest(aRequest)
+    : mozilla::Runnable("RequestPromptEvent")
+    , mRequest(aRequest)
     , mWindow(aWindow)
   {
   }
 
   NS_IMETHOD Run() override
   {
     nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow);
     nsContentPermissionUtils::AskPermission(mRequest, window);
@@ -163,18 +164,19 @@ private:
   RefPtr<nsGeolocationRequest> mRequest;
   nsWeakPtr mWindow;
 };
 
 class RequestAllowEvent : public Runnable
 {
 public:
   RequestAllowEvent(int allow, nsGeolocationRequest* request)
-    : mAllow(allow),
-      mRequest(request)
+    : mozilla::Runnable("RequestAllowEvent")
+    , mAllow(allow)
+    , mRequest(request)
   {
   }
 
   NS_IMETHOD Run() override {
     if (mAllow) {
       mRequest->Allow(JS::UndefinedHandleValue);
     } else {
       mRequest->Cancel();
@@ -187,18 +189,19 @@ private:
   RefPtr<nsGeolocationRequest> mRequest;
 };
 
 class RequestSendLocationEvent : public Runnable
 {
 public:
   RequestSendLocationEvent(nsIDOMGeoPosition* aPosition,
                            nsGeolocationRequest* aRequest)
-    : mPosition(aPosition),
-      mRequest(aRequest)
+    : mozilla::Runnable("RequestSendLocationEvent")
+    , mPosition(aPosition)
+    , mRequest(aRequest)
   {
   }
 
   NS_IMETHOD Run() override {
     mRequest->SendLocation(mPosition);
     return NS_OK;
   }
 
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -239,18 +239,20 @@ void
 HTMLCanvasPrintState::Done()
 {
   if (!mPendingNotify && !mIsDone) {
     // The canvas needs to be invalidated for printing reftests on linux to
     // work.
     if (mCanvas) {
       mCanvas->InvalidateCanvas();
     }
-    RefPtr<nsRunnableMethod<HTMLCanvasPrintState> > doneEvent =
-      NewRunnableMethod(this, &HTMLCanvasPrintState::NotifyDone);
+    RefPtr<nsRunnableMethod<HTMLCanvasPrintState>> doneEvent =
+      NewRunnableMethod("dom::HTMLCanvasPrintState::NotifyDone",
+                        this,
+                        &HTMLCanvasPrintState::NotifyDone);
     if (NS_SUCCEEDED(NS_DispatchToCurrentThread(doneEvent))) {
       mPendingNotify = true;
     }
   }
 }
 
 void
 HTMLCanvasPrintState::NotifyDone()
@@ -519,18 +521,20 @@ HTMLCanvasElement::DispatchPrintCallback
   if (!mCurrentContext) {
     nsresult rv;
     nsCOMPtr<nsISupports> context;
     rv = GetContext(NS_LITERAL_STRING("2d"), getter_AddRefs(context));
     NS_ENSURE_SUCCESS(rv, rv);
   }
   mPrintState = new HTMLCanvasPrintState(this, mCurrentContext, aCallback);
 
-  RefPtr<nsRunnableMethod<HTMLCanvasElement> > renderEvent =
-    NewRunnableMethod(this, &HTMLCanvasElement::CallPrintCallback);
+  RefPtr<nsRunnableMethod<HTMLCanvasElement>> renderEvent =
+    NewRunnableMethod("dom::HTMLCanvasElement::CallPrintCallback",
+                      this,
+                      &HTMLCanvasElement::CallPrintCallback);
   return OwnerDoc()->Dispatch("HTMLCanvasElement::CallPrintCallback",
                               TaskCategory::Other,
                               renderEvent.forget());
 }
 
 void
 HTMLCanvasElement::CallPrintCallback()
 {
@@ -842,23 +846,26 @@ HTMLCanvasElement::ToBlob(JSContext* aCx
   nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
   MOZ_ASSERT(global);
 
   nsIntSize elemSize = GetWidthHeight();
   if (elemSize.width == 0 || elemSize.height == 0) {
     // According to spec, blob should return null if either its horizontal
     // dimension or its vertical dimension is zero. See link below.
     // https://html.spec.whatwg.org/multipage/scripting.html#dom-canvas-toblob
-    OwnerDoc()->Dispatch("FireNullBlobEvent",
-                  TaskCategory::Other,
-                  NewRunnableMethod<Blob*, const char*>(
-                          &aCallback,
-                          static_cast<void(BlobCallback::*)(
-                            Blob*, const char*)>(&BlobCallback::Call),
-                          nullptr, nullptr));
+    OwnerDoc()->Dispatch(
+      "FireNullBlobEvent",
+      TaskCategory::Other,
+      NewRunnableMethod<Blob*, const char*>(
+        "dom::HTMLCanvasElement::ToBlob",
+        &aCallback,
+        static_cast<void (BlobCallback::*)(Blob*, const char*)>(
+          &BlobCallback::Call),
+        nullptr,
+        nullptr));
     return;
   }
 
   CanvasRenderingContextHelper::ToBlob(aCx, global, aCallback, aType,
                                        aParams, aRv);
 
 }
 
@@ -1351,17 +1358,18 @@ HTMLCanvasElement::OnVisibilityChange()
     return;
   }
 
   if (mOffscreenCanvas) {
     class Runnable final : public CancelableRunnable
     {
     public:
       explicit Runnable(AsyncCanvasRenderer* aRenderer)
-        : mRenderer(aRenderer)
+        : mozilla::CancelableRunnable("Runnable")
+        , mRenderer(aRenderer)
       {}
 
       NS_IMETHOD Run() override
       {
         if (mRenderer && mRenderer->mContext) {
           mRenderer->mContext->OnVisibilityChange();
         }
 
@@ -1388,17 +1396,18 @@ HTMLCanvasElement::OnVisibilityChange()
 void
 HTMLCanvasElement::OnMemoryPressure()
 {
   if (mOffscreenCanvas) {
     class Runnable final : public CancelableRunnable
     {
     public:
       explicit Runnable(AsyncCanvasRenderer* aRenderer)
-        : mRenderer(aRenderer)
+        : mozilla::CancelableRunnable("Runnable")
+        , mRenderer(aRenderer)
       {}
 
       NS_IMETHOD Run() override
       {
         if (mRenderer && mRenderer->mContext) {
           mRenderer->mContext->OnMemoryPressure();
         }
 
--- a/dom/html/HTMLFormElement.h
+++ b/dom/html/HTMLFormElement.h
@@ -421,17 +421,18 @@ protected:
   RefPtr<AsyncEventDispatcher> mFormPasswordEventDispatcher;
 
   class RemoveElementRunnable;
   friend class RemoveElementRunnable;
 
   class RemoveElementRunnable : public Runnable {
   public:
     explicit RemoveElementRunnable(HTMLFormElement* aForm)
-      : mForm(aForm)
+      : Runnable("dom::HTMLFormElement::RemoveElementRunnable")
+      , mForm(aForm)
     {}
 
     NS_IMETHOD Run() override {
       mForm->HandleDefaultSubmitRemoval();
       return NS_OK;
     }
 
   private:
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -74,19 +74,21 @@ namespace mozilla {
 namespace dom {
 
 // Calls LoadSelectedImage on host element unless it has been superseded or
 // canceled -- this is the synchronous section of "update the image data".
 // https://html.spec.whatwg.org/multipage/embedded-content.html#update-the-image-data
 class ImageLoadTask : public Runnable
 {
 public:
-  ImageLoadTask(HTMLImageElement *aElement, bool aAlwaysLoad,
+  ImageLoadTask(HTMLImageElement* aElement,
+                bool aAlwaysLoad,
                 bool aUseUrgentStartForChannel)
-    : mElement(aElement)
+    : Runnable("dom::ImageLoadTask")
+    , mElement(aElement)
     , mAlwaysLoad(aAlwaysLoad)
     , mUseUrgentStartForChannel(aUseUrgentStartForChannel)
   {
     mDocument = aElement->OwnerDoc();
     mDocument->BlockOnload();
   }
 
   NS_IMETHOD Run() override
@@ -671,17 +673,20 @@ HTMLImageElement::BindToTree(nsIDocument
     // script.
 
     // If loading is temporarily disabled, don't even launch MaybeLoadImage.
     // Otherwise MaybeLoadImage may run later when someone has reenabled
     // loading.
     if (LoadingEnabled() &&
         OwnerDoc()->IsCurrentActiveDocument()) {
       nsContentUtils::AddScriptRunner(
-        NewRunnableMethod<bool>(this, &HTMLImageElement::MaybeLoadImage, false));
+        NewRunnableMethod<bool>("dom::HTMLImageElement::MaybeLoadImage",
+                                this,
+                                &HTMLImageElement::MaybeLoadImage,
+                                false));
     }
   }
 
   return rv;
 }
 
 void
 HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
@@ -764,19 +769,24 @@ HTMLImageElement::NodeInfoChanged(nsIDoc
   // Force reload image if adoption steps are run.
   // If loading is temporarily disabled, don't even launch script runner.
   // Otherwise script runner may run later when someone has reenabled loading.
   if (LoadingEnabled()) {
     // Use script runner for the case the adopt is from appendChild.
     // Bug 1076583 - We still behave synchronously in the non-responsive case
     nsContentUtils::AddScriptRunner(
       (InResponsiveMode())
-        ? NewRunnableMethod<bool>(this, &HTMLImageElement::QueueImageLoadTask, true)
-        : NewRunnableMethod<bool>(this, &HTMLImageElement::MaybeLoadImage, true)
-    );
+        ? NewRunnableMethod<bool>("dom::HTMLImageElement::QueueImageLoadTask",
+                                  this,
+                                  &HTMLImageElement::QueueImageLoadTask,
+                                  true)
+        : NewRunnableMethod<bool>("dom::HTMLImageElement::MaybeLoadImage",
+                                  this,
+                                  &HTMLImageElement::MaybeLoadImage,
+                                  true));
   }
 }
 
 // static
 already_AddRefed<HTMLImageElement>
 HTMLImageElement::Image(const GlobalObject& aGlobal,
                         const Optional<uint32_t>& aWidth,
                         const Optional<uint32_t>& aHeight,
@@ -889,17 +899,20 @@ HTMLImageElement::CopyInnerTo(Element* a
     if (!dest->InResponsiveMode() &&
         dest->HasAttr(kNameSpaceID_None, nsGkAtoms::src) &&
         dest->OwnerDoc()->IsCurrentActiveDocument()) {
       // Mark channel as urgent-start before load image if the image load is
       // initaiated by a user interaction.
       mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
       nsContentUtils::AddScriptRunner(
-        NewRunnableMethod<bool>(dest, &HTMLImageElement::MaybeLoadImage, false));
+        NewRunnableMethod<bool>("dom::HTMLImageElement::MaybeLoadImage",
+                                dest,
+                                &HTMLImageElement::MaybeLoadImage,
+                                false));
     }
   }
 
   return NS_OK;
 }
 
 CORSMode
 HTMLImageElement::GetCORSMode()
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -4872,17 +4872,19 @@ HTMLInputElement::BindToTree(nsIDocument
       // initaiated by a user interaction.
       mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
       // FIXME: Bug 660963 it would be nice if we could just have
       // ClearBrokenState update our state and do it fast...
       ClearBrokenState();
       RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
       nsContentUtils::AddScriptRunner(
-        NewRunnableMethod(this, &HTMLInputElement::MaybeLoadImage));
+        NewRunnableMethod("dom::HTMLInputElement::MaybeLoadImage",
+                          this,
+                          &HTMLInputElement::MaybeLoadImage));
     }
   }
 
   // Add radio to document if we don't have a form already (if we do it's
   // already been added into that group)
   if (aDocument && !mForm && mType == NS_FORM_INPUT_RADIO) {
     AddedToRadioGroup();
   }
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -166,17 +166,18 @@ HTMLLinkElement::BindToTree(nsIDocument*
     aDocument->RegisterPendingLinkUpdate(this);
   }
 
   if (IsInComposedDoc()) {
     TryDNSPrefetchPreconnectOrPrefetchOrPrerender();
   }
 
   void (HTMLLinkElement::*update)() = &HTMLLinkElement::UpdateStyleSheetInternal;
-  nsContentUtils::AddScriptRunner(NewRunnableMethod(this, update));
+  nsContentUtils::AddScriptRunner(
+    NewRunnableMethod("dom::HTMLLinkElement::BindToTree", this, update));
 
   CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMLinkAdded"));
 
   return rv;
 }
 
 void
 HTMLLinkElement::LinkAdded()
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -227,20 +227,22 @@ RejectPromises(const nsTArray<RefPtr<Pro
 // since if we neglect to add a self-reference, this element might be
 // garbage collected while there are still event listeners that should
 // receive events. If we neglect to remove the self-reference then the element
 // just lives longer than it needs to.
 
 class nsMediaEvent : public Runnable
 {
 public:
-
-  explicit nsMediaEvent(HTMLMediaElement* aElement) :
-    mElement(aElement),
-    mLoadID(mElement->GetCurrentLoadID()) {}
+  explicit nsMediaEvent(HTMLMediaElement* aElement)
+    : Runnable("dom::nsMediaEvent")
+    , mElement(aElement)
+    , mLoadID(mElement->GetCurrentLoadID())
+  {
+  }
   ~nsMediaEvent() {}
 
   NS_IMETHOD Run() = 0;
 
 protected:
   bool IsCancelled() {
     return mElement->GetCurrentLoadID() != mLoadID;
   }
@@ -400,19 +402,21 @@ public:
       MOZ_ASSERT(false, "Should only lock on to a video track");
       return;
     }
 
     const VideoSegment& video = static_cast<const VideoSegment&>(aMedia);
     for (VideoSegment::ConstChunkIterator c(video); !c.IsEnded(); c.Next()) {
       if (c->mFrame.GetIntrinsicSize() != gfx::IntSize(0,0)) {
         mInitialSizeFound = true;
-        nsCOMPtr<nsIRunnable> event =
-          NewRunnableMethod<gfx::IntSize>(this, &StreamSizeListener::ReceivedSize,
-                                          c->mFrame.GetIntrinsicSize());
+        nsCOMPtr<nsIRunnable> event = NewRunnableMethod<gfx::IntSize>(
+          "dom::HTMLMediaElement::StreamSizeListener::ReceivedSize",
+          this,
+          &StreamSizeListener::ReceivedSize,
+          c->mFrame.GetIntrinsicSize());
         // This is fine to dispatch straight to main thread (instead of via
         // ...AfterStreamUpdate()) since it reflects state of the element,
         // not the stream. Events reflecting stream or track state should be
         // dispatched so their order is preserved.
         NS_DispatchToMainThread(event.forget());
         return;
       }
     }
@@ -965,34 +969,36 @@ private:
       return;
     }
 
     if (!IsPlayingStarted()) {
       return;
     }
 
     uint64_t windowID = mAudioChannelAgent->WindowID();
-    NS_DispatchToMainThread(NS_NewRunnableFunction([windowID]() -> void {
-      nsCOMPtr<nsIObserverService> observerService =
-        services::GetObserverService();
-      if (NS_WARN_IF(!observerService)) {
-        return;
-      }
-
-      nsCOMPtr<nsISupportsPRUint64> wrapper =
-        do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
-      if (NS_WARN_IF(!wrapper)) {
-         return;
-      }
-
-      wrapper->SetData(windowID);
-      observerService->NotifyObservers(wrapper,
-                                       "media-playback-resumed",
-                                       u"active");
-    }));
+    NS_DispatchToMainThread(NS_NewRunnableFunction(
+      "dom::HTMLMediaElement::AudioChannelAgentCallback::"
+      "MaybeNotifyMediaResumed",
+      [windowID]() -> void {
+        nsCOMPtr<nsIObserverService> observerService =
+          services::GetObserverService();
+        if (NS_WARN_IF(!observerService)) {
+          return;
+        }
+
+        nsCOMPtr<nsISupportsPRUint64> wrapper =
+          do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
+        if (NS_WARN_IF(!wrapper)) {
+          return;
+        }
+
+        wrapper->SetData(windowID);
+        observerService->NotifyObservers(
+          wrapper, "media-playback-resumed", u"active");
+      }));
   }
 
   bool
   IsTabActivated()
   {
     if (MaybeCreateAudioChannelAgent()) {
       return !mAudioChannelAgent->ShouldBlockMedia();
     }
@@ -4118,18 +4124,22 @@ HTMLMediaElement::WakeLockBoolWrapper::U
     }
     mOuter->WakeLockCreate();
   } else if (!mTimer) {
     // Don't release the wake lock immediately; instead, release it after a
     // grace period.
     int timeout = Preferences::GetInt("media.wakelock_timeout", 2000);
     mTimer = do_CreateInstance("@mozilla.org/timer;1");
     if (mTimer) {
-      mTimer->InitWithFuncCallback(TimerCallback, this, timeout,
-                                   nsITimer::TYPE_ONE_SHOT);
+      mTimer->InitWithNamedFuncCallback(
+        TimerCallback,
+        this,
+        timeout,
+        nsITimer::TYPE_ONE_SHOT,
+        "dom::HTMLMediaElement::WakeLockBoolWrapper::UpdateWakeLock");
     }
   }
 }
 
 void
 HTMLMediaElement::WakeLockBoolWrapper::TimerCallback(nsITimer* aTimer,
                                                      void* aClosure)
 {
@@ -4559,21 +4569,22 @@ void HTMLMediaElement::UnbindFromTree(bo
   mVisibilityState = Visibility::UNTRACKED;
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 
   MOZ_ASSERT(IsHidden());
   NotifyDecoderActivityChanges();
 
   RefPtr<HTMLMediaElement> self(this);
-  nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([self] () {
-    if (self->mUnboundFromTree) {
-      self->Pause();
-    }
-  });
+  nsCOMPtr<nsIRunnable> task =
+    NS_NewRunnableFunction("dom::HTMLMediaElement::UnbindFromTree", [self]() {
+      if (self->mUnboundFromTree) {
+        self->Pause();
+      }
+    });
   RunInStableState(task);
 }
 
 static bool
 IsVP9InMP4(const MediaContainerType& aContainerType)
 {
   const MediaContainerType mimeType(aContainerType.Type());
   return DecoderTraits::IsMP4SupportedType(mimeType,
@@ -4864,40 +4875,51 @@ public:
   }
 
   // These notifications run on the media graph thread so we need to
   // dispatch events to the main thread.
   virtual void NotifyBlockingChanged(MediaStreamGraph* aGraph, Blocking aBlocked) override
   {
     nsCOMPtr<nsIRunnable> event;
     if (aBlocked == BLOCKED) {
-      event = NewRunnableMethod(this, &StreamListener::DoNotifyBlocked);
+      event = NewRunnableMethod(
+        "dom::HTMLMediaElement::StreamListener::DoNotifyBlocked",
+        this,
+        &StreamListener::DoNotifyBlocked);
     } else {
-      event = NewRunnableMethod(this, &StreamListener::DoNotifyUnblocked);
+      event = NewRunnableMethod(
+        "dom::HTMLMediaElement::StreamListener::DoNotifyUnblocked",
+        this,
+        &StreamListener::DoNotifyUnblocked);
     }
     aGraph->DispatchToMainThreadAfterStreamStateUpdate(mAbstractMainThread,
                                                        event.forget());
   }
   virtual void NotifyHasCurrentData(MediaStreamGraph* aGraph) override
   {
     MutexAutoLock lock(mMutex);
     aGraph->DispatchToMainThreadAfterStreamStateUpdate(
       mAbstractMainThread,
-      NewRunnableMethod(this, &StreamListener::DoNotifyHaveCurrentData));
+      NewRunnableMethod(
+        "dom::HTMLMediaElement::StreamListener::DoNotifyHaveCurrentData",
+        this,
+        &StreamListener::DoNotifyHaveCurrentData));
   }
   virtual void NotifyOutput(MediaStreamGraph* aGraph,
                             GraphTime aCurrentTime) override
   {
     MutexAutoLock lock(mMutex);
     if (mPendingNotifyOutput)
       return;
     mPendingNotifyOutput = true;
     aGraph->DispatchToMainThreadAfterStreamStateUpdate(
       mAbstractMainThread,
-      NewRunnableMethod(this, &StreamListener::DoNotifyOutput));
+      NewRunnableMethod("dom::HTMLMediaElement::StreamListener::DoNotifyOutput",
+                        this,
+                        &StreamListener::DoNotifyOutput));
   }
 
 private:
   // These fields may only be accessed on the main thread
   HTMLMediaElement* mElement;
   bool mHaveCurrentData;
   bool mBlocked;
   bool mFinished;
@@ -6316,17 +6338,19 @@ void HTMLMediaElement::AddRemoveSelfRefe
       // The shutdown observer will hold a strong reference to us. This
       // will do to keep us alive. We need to know about shutdown so that
       // we can release our self-reference.
       mShutdownObserver->AddRefMediaElement();
     } else {
       // Dispatch Release asynchronously so that we don't destroy this object
       // inside a call stack of method calls on this object
       nsCOMPtr<nsIRunnable> event =
-        NewRunnableMethod(this, &HTMLMediaElement::DoRemoveSelfReference);
+        NewRunnableMethod("dom::HTMLMediaElement::DoRemoveSelfReference",
+                          this,
+                          &HTMLMediaElement::DoRemoveSelfReference);
       NS_DispatchToMainThread(event);
     }
   }
 }
 
 void HTMLMediaElement::DoRemoveSelfReference()
 {
   mShutdownObserver->ReleaseMediaElement();
@@ -7483,33 +7507,33 @@ bool HasDebuggerPrivilege(JSContext* aCx
  }
 
 void
 HTMLMediaElement::AsyncResolveSeekDOMPromiseIfExists()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mSeekDOMPromise) {
     RefPtr<dom::Promise> promise = mSeekDOMPromise.forget();
-    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
-      promise->MaybeResolveWithUndefined();
-    });
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+      "dom::HTMLMediaElement::AsyncResolveSeekDOMPromiseIfExists",
+      [=]() { promise->MaybeResolveWithUndefined(); });
     mAbstractMainThread->Dispatch(r.forget());
     mSeekDOMPromise = nullptr;
   }
 }
 
 void
 HTMLMediaElement::AsyncRejectSeekDOMPromiseIfExists()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mSeekDOMPromise) {
     RefPtr<dom::Promise> promise = mSeekDOMPromise.forget();
-    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
-      promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
-    });
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+      "dom::HTMLMediaElement::AsyncRejectSeekDOMPromiseIfExists",
+      [=]() { promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); });
     mAbstractMainThread->Dispatch(r.forget());
     mSeekDOMPromise = nullptr;
   }
 }
 
 void
 HTMLMediaElement::ReportCanPlayTelemetry()
 {
@@ -7517,36 +7541,39 @@ HTMLMediaElement::ReportCanPlayTelemetry
 
   RefPtr<nsIThread> thread;
   nsresult rv = NS_NewNamedThread("MediaTelemetry", getter_AddRefs(thread));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   thread->Dispatch(
-    NS_NewRunnableFunction([thread]() {
+    NS_NewRunnableFunction(
+      "dom::HTMLMediaElement::ReportCanPlayTelemetry",
+      [thread]() {
 #if XP_WIN
-      // Windows Media Foundation requires MSCOM to be inited.
-      HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
-      MOZ_ASSERT(hr == S_OK);
+        // Windows Media Foundation requires MSCOM to be inited.
+        HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
+        MOZ_ASSERT(hr == S_OK);
 #endif
-      bool aac = MP4Decoder::IsSupportedType(
-        MediaContainerType(MEDIAMIMETYPE("audio/mp4")), nullptr);
-      bool h264 = MP4Decoder::IsSupportedType(
-        MediaContainerType(MEDIAMIMETYPE("video/mp4")), nullptr);
+        bool aac = MP4Decoder::IsSupportedType(
+          MediaContainerType(MEDIAMIMETYPE("audio/mp4")), nullptr);
+        bool h264 = MP4Decoder::IsSupportedType(
+          MediaContainerType(MEDIAMIMETYPE("video/mp4")), nullptr);
 #if XP_WIN
-      CoUninitialize();
+        CoUninitialize();
 #endif
-      AbstractThread::MainThread()->Dispatch(
-        NS_NewRunnableFunction([thread, aac, h264]() {
-          LOG(LogLevel::Debug, ("MediaTelemetry aac=%d h264=%d", aac, h264));
-          Telemetry::Accumulate(
-            Telemetry::HistogramID::VIDEO_CAN_CREATE_AAC_DECODER, aac);
-          Telemetry::Accumulate(
-            Telemetry::HistogramID::VIDEO_CAN_CREATE_H264_DECODER, h264);
-          thread->AsyncShutdown();
-        }));
-    }),
+        AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction(
+          "dom::HTMLMediaElement::ReportCanPlayTelemetry",
+          [thread, aac, h264]() {
+            LOG(LogLevel::Debug, ("MediaTelemetry aac=%d h264=%d", aac, h264));
+            Telemetry::Accumulate(
+              Telemetry::HistogramID::VIDEO_CAN_CREATE_AAC_DECODER, aac);
+            Telemetry::Accumulate(
+              Telemetry::HistogramID::VIDEO_CAN_CREATE_H264_DECODER, h264);
+            thread->AsyncShutdown();
+          }));
+      }),
     NS_DISPATCH_NORMAL);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -126,17 +126,19 @@ static nsIWidget* GetWidget(Element* aEl
 }
 
 Element* HTMLObjectElement::sLastFocused = nullptr; // Weak
 
 class PluginFocusSetter : public Runnable
 {
 public:
   PluginFocusSetter(nsIWidget* aWidget, Element* aElement)
-  : mWidget(aWidget), mElement(aElement)
+    : Runnable("PluginFocusSetter")
+    , mWidget(aWidget)
+    , mElement(aElement)
   {
   }
 
   NS_IMETHOD Run() override
   {
     if (mElement) {
       HTMLObjectElement::sLastFocused = mElement;
       bool value = true;
@@ -264,17 +266,18 @@ HTMLObjectElement::BindToTree(nsIDocumen
   // Don't kick off load from being bound to a plugin document - the plugin
   // document will call nsObjectLoadingContent::InitializeFromChannel() for the
   // initial load.
   nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(aDocument);
 
   // If we already have all the children, start the load.
   if (mIsDoneAddingChildren && !pluginDoc) {
     void (HTMLObjectElement::*start)() = &HTMLObjectElement::StartObjectLoad;
-    nsContentUtils::AddScriptRunner(NewRunnableMethod(this, start));
+    nsContentUtils::AddScriptRunner(
+      NewRunnableMethod("dom::HTMLObjectElement::BindToTree", this, start));
   }
 
   return NS_OK;
 }
 
 void
 HTMLObjectElement::UnbindFromTree(bool aDeep,
                                   bool aNullParent)
--- a/dom/html/HTMLSharedObjectElement.cpp
+++ b/dom/html/HTMLSharedObjectElement.cpp
@@ -134,17 +134,18 @@ HTMLSharedObjectElement::BindToTree(nsID
   // document will call nsObjectLoadingContent::InitializeFromChannel() for the
   // initial load.
   nsCOMPtr<nsIPluginDocument> pluginDoc = do_QueryInterface(aDocument);
 
   // If we already have all the children, start the load.
   if (mIsDoneAddingChildren && !pluginDoc) {
     void (HTMLSharedObjectElement::*start)() =
       &HTMLSharedObjectElement::StartObjectLoad;
-    nsContentUtils::AddScriptRunner(NewRunnableMethod(this, start));
+    nsContentUtils::AddScriptRunner(NewRunnableMethod(
+      "dom::HTMLSharedObjectElement::BindToTree", this, start));
   }
 
   return NS_OK;
 }
 
 void
 HTMLSharedObjectElement::UnbindFromTree(bool aDeep,
                                         bool aNullParent)
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -141,17 +141,18 @@ HTMLStyleElement::BindToTree(nsIDocument
                              bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   void (HTMLStyleElement::*update)() = &HTMLStyleElement::UpdateStyleSheetInternal;
-  nsContentUtils::AddScriptRunner(NewRunnableMethod(this, update));
+  nsContentUtils::AddScriptRunner(
+    NewRunnableMethod("dom::HTMLStyleElement::BindToTree", this, update));
 
   return rv;  
 }
 
 void
 HTMLStyleElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc();
--- a/dom/html/HTMLTrackElement.cpp
+++ b/dom/html/HTMLTrackElement.cpp
@@ -260,17 +260,20 @@ HTMLTrackElement::SetSrc(const nsAString
 
   DispatchLoadResource();
 }
 
 void
 HTMLTrackElement::DispatchLoadResource()
 {
   if (!mLoadResourceDispatched) {
-    RefPtr<Runnable> r = NewRunnableMethod(this, &HTMLTrackElement::LoadResource);
+    RefPtr<Runnable> r =
+      NewRunnableMethod("dom::HTMLTrackElement::LoadResource",
+                        this,
+                        &HTMLTrackElement::LoadResource);
     nsContentUtils::RunInStableState(r.forget());
     mLoadResourceDispatched = true;
   }
 }
 
 void
 HTMLTrackElement::LoadResource()
 {
@@ -432,21 +435,21 @@ HTMLTrackElement::SetReadyState(uint16_t
 
 void
 HTMLTrackElement::DispatchTrackRunnable(const nsString& aEventName)
 {
   nsIDocument* doc = OwnerDoc();
   if (!doc) {
     return;
   }
-  nsCOMPtr<nsIRunnable> runnable =
-    NewRunnableMethod
-      <const nsString>(this,
-                       &HTMLTrackElement::DispatchTrustedEvent,
-                       aEventName);
+  nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod<const nsString>(
+    "dom::HTMLTrackElement::DispatchTrustedEvent",
+    this,
+    &HTMLTrackElement::DispatchTrustedEvent,
+    aEventName);
   doc->Dispatch("HTMLTrackElement::DispatchTrackRunnable",
                 TaskCategory::Other, runnable.forget());
 }
 
 void
 HTMLTrackElement::DispatchTrustedEvent(const nsAString& aName)
 {
   nsIDocument* doc = OwnerDoc();
--- a/dom/html/ImageDocument.cpp
+++ b/dom/html/ImageDocument.cpp
@@ -488,17 +488,19 @@ ImageDocument::Notify(imgIRequest* aRequ
     aRequest->GetImage(getter_AddRefs(image));
     return OnSizeAvailable(aRequest, image);
   }
 
   // Run this using a script runner because HAS_TRANSPARENCY notifications can
   // come during painting and this will trigger invalidation.
   if (aType == imgINotificationObserver::HAS_TRANSPARENCY) {
     nsCOMPtr<nsIRunnable> runnable =
-      NewRunnableMethod(this, &ImageDocument::OnHasTransparency);
+      NewRunnableMethod("dom::ImageDocument::OnHasTransparency",
+                        this,
+                        &ImageDocument::OnHasTransparency);
     nsContentUtils::AddScriptRunner(runnable);
   }
 
   if (aType == imgINotificationObserver::LOAD_COMPLETE) {
     uint32_t reqStatus;
     aRequest->GetImageStatus(&reqStatus);
     nsresult status =
         reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK;
@@ -561,17 +563,19 @@ ImageDocument::OnSizeAvailable(imgIReque
   // Multipart images send size available for each part; ignore them if it
   // doesn't change our size. (We may not even support changing size in
   // multipart images in the future.)
   if (oldWidth == mImageWidth && oldHeight == mImageHeight) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIRunnable> runnable =
-    NewRunnableMethod(this, &ImageDocument::DefaultCheckOverflowing);
+    NewRunnableMethod("dom::ImageDocument::DefaultCheckOverflowing",
+                      this,
+                      &ImageDocument::DefaultCheckOverflowing);
   nsContentUtils::AddScriptRunner(runnable);
   UpdateTitleAndCharset();
 
   return NS_OK;
 }
 
 nsresult
 ImageDocument::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus)
--- a/dom/html/TextTrackManager.cpp
+++ b/dom/html/TextTrackManager.cpp
@@ -165,18 +165,20 @@ TextTrackManager::AddTextTrack(TextTrack
     NS_ConvertUTF16toUTF8(aLabel).get(), NS_ConvertUTF16toUTF8(aLanguage).get());
   RefPtr<TextTrack> track =
     mTextTracks->AddTextTrack(aKind, aLabel, aLanguage, aMode, aReadyState,
                               aTextTrackSource, CompareTextTracks(mMediaElement));
   AddCues(track);
   ReportTelemetryForTrack(track);
 
   if (aTextTrackSource == TextTrackSource::Track) {
-    RefPtr<nsIRunnable> task =
-      NewRunnableMethod(this, &TextTrackManager::HonorUserPreferencesForTrackSelection);
+    RefPtr<nsIRunnable> task = NewRunnableMethod(
+      "dom::TextTrackManager::HonorUserPreferencesForTrackSelection",
+      this,
+      &TextTrackManager::HonorUserPreferencesForTrackSelection);
     nsContentUtils::RunInStableState(task.forget());
   }
 
   return track.forget();
 }
 
 void
 TextTrackManager::AddTextTrack(TextTrack* aTextTrack)
@@ -185,18 +187,20 @@ TextTrackManager::AddTextTrack(TextTrack
     return;
   }
   WEBVTT_LOG("%p AddTextTrack TextTrack %p",this, aTextTrack);
   mTextTracks->AddTextTrack(aTextTrack, CompareTextTracks(mMediaElement));
   AddCues(aTextTrack);
   ReportTelemetryForTrack(aTextTrack);
 
   if (aTextTrack->GetTextTrackSource() == TextTrackSource::Track) {
-    RefPtr<nsIRunnable> task =
-      NewRunnableMethod(this, &TextTrackManager::HonorUserPreferencesForTrackSelection);
+    RefPtr<nsIRunnable> task = NewRunnableMethod(
+      "dom::TextTrackManager::HonorUserPreferencesForTrackSelection",
+      this,
+      &TextTrackManager::HonorUserPreferencesForTrackSelection);
     nsContentUtils::RunInStableState(task.forget());
   }
 }
 
 void
 TextTrackManager::AddCues(TextTrack* aTextTrack)
 {
   if (!mNewCues) {
@@ -478,22 +482,25 @@ TextTrackManager::HandleEvent(nsIDOMEven
   return NS_OK;
 }
 
 
 class SimpleTextTrackEvent : public Runnable
 {
 public:
   friend class CompareSimpleTextTrackEvents;
-  SimpleTextTrackEvent(const nsAString& aEventName, double aTime,
-                       TextTrack* aTrack, TextTrackCue* aCue)
-  : mName(aEventName),
-    mTime(aTime),
-    mTrack(aTrack),
-    mCue(aCue)
+  SimpleTextTrackEvent(const nsAString& aEventName,
+                       double aTime,
+                       TextTrack* aTrack,
+                       TextTrackCue* aCue)
+    : Runnable("dom::SimpleTextTrackEvent")
+    , mName(aEventName)
+    , mTime(aTime)
+    , mTrack(aTrack)
+    , mCue(aCue)
   {}
 
   NS_IMETHOD Run() {
     WEBVTT_LOGV("SimpleTextTrackEvent cue %p mName %s mTime %lf",
       mCue.get(), NS_ConvertUTF16toUTF8(mName).get(), mTime);
     mCue->DispatchTrustedEvent(mName);
     return NS_OK;
   }
@@ -619,18 +626,21 @@ void
 TextTrackManager::DispatchUpdateCueDisplay()
 {
   if (!mUpdateCueDisplayDispatched && !mShutdown &&
       (mMediaElement->GetHasUserInteraction() || mMediaElement->IsCurrentlyPlaying())) {
     WEBVTT_LOG("DispatchUpdateCueDisplay");
     nsPIDOMWindowInner* win = mMediaElement->OwnerDoc()->GetInnerWindow();
     if (win) {
       nsGlobalWindow::Cast(win)->Dispatch(
-        "TextTrackManager::UpdateCueDisplay", TaskCategory::Other,
-        NewRunnableMethod(this, &TextTrackManager::UpdateCueDisplay));
+        "TextTrackManager::UpdateCueDisplay",
+        TaskCategory::Other,
+        NewRunnableMethod("dom::TextTrackManager::UpdateCueDisplay",
+                          this,
+                          &TextTrackManager::UpdateCueDisplay));
       mUpdateCueDisplayDispatched = true;
     }
   }
 }
 
 void
 TextTrackManager::DispatchTimeMarchesOn()
 {
@@ -639,18 +649,21 @@ TextTrackManager::DispatchTimeMarchesOn(
   // through its usual monotonic increase during normal playback; current
   // executing call upon completion will check queue for further 'work'.
   if (!mTimeMarchesOnDispatched && !mShutdown &&
       (mMediaElement->GetHasUserInteraction() || mMediaElement->IsCurrentlyPlaying())) {
     WEBVTT_LOG("DispatchTimeMarchesOn");
     nsPIDOMWindowInner* win = mMediaElement->OwnerDoc()->GetInnerWindow();
     if (win) {
       nsGlobalWindow::Cast(win)->Dispatch(
-        "TextTrackManager::TimeMarchesOn", TaskCategory::Other,
-        NewRunnableMethod(this, &TextTrackManager::TimeMarchesOn));
+        "TextTrackManager::TimeMarchesOn",
+        TaskCategory::Other,
+        NewRunnableMethod("dom::TextTrackManager::TimeMarchesOn",
+                          this,
+                          &TextTrackManager::TimeMarchesOn));
       mTimeMarchesOnDispatched = true;
     }
   }
 }
 
 // https://html.spec.whatwg.org/multipage/embedded-content.html#time-marches-on
 void
 TextTrackManager::TimeMarchesOn()
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -116,17 +116,21 @@ using namespace mozilla::dom;
 /**
  * nsAutoFocusEvent is used to dispatch a focus event when a
  * nsGenericHTMLFormElement is binded to the tree with the autofocus attribute
  * enabled.
  */
 class nsAutoFocusEvent : public Runnable
 {
 public:
-  explicit nsAutoFocusEvent(nsGenericHTMLFormElement* aElement) : mElement(aElement) {}
+  explicit nsAutoFocusEvent(nsGenericHTMLFormElement* aElement)
+    : mozilla::Runnable("nsAutoFocusEvent")
+    , mElement(aElement)
+  {
+  }
 
   NS_IMETHOD Run() override {
     nsFocusManager* fm = nsFocusManager::GetFocusManager();
     if (!fm) {
       return NS_ERROR_NULL_POINTER;
     }
 
     nsIDocument* document = mElement->OwnerDoc();
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -2516,17 +2516,19 @@ void
 nsHTMLDocument::MaybeEditingStateChanged()
 {
   if (!mPendingMaybeEditingStateChanged && mMayStartLayout &&
       mUpdateNestLevel == 0 && (mContentEditableCount > 0) != IsEditingOn()) {
     if (nsContentUtils::IsSafeToRunScript()) {
       EditingStateChanged();
     } else if (!mInDestructor) {
       nsContentUtils::AddScriptRunner(
-        NewRunnableMethod(this, &nsHTMLDocument::MaybeEditingStateChanged));
+        NewRunnableMethod("nsHTMLDocument::MaybeEditingStateChanged",
+                          this,
+                          &nsHTMLDocument::MaybeEditingStateChanged));
     }
   }
 }
 
 void
 nsHTMLDocument::EndUpdate(nsUpdateType aUpdateType)
 {
   const bool reset = !mPendingMaybeEditingStateChanged;
@@ -2547,19 +2549,20 @@ nsHTMLDocument::SetMayStartLayout(bool a
 }
 
 
 
 // Helper class, used below in ChangeContentEditableCount().
 class DeferredContentEditableCountChangeEvent : public Runnable
 {
 public:
-  DeferredContentEditableCountChangeEvent(nsHTMLDocument *aDoc,
-                                          nsIContent *aElement)
-    : mDoc(aDoc)
+  DeferredContentEditableCountChangeEvent(nsHTMLDocument* aDoc,
+                                          nsIContent* aElement)
+    : mozilla::Runnable("DeferredContentEditableCountChangeEvent")
+    , mDoc(aDoc)
     , mElement(aElement)
   {
   }
 
   NS_IMETHOD Run() override {
     if (mElement && mElement->OwnerDoc() == mDoc) {
       mDoc->DeferredContentEditableCountChange(mElement);
     }
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -78,19 +78,20 @@ public:
 
 private:
   RefPtr<TextEditor> mTextEditor;
   bool mOuterTransaction;
 };
 
 class RestoreSelectionState : public Runnable {
 public:
-  RestoreSelectionState(nsTextEditorState *aState, nsTextControlFrame *aFrame)
-    : mFrame(aFrame),
-      mTextEditorState(aState)
+  RestoreSelectionState(nsTextEditorState* aState, nsTextControlFrame* aFrame)
+    : mozilla::Runnable("RestoreSelectionState")
+    , mFrame(aFrame)
+    , mTextEditorState(aState)
   {
   }
 
   NS_IMETHOD Run() override {
     if (!mTextEditorState) {
       return NS_OK;
     }
 
@@ -1233,20 +1234,21 @@ nsISelectionController*
 nsTextEditorState::GetSelectionController() const
 {
   return mSelCon;
 }
 
 // Helper class, used below in BindToFrame().
 class PrepareEditorEvent : public Runnable {
 public:
-  PrepareEditorEvent(nsTextEditorState &aState,
-                     nsIContent *aOwnerContent,
-                     const nsAString &aCurrentValue)
-    : mState(&aState)
+  PrepareEditorEvent(nsTextEditorState& aState,
+                     nsIContent* aOwnerContent,
+                     const nsAString& aCurrentValue)
+    : mozilla::Runnable("PrepareEditorEvent")
+    , mState(&aState)
     , mOwnerContent(aOwnerContent)
     , mCurrentValue(aCurrentValue)
   {
     aState.mValueTransferInProgress = true;
   }
 
   NS_IMETHOD Run() override {
     NS_ENSURE_TRUE(mState, NS_ERROR_NULL_POINTER);
@@ -2849,25 +2851,18 @@ nsTextEditorState::UpdateOverlayTextVisi
 {
   nsAutoString value, previewValue;
   bool valueIsEmpty = !HasNonEmptyValue();
   GetPreviewText(previewValue);
 
   mPreviewVisibility = valueIsEmpty && !previewValue.IsEmpty();
   mPlaceholderVisibility = valueIsEmpty && previewValue.IsEmpty();
 
-  static bool sPrefCached = false;
-  static bool sPrefShowOnFocus = true;
-  if (!sPrefCached) {
-    sPrefCached = true;
-    Preferences::AddBoolVarCache(&sPrefShowOnFocus,
-                                 "dom.placeholder.show_on_focus", true);
-  }
-
-  if (mPlaceholderVisibility && !sPrefShowOnFocus) {
+  if (mPlaceholderVisibility &&
+      !nsContentUtils::ShowInputPlaceholderOnFocus()) {
     nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
     mPlaceholderVisibility = !nsContentUtils::IsFocusedContent(content);
   }
 
   if (mBoundFrame && aNotify) {
     mBoundFrame->InvalidateFrame();
   }
 }
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -2218,27 +2218,17 @@ BackgroundDatabaseChild::RecvPBackground
   MOZ_ASSERT(request);
 
   RefPtr<IDBTransaction> transaction =
     IDBTransaction::CreateVersionChange(mDatabase,
                                         actor,
                                         request,
                                         aNextObjectStoreId,
                                         aNextIndexId);
-  if (NS_WARN_IF(!transaction)) {
-    // This can happen if we receive events after a worker has begun its
-    // shutdown process.
-    MOZ_ASSERT(!NS_IsMainThread());
-
-    // Report this to the console.
-    IDB_REPORT_INTERNAL_ERR();
-
-    MOZ_ALWAYS_TRUE(aActor->SendDeleteMe());
-    return IPC_OK();
-  }
+  MOZ_ASSERT(transaction);
 
   transaction->AssertIsOnOwningThread();
 
   actor->SetDOMTransaction(transaction);
 
   mDatabase->EnterSetVersionTransaction(aRequestedVersion);
 
   request->SetTransaction(transaction);
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -5934,17 +5934,18 @@ public:
     MOZ_ASSERT(NS_FAILED(aErrorCode));
 
     mResultCode = aErrorCode;
   }
 
 protected:
   DatabaseOperationBase(const nsID& aBackgroundChildLoggingId,
                         uint64_t aLoggingSerialNumber)
-    : mOwningEventTarget(GetCurrentThreadEventTarget())
+    : Runnable("dom::indexedDB::DatabaseOperationBase")
+    , mOwningEventTarget(GetCurrentThreadEventTarget())
     , mBackgroundChildLoggingId(aBackgroundChildLoggingId)
     , mLoggingSerialNumber(aLoggingSerialNumber)
     , mResultCode(NS_OK)
     , mOperationMayProceed(true)
     , mActorDestroyed(false)
   {
     AssertIsOnOwningThread();
   }
@@ -6290,17 +6291,18 @@ class WaitForTransactionsHelper final
     WaitingForTransactions,
     WaitingForFileHandles,
     Complete
   } mState;
 
 public:
   WaitForTransactionsHelper(const nsCString& aDatabaseId,
                             nsIRunnable* aCallback)
-    : mDatabaseId(aDatabaseId)
+    : Runnable("dom::indexedDB::WaitForTransactionsHelper")
+    , mDatabaseId(aDatabaseId)
     , mCallback(aCallback)
     , mState(State::Initial)
   {
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(!aDatabaseId.IsEmpty());
     MOZ_ASSERT(aCallback);
   }
 
@@ -8915,17 +8917,18 @@ class GetFileReferencesHelper final
   bool mResult;
   bool mWaiting;
 
 public:
   GetFileReferencesHelper(PersistenceType aPersistenceType,
                           const nsACString& aOrigin,
                           const nsAString& aDatabaseName,
                           int64_t aFileId)
-    : mPersistenceType(aPersistenceType)
+    : Runnable("dom::indexedDB::GetFileReferencesHelper")
+    , mPersistenceType(aPersistenceType)
     , mOrigin(aOrigin)
     , mDatabaseName(aDatabaseName)
     , mFileId(aFileId)
     , mMutex("GetFileReferencesHelper::mMutex")
     , mCondVar(mMutex, "GetFileReferencesHelper::mCondVar")
     , mMemRefCnt(-1)
     , mDBRefCnt(-1)
     , mSliceRefCnt(-1)
@@ -8943,16 +8946,19 @@ private:
   ~GetFileReferencesHelper() override = default;
 
   NS_DECL_NSIRUNNABLE
 };
 
 class FlushPendingFileDeletionsRunnable final
   : public Runnable
 {
+public:
+  FlushPendingFileDeletionsRunnable() : Runnable("FlushPendingFileDeletionsRunnable") {}
+
 private:
   ~FlushPendingFileDeletionsRunnable() override = default;
 
   NS_DECL_NSIRUNNABLE
 };
 
 class PermissionRequestHelper final
   : public PermissionRequestBase
@@ -9281,17 +9287,18 @@ class Maintenance final
   nsTArray<DirectoryInfo> mDirectoryInfos;
   nsDataHashtable<nsStringHashKey, DatabaseMaintenance*> mDatabaseMaintenances;
   nsresult mResultCode;
   Atomic<bool> mAborted;
   State mState;
 
 public:
   explicit Maintenance(QuotaClient* aQuotaClient)
-    : mQuotaClient(aQuotaClient)
+    : Runnable("dom::indexedDB::Maintenance")
+    , mQuotaClient(aQuotaClient)
     , mStartTime(PR_Now())
     , mResultCode(NS_OK)
     , mAborted(false)
     , mState(State::Initial)
   {
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(aQuotaClient);
     MOZ_ASSERT(QuotaClient::GetInstance() == aQuotaClient);
@@ -9497,17 +9504,18 @@ class DatabaseMaintenance final
   const PersistenceType mPersistenceType;
 
 public:
   DatabaseMaintenance(Maintenance* aMaintenance,
                       PersistenceType aPersistenceType,
                       const nsCString& aGroup,
                       const nsCString& aOrigin,
                       const nsString& aDatabasePath)
-    : mMaintenance(aMaintenance)
+    : Runnable("dom::indexedDB::DatabaseMaintenance")
+    , mMaintenance(aMaintenance)
     , mGroup(aGroup)
     , mOrigin(aOrigin)
     , mDatabasePath(aDatabasePath)
     , mPersistenceType(aPersistenceType)
   { }
 
   const nsString&
   DatabasePath() const
@@ -12495,17 +12503,17 @@ ConnectionPool::ShutdownThread(ThreadInf
   IDB_DEBUG_LOG(("ConnectionPool shutting down thread %" PRIu32,
                  runnable->SerialNumber()));
 
   // This should clean up the thread with the profiler.
   MOZ_ALWAYS_SUCCEEDS(thread->Dispatch(runnable.forget(),
                                        NS_DISPATCH_NORMAL));
 
   MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(
-                        NewRunnableMethod(thread, &nsIThread::Shutdown)));
+                        NewRunnableMethod("nsIThread::Shutdown", thread, &nsIThread::Shutdown)));
 
   mTotalThreadCount--;
 }
 
 void
 ConnectionPool::CloseIdleDatabases()
 {
   AssertIsOnOwningThread();
@@ -12597,17 +12605,17 @@ ConnectionPool::ScheduleTransaction(Tran
           created = true;
         } else {
           NS_WARNING("Failed to make new thread!");
         }
       } else if (!mDatabasesPerformingIdleMaintenance.IsEmpty()) {
         // We need a thread right now so force all idle processing to stop by
         // posting a dummy runnable to each thread that might be doing idle
         // maintenance.
-        nsCOMPtr<nsIRunnable> runnable = new Runnable();
+        nsCOMPtr<nsIRunnable> runnable = new Runnable("IndexedDBDummyRunnable");
 
         for (uint32_t index = mDatabasesPerformingIdleMaintenance.Length();
              index > 0;
              index--) {
           DatabaseInfo* dbInfo = mDatabasesPerformingIdleMaintenance[index - 1];
           MOZ_ASSERT(dbInfo);
           MOZ_ASSERT(dbInfo->mThreadInfo.mThread);
 
@@ -13029,17 +13037,18 @@ ConnectionPool::CloseDatabaseWhenIdleInt
     return true;
   }
 
   return false;
 }
 
 ConnectionPool::
 ConnectionRunnable::ConnectionRunnable(DatabaseInfo* aDatabaseInfo)
-  : mDatabaseInfo(aDatabaseInfo)
+  : Runnable("dom::indexedDB::ConnectionPool::ConnectionRunnable")
+  , mDatabaseInfo(aDatabaseInfo)
   , mOwningEventTarget(GetCurrentThreadEventTarget())
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aDatabaseInfo);
   MOZ_ASSERT(aDatabaseInfo->mConnectionPool);
   aDatabaseInfo->mConnectionPool->AssertIsOnOwningThread();
   MOZ_ASSERT(mOwningEventTarget);
 }
@@ -13189,21 +13198,22 @@ DatabasesCompleteCallback::DatabasesComp
 ConnectionPool::
 DatabasesCompleteCallback::~DatabasesCompleteCallback()
 {
   AssertIsOnBackgroundThread();
 
   MOZ_COUNT_DTOR(ConnectionPool::DatabasesCompleteCallback);
 }
 
-ConnectionPool::
-FinishCallbackWrapper::FinishCallbackWrapper(ConnectionPool* aConnectionPool,
-                                             uint64_t aTransactionId,
-                                             FinishCallback* aCallback)
-  : mConnectionPool(aConnectionPool)
+ConnectionPool::FinishCallbackWrapper::FinishCallbackWrapper(
+  ConnectionPool* aConnectionPool,
+  uint64_t aTransactionId,
+  FinishCallback* aCallback)
+  : Runnable("dom::indexedDB::ConnectionPool::FinishCallbackWrapper")
+  , mConnectionPool(aConnectionPool)
   , mCallback(aCallback)
   , mOwningEventTarget(GetCurrentThreadEventTarget())
   , mTransactionId(aTransactionId)
   , mHasRunOnce(false)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aConnectionPool);
   MOZ_ASSERT(aCallback);
@@ -13254,19 +13264,19 @@ FinishCallbackWrapper::Run()
 
   callback->TransactionFinishedAfterUnblock();
 
   return NS_OK;
 }
 
 uint32_t ConnectionPool::ThreadRunnable::sNextSerialNumber = 0;
 
-ConnectionPool::
-ThreadRunnable::ThreadRunnable()
-  : mSerialNumber(++sNextSerialNumber)
+ConnectionPool::ThreadRunnable::ThreadRunnable()
+  : Runnable("dom::indexedDB::ConnectionPool::ThreadRunnable")
+  , mSerialNumber(++sNextSerialNumber)
   , mFirstRun(true)
   , mContinueRunning(true)
 {
   AssertIsOnBackgroundThread();
 }
 
 ConnectionPool::
 ThreadRunnable::~ThreadRunnable()
@@ -14315,17 +14325,19 @@ Database::MaybeCloseConnection()
 {
   AssertIsOnBackgroundThread();
 
   if (!mTransactions.Count() &&
       !mActiveMutableFileCount &&
       IsClosed() &&
       mDirectoryLock) {
     nsCOMPtr<nsIRunnable> callback =
-      NewRunnableMethod(this, &Database::ConnectionClosedCallback);
+      NewRunnableMethod("dom::indexedDB::Database::ConnectionClosedCallback",
+                        this,
+                        &Database::ConnectionClosedCallback);
 
     RefPtr<WaitForTransactionsHelper> helper =
       new WaitForTransactionsHelper(Id(), callback);
     helper->WaitForTransactions();
   }
 }
 
 void
@@ -22504,18 +22516,20 @@ OpenDatabaseOp::SendResults()
 
     if (NS_FAILED(mResultCode)) {
       mDatabase->Invalidate();
     }
 
     // Make sure to release the database on this thread.
     mDatabase = nullptr;
   } else if (mDirectoryLock) {
-    nsCOMPtr<nsIRunnable> callback =
-      NewRunnableMethod(this, &OpenDatabaseOp::ConnectionClosedCallback);
+    nsCOMPtr<nsIRunnable> callback = NewRunnableMethod(
+      "dom::indexedDB::OpenDatabaseOp::ConnectionClosedCallback",
+      this,
+      &OpenDatabaseOp::ConnectionClosedCallback);
 
     RefPtr<WaitForTransactionsHelper> helper =
       new WaitForTransactionsHelper(mDatabaseId, callback);
     helper->WaitForTransactions();
   }
 
   FinishSendResults();
 }
--- a/dom/indexedDB/FileInfo.cpp
+++ b/dom/indexedDB/FileInfo.cpp
@@ -55,17 +55,18 @@ class CleanupFileRunnable final
   RefPtr<FileManager> mFileManager;
   int64_t mFileId;
 
 public:
   static void
   DoCleanup(FileManager* aFileManager, int64_t aFileId);
 
   CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId)
-    : mFileManager(aFileManager)
+    : Runnable("dom::indexedDB::CleanupFileRunnable")
+    , mFileManager(aFileManager)
     , mFileId(aFileId)
   {
     MOZ_ASSERT(aFileManager);
     MOZ_ASSERT(aFileId > 0);
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -68,19 +68,19 @@ const char kMemoryPressureObserverTopic[
 const char kWindowObserverTopic[] = "inner-window-destroyed";
 
 class CancelableRunnableWrapper final
   : public CancelableRunnable
 {
   nsCOMPtr<nsIRunnable> mRunnable;
 
 public:
-  explicit
-  CancelableRunnableWrapper(nsIRunnable* aRunnable)
-    : mRunnable(aRunnable)
+  explicit CancelableRunnableWrapper(nsIRunnable* aRunnable)
+    : CancelableRunnable("dom::CancelableRunnableWrapper")
+    , mRunnable(aRunnable)
   {
     MOZ_ASSERT(aRunnable);
   }
 
 private:
   ~CancelableRunnableWrapper()
   { }
 
@@ -172,28 +172,30 @@ IDBDatabase::IDBDatabase(IDBOpenDBReques
   : IDBWrapperCache(aRequest)
   , mFactory(aFactory)
   , mSpec(aSpec)
   , mBackgroundActor(aActor)
   , mFileHandleDisabled(aRequest->IsFileHandleDisabled())
   , mClosed(false)
   , mInvalidated(false)
   , mQuotaExceeded(false)
+  , mIncreasedActiveDatabaseCount(false)
 {
   MOZ_ASSERT(aRequest);
   MOZ_ASSERT(aFactory);
   aFactory->AssertIsOnOwningThread();
   MOZ_ASSERT(aActor);
   MOZ_ASSERT(aSpec);
 }
 
 IDBDatabase::~IDBDatabase()
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(!mBackgroundActor);
+  MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
 }
 
 // static
 already_AddRefed<IDBDatabase>
 IDBDatabase::Create(IDBOpenDBRequest* aRequest,
                     IDBFactory* aFactory,
                     BackgroundDatabaseChild* aActor,
                     DatabaseSpec* aSpec)
@@ -214,36 +216,35 @@ IDBDatabase::Create(IDBOpenDBRequest* aR
       uint64_t windowId = window->WindowID();
 
       RefPtr<Observer> observer = new Observer(db, windowId);
 
       nsCOMPtr<nsIObserverService> obsSvc = GetObserverService();
       MOZ_ASSERT(obsSvc);
 
       // This topic must be successfully registered.
-      if (NS_WARN_IF(NS_FAILED(
-            obsSvc->AddObserver(observer, kWindowObserverTopic, false)))) {
-        observer->Revoke();
-        return nullptr;
-      }
+      MOZ_ALWAYS_SUCCEEDS(
+        obsSvc->AddObserver(observer, kWindowObserverTopic, false));
 
       // These topics are not crucial.
       if (NS_FAILED(obsSvc->AddObserver(observer,
                                         kCycleCollectionObserverTopic,
                                         false)) ||
           NS_FAILED(obsSvc->AddObserver(observer,
                                         kMemoryPressureObserverTopic,
                                         false))) {
         NS_WARNING("Failed to add additional memory observers!");
       }
 
       db->mObserver.swap(observer);
     }
   }
 
+  db->IncreaseActiveDatabaseCount();
+
   return db.forget();
 }
 
 #ifdef DEBUG
 
 void
 IDBDatabase::AssertIsOnOwningThread() const
 {
@@ -284,16 +285,20 @@ IDBDatabase::CloseInternal()
       }
 
       mObserver = nullptr;
     }
 
     if (mBackgroundActor && !mInvalidated) {
       mBackgroundActor->SendClose();
     }
+
+    // Decrease the number of active databases right after the database is
+    // closed.
+    MaybeDecreaseActiveDatabaseCount();
   }
 }
 
 void
 IDBDatabase::InvalidateInternal()
 {
   AssertIsOnOwningThread();
 
@@ -685,20 +690,17 @@ IDBDatabase::Transaction(JSContext* aCx,
       return NS_ERROR_DOM_TYPE_ERR;
 
     default:
       MOZ_CRASH("Unknown mode!");
   }
 
   RefPtr<IDBTransaction> transaction =
     IDBTransaction::Create(aCx, this, sortedStoreNames, mode);
-  if (NS_WARN_IF(!transaction)) {
-    IDB_REPORT_INTERNAL_ERR();
-    return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
-  }
+  MOZ_ASSERT(transaction);
 
   BackgroundTransactionChild* actor =
     new BackgroundTransactionChild(transaction);
 
   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld]: "
                  "database(%s).transaction(%s)",
                "IndexedDB %s: C T[%lld]: IDBDatabase.transaction()",
                IDB_LOG_ID_STRING(),
@@ -962,29 +964,40 @@ IDBDatabase::NoteFinishedFileActor(PBack
 
     if (actor == aFileActor) {
       iter.Remove();
     }
   }
 }
 
 void
-IDBDatabase::DelayedMaybeExpireFileActors()
+IDBDatabase::NoteActiveTransaction()
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(mFactory);
+
+  // Increase the number of active transactions.
+  mFactory->UpdateActiveTransactionCount(1);
+}
+
+void
+IDBDatabase::NoteInactiveTransaction()
 {
   AssertIsOnOwningThread();
 
   if (!mBackgroundActor || !mFileActors.Count()) {
+    MOZ_ASSERT(mFactory);
+    mFactory->UpdateActiveTransactionCount(-1);
     return;
   }
 
   RefPtr<Runnable> runnable =
-    NewRunnableMethod<bool>("IDBDatabase::ExpireFileActors",
-                            this,
-                            &IDBDatabase::ExpireFileActors,
-                            /* aExpireAll */ false);
+    NewRunnableMethod("IDBDatabase::NoteInactiveTransactionDelayed",
+                      this,
+                      &IDBDatabase::NoteInactiveTransactionDelayed);
   MOZ_ASSERT(runnable);
 
   if (!NS_IsMainThread()) {
     // Wrap as a nsICancelableRunnable to make workers happy.
     RefPtr<Runnable> cancelable = new CancelableRunnableWrapper(runnable);
     cancelable.swap(runnable);
   }
 
@@ -1127,16 +1140,25 @@ IDBDatabase::Invalidate()
   if (!mInvalidated) {
     mInvalidated = true;
 
     InvalidateInternal();
   }
 }
 
 void
+IDBDatabase::NoteInactiveTransactionDelayed()
+{
+  ExpireFileActors(/* aExpireAll */ false);
+
+  MOZ_ASSERT(mFactory);
+  mFactory->UpdateActiveTransactionCount(-1);
+}
+
+void
 IDBDatabase::LogWarning(const char* aMessageName,
                         const nsAString& aFilename,
                         uint32_t aLineNumber,
                         uint32_t aColumnNumber)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aMessageName);
 
@@ -1347,10 +1369,34 @@ IDBDatabase::RenameIndex(int64_t aObject
   MOZ_ASSERT(foundIndexMetadata);
 
   // Update the name of the matched object store.
   foundIndexMetadata->name() = nsString(aName);
 
   return NS_OK;
 }
 
+void
+IDBDatabase::IncreaseActiveDatabaseCount()
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(mFactory);
+  MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
+
+  mFactory->UpdateActiveDatabaseCount(1);
+  mIncreasedActiveDatabaseCount = true;
+}
+
+void
+IDBDatabase::MaybeDecreaseActiveDatabaseCount()
+{
+  AssertIsOnOwningThread();
+
+  if (mIncreasedActiveDatabaseCount) {
+    // Decrease the number of active databases.
+    MOZ_ASSERT(mFactory);
+    mFactory->UpdateActiveDatabaseCount(-1);
+    mIncreasedActiveDatabaseCount = false;
+  }
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -81,16 +81,17 @@ class IDBDatabase final
 
   // Weak refs, IDBMutableFile strongly owns this IDBDatabase object.
   nsTArray<IDBMutableFile*> mLiveMutableFiles;
 
   const bool mFileHandleDisabled;
   bool mClosed;
   bool mInvalidated;
   bool mQuotaExceeded;
+  bool mIncreasedActiveDatabaseCount;
 
 public:
   static already_AddRefed<IDBDatabase>
   Create(IDBOpenDBRequest* aRequest,
          IDBFactory* aFactory,
          indexedDB::BackgroundDatabaseChild* aActor,
          DatabaseSpec* aSpec);
 
@@ -187,17 +188,20 @@ public:
 
   indexedDB::PBackgroundIDBDatabaseFileChild*
   GetOrCreateFileActorForBlob(Blob* aBlob);
 
   void
   NoteFinishedFileActor(indexedDB::PBackgroundIDBDatabaseFileChild* aFileActor);
 
   void
-  DelayedMaybeExpireFileActors();
+  NoteActiveTransaction();
+
+  void
+  NoteInactiveTransaction();
 
   // XXX This doesn't really belong here... It's only needed for IDBMutableFile
   //     serialization and should be removed or fixed someday.
   nsresult
   GetQuotaInfo(nsACString& aOrigin, PersistenceType* aPersistenceType);
 
   bool
   IsFileHandleDisabled() const
@@ -262,16 +266,20 @@ public:
     return CreateMutableFile(aCx, aName, aType, aRv);
   }
 
   void
   ClearBackgroundActor()
   {
     AssertIsOnOwningThread();
 
+    // Decrease the number of active databases if it was not done in
+    // CloseInternal().
+    MaybeDecreaseActiveDatabaseCount();
+
     mBackgroundActor = nullptr;
   }
 
   const DatabaseSpec*
   Spec() const
   {
     return mSpec;
   }
@@ -317,26 +325,35 @@ private:
 
   void
   ExpireFileActors(bool aExpireAll);
 
   void
   InvalidateMutableFiles();
 
   void
+  NoteInactiveTransactionDelayed();
+
+  void
   LogWarning(const char* aMessageName,
              const nsAString& aFilename,
              uint32_t aLineNumber,
              uint32_t aColumnNumber);
 
   // Only accessed by IDBObjectStore.
   nsresult
   RenameObjectStore(int64_t aObjectStoreId, const nsAString& aName);
 
   // Only accessed by IDBIndex.
   nsresult
   RenameIndex(int64_t aObjectStoreId, int64_t aIndexId, const nsAString& aName);
+
+  void
+  IncreaseActiveDatabaseCount();
+
+  void
+  MaybeDecreaseActiveDatabaseCount();
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_idbdatabase_h__
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -412,16 +412,34 @@ IDBFactory::AllowedForPrincipal(nsIPrinc
 
   if (aPrincipal->GetIsNullPrincipal()) {
     return false;
   }
 
   return true;
 }
 
+void
+IDBFactory::UpdateActiveTransactionCount(int32_t aDelta)
+{
+  AssertIsOnOwningThread();
+  if (mWindow) {
+    mWindow->UpdateActiveIndexedDBTransactionCount(aDelta);
+  }
+}
+
+void
+IDBFactory::UpdateActiveDatabaseCount(int32_t aDelta)
+{
+  AssertIsOnOwningThread();
+  if (mWindow) {
+    mWindow->UpdateActiveIndexedDBDatabaseCount(aDelta);
+  }
+}
+
 bool
 IDBFactory::IsChrome() const
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mPrincipalInfo);
 
   return mPrincipalInfo->type() == PrincipalInfo::TSystemPrincipalInfo;
 }
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -124,16 +124,30 @@ public:
   void
   ClearBackgroundActor()
   {
     AssertIsOnOwningThread();
 
     mBackgroundActor = nullptr;
   }
 
+  // Increase/Decrease the number of active transactions for the decision
+  // making of preemption and throttling.
+  // Note: If the state of its actor is not committed or aborted, it could block
+  // IDB operations in other window.
+  void
+  UpdateActiveTransactionCount(int32_t aDelta);
+
+  // Increase/Decrease the number of active databases and IDBOpenRequests for
+  // the decision making of preemption and throttling.
+  // Note: A non-closed database or a pending IDBOpenRequest could block
+  // IDB operations in other window.
+  void
+  UpdateActiveDatabaseCount(int32_t aDelta);
+
   void
   IncrementParentLoggingRequestSerialNumber();
 
   nsPIDOMWindowInner*
   GetParentObject() const
   {
     return mWindow;
   }
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -206,39 +206,16 @@ IDBRequest::Reset()
   AssertIsOnOwningThread();
 
   mResultVal.setUndefined();
   mHaveResultOrErrorCode = false;
   mError = nullptr;
 }
 
 void
-IDBRequest::DispatchNonTransactionError(nsresult aErrorCode)
-{
-  AssertIsOnOwningThread();
-  MOZ_ASSERT(NS_FAILED(aErrorCode));
-  MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_INDEXEDDB);
-
-  SetError(aErrorCode);
-
-  // Make an error event and fire it at the target.
-  nsCOMPtr<nsIDOMEvent> event =
-    CreateGenericEvent(this,
-                       nsDependentString(kErrorEventType),
-                       eDoesBubble,
-                       eCancelable);
-  MOZ_ASSERT(event);
-
-  bool ignored;
-  if (NS_FAILED(DispatchEvent(event, &ignored))) {
-    NS_WARNING("Failed to dispatch event!");
-  }
-}
-
-void
 IDBRequest::SetError(nsresult aRv)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(NS_FAILED(aRv));
   MOZ_ASSERT(NS_ERROR_GET_MODULE(aRv) == NS_ERROR_MODULE_DOM_INDEXEDDB);
   MOZ_ASSERT(!mError);
 
   mHaveResultOrErrorCode = true;
@@ -486,26 +463,28 @@ private:
 };
 
 IDBOpenDBRequest::IDBOpenDBRequest(IDBFactory* aFactory,
                                    nsPIDOMWindowInner* aOwner,
                                    bool aFileHandleDisabled)
   : IDBRequest(aOwner)
   , mFactory(aFactory)
   , mFileHandleDisabled(aFileHandleDisabled)
+  , mIncreasedActiveDatabaseCount(false)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aFactory);
 
   // aOwner may be null.
 }
 
 IDBOpenDBRequest::~IDBOpenDBRequest()
 {
   AssertIsOnOwningThread();
+  MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
 }
 
 // static
 already_AddRefed<IDBOpenDBRequest>
 IDBOpenDBRequest::CreateForWindow(JSContext* aCx,
                                   IDBFactory* aFactory,
                                   nsPIDOMWindowInner* aOwner,
                                   JS::Handle<JSObject*> aScriptOwner)
@@ -518,16 +497,18 @@ IDBOpenDBRequest::CreateForWindow(JSCont
   bool fileHandleDisabled = !IndexedDatabaseManager::IsFileHandleEnabled();
 
   RefPtr<IDBOpenDBRequest> request =
     new IDBOpenDBRequest(aFactory, aOwner, fileHandleDisabled);
   CaptureCaller(aCx, request->mFilename, &request->mLineNo, &request->mColumn);
 
   request->SetScriptOwner(aScriptOwner);
 
+  request->IncreaseActiveDatabaseCount();
+
   return request.forget();
 }
 
 // static
 already_AddRefed<IDBOpenDBRequest>
 IDBOpenDBRequest::CreateForJS(JSContext* aCx,
                               IDBFactory* aFactory,
                               JS::Handle<JSObject*> aScriptOwner)
@@ -554,40 +535,99 @@ IDBOpenDBRequest::CreateForJS(JSContext*
     if (NS_WARN_IF(!workerHolder->HoldWorker(workerPrivate, Canceling))) {
       workerHolder->NoteAddWorkerHolderFailed();
       return nullptr;
     }
 
     request->mWorkerHolder = Move(workerHolder);
   }
 
+  request->IncreaseActiveDatabaseCount();
+
   return request.forget();
 }
 
 void
 IDBOpenDBRequest::SetTransaction(IDBTransaction* aTransaction)
 {
   AssertIsOnOwningThread();
 
   MOZ_ASSERT(!aTransaction || !mTransaction);
 
   mTransaction = aTransaction;
 }
 
 void
+IDBOpenDBRequest::DispatchNonTransactionError(nsresult aErrorCode)
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(NS_FAILED(aErrorCode));
+  MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_INDEXEDDB);
+
+  // The actor failed to initiate, decrease the number of active IDBOpenRequests
+  // here since NoteComplete won't be called.
+  MaybeDecreaseActiveDatabaseCount();
+
+  SetError(aErrorCode);
+
+  // Make an error event and fire it at the target.
+  nsCOMPtr<nsIDOMEvent> event =
+    CreateGenericEvent(this,
+                       nsDependentString(kErrorEventType),
+                       eDoesBubble,
+                       eCancelable);
+  MOZ_ASSERT(event);
+
+  bool ignored;
+  if (NS_FAILED(DispatchEvent(event, &ignored))) {
+    NS_WARNING("Failed to dispatch event!");
+  }
+}
+
+void
 IDBOpenDBRequest::NoteComplete()
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerHolder);
 
+  // Normally, we decrease the number of active IDBOpenRequests here.
+  MaybeDecreaseActiveDatabaseCount();
+
   // If we have a WorkerHolder installed on the worker then nulling this out
   // will uninstall it from the worker.
   mWorkerHolder = nullptr;
 }
 
+void
+IDBOpenDBRequest::IncreaseActiveDatabaseCount()
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
+
+  // Increase the number of active IDBOpenRequests.
+  // Note: We count here instead of the actor's ctor because the preemption
+  // could happen at next JS interrupt but its BackgroundFactoryRequestChild
+  // could be created asynchronously from IDBFactory::BackgroundCreateCallback
+  // ::ActorCreated() if its PBackgroundChild is not created yet on this thread.
+  mFactory->UpdateActiveDatabaseCount(1);
+  mIncreasedActiveDatabaseCount = true;
+}
+
+void
+IDBOpenDBRequest::MaybeDecreaseActiveDatabaseCount()
+{
+  AssertIsOnOwningThread();
+
+  if (mIncreasedActiveDatabaseCount) {
+    // Decrease the number of active IDBOpenRequests.
+    mFactory->UpdateActiveDatabaseCount(-1);
+    mIncreasedActiveDatabaseCount = false;
+  }
+}
+
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBOpenDBRequest)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBOpenDBRequest,
                                                   IDBRequest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFactory)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBOpenDBRequest,
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -89,19 +89,16 @@ public:
 
   void
   GetSource(Nullable<OwningIDBObjectStoreOrIDBIndexOrIDBCursor>& aSource) const;
 
   void
   Reset();
 
   void
-  DispatchNonTransactionError(nsresult aErrorCode);
-
-  void
   SetResultCallback(ResultCallback* aCallback);
 
   void
   SetError(nsresult aRv);
 
   nsresult
   GetErrorCode() const
 #ifdef DEBUG
@@ -222,16 +219,17 @@ class IDBOpenDBRequest final
   class WorkerHolder;
 
   // Only touched on the owning thread.
   RefPtr<IDBFactory> mFactory;
 
   nsAutoPtr<WorkerHolder> mWorkerHolder;
 
   const bool mFileHandleDisabled;
+  bool mIncreasedActiveDatabaseCount;
 
 public:
   static already_AddRefed<IDBOpenDBRequest>
   CreateForWindow(JSContext* aCx,
                   IDBFactory* aFactory,
                   nsPIDOMWindowInner* aOwner,
                   JS::Handle<JSObject*> aScriptOwner);
 
@@ -245,16 +243,19 @@ public:
   {
     return mFileHandleDisabled;
   }
 
   void
   SetTransaction(IDBTransaction* aTransaction);
 
   void
+  DispatchNonTransactionError(nsresult aErrorCode);
+
+  void
   NoteComplete();
 
   // nsIDOMEventTarget
   virtual nsresult
   PostHandleEvent(EventChainPostVisitor& aVisitor) override;
 
   IDBFactory*
   Factory() const
@@ -273,14 +274,20 @@ public:
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
   IDBOpenDBRequest(IDBFactory* aFactory,
                    nsPIDOMWindowInner* aOwner,
                    bool aFileHandleDisabled);
 
   ~IDBOpenDBRequest();
+
+  void
+  IncreaseActiveDatabaseCount();
+
+  void
+  MaybeDecreaseActiveDatabaseCount();
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_idbrequest_h__
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -83,16 +83,17 @@ IDBTransaction::IDBTransaction(IDBDataba
   , mPendingRequestCount(0)
   , mLineNo(0)
   , mColumn(0)
   , mReadyState(IDBTransaction::INITIAL)
   , mMode(aMode)
   , mCreating(false)
   , mRegistered(false)
   , mAbortedByScript(false)
+  , mNotedActiveTransaction(false)
 #ifdef DEBUG
   , mSentCommitOrAbort(false)
   , mFiredCompleteOrAbort(false)
 #endif
 {
   MOZ_ASSERT(aDatabase);
   aDatabase->AssertIsOnOwningThread();
 
@@ -129,16 +130,17 @@ IDBTransaction::IDBTransaction(IDBDataba
 #endif
 }
 
 IDBTransaction::~IDBTransaction()
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(!mPendingRequestCount);
   MOZ_ASSERT(!mCreating);
+  MOZ_ASSERT(!mNotedActiveTransaction);
   MOZ_ASSERT(mSentCommitOrAbort);
   MOZ_ASSERT_IF(mMode == VERSION_CHANGE &&
                   mBackgroundActor.mVersionChangeBackgroundActor,
                 mFiredCompleteOrAbort);
   MOZ_ASSERT_IF(mMode != VERSION_CHANGE &&
                   mBackgroundActor.mNormalBackgroundActor,
                 mFiredCompleteOrAbort);
 
@@ -189,16 +191,18 @@ IDBTransaction::CreateVersionChange(
   aOpenRequest->GetCallerLocation(transaction->mFilename,
                                   &transaction->mLineNo, &transaction->mColumn);
 
   transaction->SetScriptOwner(aDatabase->GetScriptOwner());
 
   nsCOMPtr<nsIRunnable> runnable = do_QueryObject(transaction);
   nsContentUtils::RunInMetastableState(runnable.forget());
 
+  transaction->NoteActiveTransaction();
+
   transaction->mBackgroundActor.mVersionChangeBackgroundActor = aActor;
   transaction->mNextObjectStoreId = aNextObjectStoreId;
   transaction->mNextIndexId = aNextIndexId;
   transaction->mCreating = true;
 
   aDatabase->RegisterTransaction(transaction);
   transaction->mRegistered = true;
 
@@ -279,16 +283,18 @@ IDBTransaction::AssertIsOnOwningThread()
 void
 IDBTransaction::SetBackgroundActor(indexedDB::BackgroundTransactionChild* aBackgroundActor)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aBackgroundActor);
   MOZ_ASSERT(!mBackgroundActor.mNormalBackgroundActor);
   MOZ_ASSERT(mMode != VERSION_CHANGE);
 
+  NoteActiveTransaction();
+
   mBackgroundActor.mNormalBackgroundActor = aBackgroundActor;
 }
 
 BackgroundRequestChild*
 IDBTransaction::StartRequest(IDBRequest* aRequest, const RequestParams& aParams)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aRequest);
@@ -469,16 +475,37 @@ IDBTransaction::SendAbort(nsresult aResu
     mBackgroundActor.mNormalBackgroundActor->SendAbort(aResultCode);
   }
 
 #ifdef DEBUG
   mSentCommitOrAbort = true;
 #endif
 }
 
+void
+IDBTransaction::NoteActiveTransaction()
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(!mNotedActiveTransaction);
+
+  mDatabase->NoteActiveTransaction();
+  mNotedActiveTransaction = true;
+}
+
+void
+IDBTransaction::MaybeNoteInactiveTransaction()
+{
+  AssertIsOnOwningThread();
+
+  if (mNotedActiveTransaction) {
+    mDatabase->NoteInactiveTransaction();
+    mNotedActiveTransaction = false;
+  }
+}
+
 bool
 IDBTransaction::IsOpen() const
 {
   AssertIsOnOwningThread();
 
   // If we haven't started anything then we're open.
   if (mReadyState == IDBTransaction::INITIAL) {
     return true;
@@ -829,17 +856,25 @@ IDBTransaction::FireCompleteOrAbortEvent
                  mAbortCode);
   }
 
   bool dummy;
   if (NS_FAILED(DispatchEvent(event, &dummy))) {
     NS_WARNING("DispatchEvent failed!");
   }
 
-  mDatabase->DelayedMaybeExpireFileActors();
+  // Normally, we note inactive transaction here instead of
+  // IDBTransaction::ClearBackgroundActor() because here is the earliest place
+  // to know that it becomes non-blocking to allow the scheduler to start the
+  // preemption as soon as it can.
+  // Note: If the IDBTransaction object is held by the script,
+  // ClearBackgroundActor() will be done in ~IDBTransaction() until garbage
+  // collected after its window is closed which prevents us to preempt its
+  // window immediately after committed.
+  MaybeNoteInactiveTransaction();
 }
 
 int64_t
 IDBTransaction::NextObjectStoreId()
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(VERSION_CHANGE == mMode);
 
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -104,16 +104,17 @@ private:
   uint32_t mColumn;
 
   ReadyState mReadyState;
   Mode mMode;
 
   bool mCreating;
   bool mRegistered;
   bool mAbortedByScript;
+  bool mNotedActiveTransaction;
 
 #ifdef DEBUG
   bool mSentCommitOrAbort;
   bool mFiredCompleteOrAbort;
 #endif
 
 public:
   static already_AddRefed<IDBTransaction>
@@ -147,16 +148,20 @@ public:
   {
     AssertIsOnOwningThread();
 
     if (mMode == VERSION_CHANGE) {
       mBackgroundActor.mVersionChangeBackgroundActor = nullptr;
     } else {
       mBackgroundActor.mNormalBackgroundActor = nullptr;
     }
+
+    // Note inactive transaction here if we didn't receive the Complete message
+    // from the parent.
+    MaybeNoteInactiveTransaction();
   }
 
   indexedDB::BackgroundRequestChild*
   StartRequest(IDBRequest* aRequest, const indexedDB::RequestParams& aParams);
 
   void
   OpenCursor(indexedDB::BackgroundCursorChild* aBackgroundActor,
              const indexedDB::OpenCursorParams& aParams);
@@ -327,16 +332,22 @@ private:
 
   void
   SendCommit();
 
   void
   SendAbort(nsresult aResultCode);
 
   void
+  NoteActiveTransaction();
+
+  void
+  MaybeNoteInactiveTransaction();
+
+  void
   OnNewRequest();
 
   void
   OnRequestFinished(bool aActorDestroyedNormally);
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/indexedDB/ScriptErrorHelper.cpp
+++ b/dom/indexedDB/ScriptErrorHelper.cpp
@@ -31,17 +31,18 @@ class ScriptErrorRunnable final : public
 public:
   ScriptErrorRunnable(const nsAString& aMessage,
                       const nsAString& aFilename,
                       uint32_t aLineNumber,
                       uint32_t aColumnNumber,
                       uint32_t aSeverityFlag,
                       bool aIsChrome,
                       uint64_t aInnerWindowID)
-    : mMessage(aMessage)
+    : mozilla::Runnable("ScriptErrorRunnable")
+    , mMessage(aMessage)
     , mFilename(aFilename)
     , mLineNumber(aLineNumber)
     , mColumnNumber(aColumnNumber)
     , mSeverityFlag(aSeverityFlag)
     , mInnerWindowID(aInnerWindowID)
     , mIsChrome(aIsChrome)
   {
     MOZ_ASSERT(!NS_IsMainThread());
@@ -50,17 +51,18 @@ public:
 
   ScriptErrorRunnable(const nsACString& aMessageName,
                       const nsAString& aFilename,
                       uint32_t aLineNumber,
                       uint32_t aColumnNumber,
                       uint32_t aSeverityFlag,
                       bool aIsChrome,
                       uint64_t aInnerWindowID)
-    : mMessageName(aMessageName)
+    : mozilla::Runnable("ScriptErrorRunnable")
+    , mMessageName(aMessageName)
     , mFilename(aFilename)
     , mLineNumber(aLineNumber)
     , mColumnNumber(aColumnNumber)
     , mSeverityFlag(aSeverityFlag)
     , mInnerWindowID(aInnerWindowID)
     , mIsChrome(aIsChrome)
   {
     MOZ_ASSERT(!NS_IsMainThread());
--- a/dom/indexedDB/test/browser.ini
+++ b/dom/indexedDB/test/browser.ini
@@ -11,11 +11,12 @@ support-files =
   browser_permissionsWorker.html
   browser_permissionsWorker.js
   bug839193.js
   bug839193.xul
 
 [browser_forgetThisSite.js]
 [browser_permissionsPromptAllow.js]
 [browser_permissionsPromptDeny.js]
+skip-if = os == 'mac' # bug 1324163
 [browser_permissionsPromptWorker.js]
 [browser_perwindow_privateBrowsing.js]
 [browser_bug839193.js]
--- a/dom/ipc/ContentBridgeChild.cpp
+++ b/dom/ipc/ContentBridgeChild.cpp
@@ -27,17 +27,20 @@ ContentBridgeChild::ContentBridgeChild()
 
 ContentBridgeChild::~ContentBridgeChild()
 {
 }
 
 void
 ContentBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
 {
-  MessageLoop::current()->PostTask(NewRunnableMethod(this, &ContentBridgeChild::DeferredDestroy));
+  MessageLoop::current()->PostTask(
+    NewRunnableMethod("dom::ContentBridgeChild::DeferredDestroy",
+                      this,
+                      &ContentBridgeChild::DeferredDestroy));
 }
 
 /*static*/ void
 ContentBridgeChild::Create(Endpoint<PContentBridgeChild>&& aEndpoint)
 {
   RefPtr<ContentBridgeChild> bridge = new ContentBridgeChild();
   bridge->mSelfRef = bridge;
 
--- a/dom/ipc/ContentBridgeParent.cpp
+++ b/dom/ipc/ContentBridgeParent.cpp
@@ -31,17 +31,20 @@ ContentBridgeParent::~ContentBridgeParen
 
 void
 ContentBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
     os->RemoveObserver(this, "content-child-shutdown");
   }
-  MessageLoop::current()->PostTask(NewRunnableMethod(this, &ContentBridgeParent::DeferredDestroy));
+  MessageLoop::current()->PostTask(
+    NewRunnableMethod("dom::ContentBridgeParent::DeferredDestroy",
+                      this,
+                      &ContentBridgeParent::DeferredDestroy));
 }
 
 /*static*/ ContentBridgeParent*
 ContentBridgeParent::Create(Endpoint<PContentBridgeParent>&& aEndpoint)
 {
   RefPtr<ContentBridgeParent> bridge = new ContentBridgeParent();
   bridge->mSelfRef = bridge;
 
@@ -168,17 +171,18 @@ ContentBridgeParent::DeallocPBrowserPare
   return nsIContentParent::DeallocPBrowserParent(aParent);
 }
 
 void
 ContentBridgeParent::NotifyTabDestroyed()
 {
   int32_t numLiveTabs = ManagedPBrowserParent().Count();
   if (numLiveTabs == 1) {
-    MessageLoop::current()->PostTask(NewRunnableMethod(this, &ContentBridgeParent::Close));
+    MessageLoop::current()->PostTask(NewRunnableMethod(
+      "dom::ContentBridgeParent::Close", this, &ContentBridgeParent::Close));
   }
 }
 
 // This implementation is identical to ContentParent::GetCPOWManager but we can't
 // move it to nsIContentParent because it calls ManagedPJavaScriptParent() which
 // only exists in PContentParent and PContentBridgeParent.
 jsipc::CPOWManager*
 ContentBridgeParent::GetCPOWManager()
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2771,20 +2771,22 @@ ContentChild::StartForceKillTimer()
   if (mForceKillTimer) {
     return;
   }
 
   int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
   if (timeoutSecs > 0) {
     mForceKillTimer = do_CreateInstance("@mozilla.org/timer;1");
     MOZ_ASSERT(mForceKillTimer);
-    mForceKillTimer->InitWithFuncCallback(ContentChild::ForceKillTimerCallback,
+    mForceKillTimer->InitWithNamedFuncCallback(
+      ContentChild::ForceKillTimerCallback,
       this,
       timeoutSecs * 1000,
-      nsITimer::TYPE_ONE_SHOT);
+      nsITimer::TYPE_ONE_SHOT,
+      "dom::ContentChild::StartForceKillTimer");
   }
 }
 
 /* static */ void
 ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
 {
   ProcessChild::QuickExit();
 }
@@ -2804,17 +2806,19 @@ ContentChild::RecvShutdown()
   nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
   if (NS_SUCCEEDED(rv) && thread) {
     RefPtr<nsThread> mainThread(thread.forget().downcast<nsThread>());
     if (mainThread->RecursionDepth() > 1) {
       // We're in a nested event loop. Let's delay for an arbitrary period of
       // time (100ms) in the hopes that the event loop will have finished by
       // then.
       MessageLoop::current()->PostDelayedTask(
-        NewRunnableMethod(this, &ContentChild::RecvShutdown), 100);
+        NewRunnableMethod(
+          "dom::ContentChild::RecvShutdown", this, &ContentChild::RecvShutdown),
+        100);
       return IPC_OK();
     }
   }
 
   mShuttingDown = true;
 
   if (mPolicy) {
     mPolicy->Deactivate();
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1706,17 +1706,21 @@ DelayedDeleteSubprocess(GeckoChildProces
   XRE_GetIOMessageLoop()->PostTask(task.forget());
 }
 
 // This runnable only exists to delegate ownership of the
 // ContentParent to this runnable, until it's deleted by the event
 // system.
 struct DelayedDeleteContentParentTask : public Runnable
 {
-  explicit DelayedDeleteContentParentTask(ContentParent* aObj) : mObj(aObj) { }
+  explicit DelayedDeleteContentParentTask(ContentParent* aObj)
+    : Runnable("dom::DelayedDeleteContentParentTask")
+    , mObj(aObj)
+  {
+  }
 
   // No-op
   NS_IMETHOD Run() override { return NS_OK; }
 
   RefPtr<ContentParent> mObj;
 };
 
 } // namespace
@@ -1838,20 +1842,21 @@ ContentParent::ActorDestroy(ActorDestroy
 
   ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
   nsTArray<ContentParentId> childIDArray =
     cpm->GetAllChildProcessById(this->ChildID());
 
   // Destroy any processes created by this ContentParent
   for(uint32_t i = 0; i < childIDArray.Length(); i++) {
     ContentParent* cp = cpm->GetContentProcessById(childIDArray[i]);
-    MessageLoop::current()->PostTask(NewRunnableMethod
-                                     <ShutDownMethod>(cp,
-                                                      &ContentParent::ShutDownProcess,
-                                                      SEND_SHUTDOWN_MESSAGE));
+    MessageLoop::current()->PostTask(
+      NewRunnableMethod<ShutDownMethod>("dom::ContentParent::ShutDownProcess",
+                                        cp,
+                                        &ContentParent::ShutDownProcess,
+                                        SEND_SHUTDOWN_MESSAGE));
   }
   cpm->RemoveContentProcess(this->ChildID());
 
   if (mDriverCrashGuard) {
     mDriverCrashGuard->NotifyCrashed();
   }
 
   // Unregister all the BlobURLs registered by the ContentChild.
@@ -1967,20 +1972,22 @@ ContentParent::StartForceKillTimer()
   if (mForceKillTimer || !mIPCOpen) {
     return;
   }
 
   int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
   if (timeoutSecs > 0) {
     mForceKillTimer = do_CreateInstance("@mozilla.org/timer;1");
     MOZ_ASSERT(mForceKillTimer);
-    mForceKillTimer->InitWithFuncCallback(ContentParent::ForceKillTimerCallback,
-                                          this,
-                                          timeoutSecs * 1000,
-                                          nsITimer::TYPE_ONE_SHOT);
+    mForceKillTimer->InitWithNamedFuncCallback(
+      ContentParent::ForceKillTimerCallback,
+      this,
+      timeoutSecs * 1000,
+      nsITimer::TYPE_ONE_SHOT,
+      "dom::ContentParent::StartForceKillTimer");
   }
 }
 
 void
 ContentParent::NotifyTabDestroyed(const TabId& aTabId,
                                   bool aNotifiedDestroying)
 {
   if (aNotifiedDestroying) {
@@ -1999,20 +2006,21 @@ ContentParent::NotifyTabDestroyed(const 
   // because of popup windows.  When the last one closes, shut
   // us down.
   ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
   nsTArray<TabId> tabIds = cpm->GetTabParentsByProcessId(this->ChildID());
 
   if (tabIds.Length() == 1 && !ShouldKeepProcessAlive() && !TryToRecycle()) {
     // In the case of normal shutdown, send a shutdown message to child to
     // allow it to perform shutdown tasks.
-    MessageLoop::current()->PostTask(NewRunnableMethod
-                                     <ShutDownMethod>(this,
-                                                      &ContentParent::ShutDownProcess,
-                                                      SEND_SHUTDOWN_MESSAGE));
+    MessageLoop::current()->PostTask(
+      NewRunnableMethod<ShutDownMethod>("dom::ContentParent::ShutDownProcess",
+                                        this,
+                                        &ContentParent::ShutDownProcess,
+                                        SEND_SHUTDOWN_MESSAGE));
   }
 }
 
 jsipc::CPOWManager*
 ContentParent::GetCPOWManager()
 {
   if (PJavaScriptParent* p = LoneManagedOrNullAsserts(ManagedPJavaScriptParent())) {
     return CPOWManagerFor(p);
@@ -4110,17 +4118,18 @@ ContentParent::RecvBackUpXResources(cons
 #endif
   return IPC_OK();
 }
 
 class AnonymousTemporaryFileRequestor final : public Runnable
 {
 public:
   AnonymousTemporaryFileRequestor(ContentParent* aCP, const uint64_t& aID)
-    : mCP(aCP)
+    : Runnable("dom::AnonymousTemporaryFileRequestor")
+    , mCP(aCP)
     , mID(aID)
     , mRv(NS_OK)
     , mPRFD(nullptr)
   {
   }
 
   NS_IMETHOD Run() override
   {
--- a/dom/ipc/FilePickerParent.cpp
+++ b/dom/ipc/FilePickerParent.cpp
@@ -44,21 +44,22 @@ FilePickerParent::~FilePickerParent()
 {
 }
 
 // We run code in three places:
 // 1. The main thread calls Dispatch() to start the runnable.
 // 2. The stream transport thread stat()s the file in Run() and then dispatches
 // the same runnable on the main thread.
 // 3. The main thread sends the results over IPC.
-FilePickerParent::IORunnable::IORunnable(FilePickerParent *aFPParent,
+FilePickerParent::IORunnable::IORunnable(FilePickerParent* aFPParent,
                                          nsTArray<nsCOMPtr<nsIFile>>& aFiles,
                                          bool aIsDirectory)
- : mFilePickerParent(aFPParent)
- , mIsDirectory(aIsDirectory)
+  : mozilla::Runnable("dom::FilePickerParent::IORunnable")
+  , mFilePickerParent(aFPParent)
+  , mIsDirectory(aIsDirectory)
 {
   mFiles.SwapElements(aFiles);
   MOZ_ASSERT_IF(aIsDirectory, mFiles.Length() == 1);
 }
 
 bool
 FilePickerParent::IORunnable::Dispatch()
 {
--- a/dom/ipc/PreallocatedProcessManager.cpp
+++ b/dom/ipc/PreallocatedProcessManager.cpp
@@ -201,29 +201,34 @@ PreallocatedProcessManagerImpl::Allocate
   if (!mEnabled || mPreallocatedProcess || mShutdown) {
     return;
   }
 
   // Originally AllocateOnIdle() was post here, but since the gecko parent
   // message loop in practice never goes idle, that didn't work out well.
   // Let's just launch the process after the delay.
   NS_DelayedDispatchToCurrentThread(
-    NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateNow),
+    NewRunnableMethod("PreallocatedProcessManagerImpl::AllocateNow",
+                      this,
+                      &PreallocatedProcessManagerImpl::AllocateNow),
     Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
                          DEFAULT_ALLOCATE_DELAY));
 }
 
 void
 PreallocatedProcessManagerImpl::AllocateOnIdle()
 {
   if (!mEnabled || mPreallocatedProcess || mShutdown) {
     return;
   }
 
-  NS_IdleDispatchToCurrentThread(NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateNow));
+  NS_IdleDispatchToCurrentThread(
+    NewRunnableMethod("PreallocatedProcessManagerImpl::AllocateNow",
+                      this,
+                      &PreallocatedProcessManagerImpl::AllocateNow));
 }
 
 void
 PreallocatedProcessManagerImpl::AllocateNow()
 {
   if (!mEnabled || mPreallocatedProcess || mShutdown ||
       ContentParent::IsMaxProcessCountReached(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE))) {
     return;
--- a/dom/ipc/ProcessHangMonitor.cpp
+++ b/dom/ipc/ProcessHangMonitor.cpp
@@ -366,17 +366,19 @@ void
 HangMonitorChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   MOZ_RELEASE_ASSERT(IsOnThread());
 
   mIPCOpen = false;
 
   // We use a task here to ensure that IPDL is finished with this
   // HangMonitorChild before it gets deleted on the main thread.
-  Dispatch(NewNonOwningRunnableMethod(this, &HangMonitorChild::ShutdownOnThread));
+  Dispatch(NewNonOwningRunnableMethod("HangMonitorChild::ShutdownOnThread",
+                                      this,
+                                      &HangMonitorChild::ShutdownOnThread));
 }
 
 mozilla::ipc::IPCResult
 HangMonitorChild::RecvTerminateScript()
 {
   MOZ_RELEASE_ASSERT(IsOnThread());
 
   MonitorAutoLock lock(mMonitor);
@@ -477,20 +479,22 @@ HangMonitorChild::NotifySlowScript(nsITa
 
   TabId id;
   if (aTabChild) {
     RefPtr<TabChild> tabChild = static_cast<TabChild*>(aTabChild);
     id = tabChild->GetTabId();
   }
   nsAutoCString filename(aFileName);
 
-  Dispatch(NewNonOwningRunnableMethod
-           <TabId, nsCString>(this,
-                              &HangMonitorChild::NotifySlowScriptAsync,
-                              id, filename));
+  Dispatch(NewNonOwningRunnableMethod<TabId, nsCString>(
+    "HangMonitorChild::NotifySlowScriptAsync",
+    this,
+    &HangMonitorChild::NotifySlowScriptAsync,
+    id,
+    filename));
   return SlowScriptAction::Continue;
 }
 
 bool
 HangMonitorChild::IsDebuggerStartupComplete()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
@@ -508,19 +512,21 @@ void
 HangMonitorChild::NotifyPluginHang(uint32_t aPluginId)
 {
   // main thread in the child
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   mSentReport = true;
 
   // bounce to background thread
-  Dispatch(NewNonOwningRunnableMethod<uint32_t>(this,
-                                                &HangMonitorChild::NotifyPluginHangAsync,
-                                                aPluginId));
+  Dispatch(NewNonOwningRunnableMethod<uint32_t>(
+    "HangMonitorChild::NotifyPluginHangAsync",
+    this,
+    &HangMonitorChild::NotifyPluginHangAsync,
+    aPluginId));
 }
 
 void
 HangMonitorChild::NotifyPluginHangAsync(uint32_t aPluginId)
 {
   MOZ_RELEASE_ASSERT(IsOnThread());
 
   // bounce back to parent on background thread
@@ -532,17 +538,19 @@ HangMonitorChild::NotifyPluginHangAsync(
 
 void
 HangMonitorChild::ClearHang()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mSentReport) {
     // bounce to background thread
-    Dispatch(NewNonOwningRunnableMethod(this, &HangMonitorChild::ClearHangAsync));
+    Dispatch(NewNonOwningRunnableMethod("HangMonitorChild::ClearHangAsync",
+                                        this,
+                                        &HangMonitorChild::ClearHangAsync));
 
     MonitorAutoLock lock(mMonitor);
     mSentReport = false;
     mTerminateScript = false;
     mStartDebugger = false;
     mFinishedStartingDebugger = false;
   }
 }
@@ -600,17 +608,18 @@ HangMonitorParent::Shutdown()
 
   MonitorAutoLock lock(mMonitor);
 
   if (mProcess) {
     mProcess->Clear();
     mProcess = nullptr;
   }
 
-  Dispatch(NewNonOwningRunnableMethod(this,
+  Dispatch(NewNonOwningRunnableMethod("HangMonitorParent::ShutdownOnThread",
+                                      this,
                                       &HangMonitorParent::ShutdownOnThread));
 
   while (!mShutdownDone) {
     mMonitor.Wait();
   }
 }
 
 void
@@ -631,18 +640,22 @@ HangMonitorParent::ShutdownOnThread()
 }
 
 void
 HangMonitorParent::ForcePaint(dom::TabParent* aTab, uint64_t aLayerObserverEpoch)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   if (sShouldForcePaint) {
     TabId id = aTab->GetTabId();
-    Dispatch(NewNonOwningRunnableMethod
-             <TabId, uint64_t>(this, &HangMonitorParent::ForcePaintOnThread, id, aLayerObserverEpoch));
+    Dispatch(NewNonOwningRunnableMethod<TabId, uint64_t>(
+      "HangMonitorParent::ForcePaintOnThread",
+      this,
+      &HangMonitorParent::ForcePaintOnThread,
+      id,
+      aLayerObserverEpoch));
   }
 }
 
 void
 HangMonitorParent::ForcePaintOnThread(TabId aTabId, uint64_t aLayerObserverEpoch)
 {
   MOZ_RELEASE_ASSERT(IsOnThread());
 
@@ -957,52 +970,58 @@ HangMonitoredProcess::TerminateScript()
   if (mHangData.type() != HangData::TSlowScriptData) {
     return NS_ERROR_UNEXPECTED;
   }
 
   if (!mActor) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  ProcessHangMonitor::Get()->Dispatch(NewNonOwningRunnableMethod(mActor,
-                                                                 &HangMonitorParent::TerminateScript));
+  ProcessHangMonitor::Get()->Dispatch(
+    NewNonOwningRunnableMethod("HangMonitorParent::TerminateScript",
+                               mActor,
+                               &HangMonitorParent::TerminateScript));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HangMonitoredProcess::BeginStartingDebugger()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   if (mHangData.type() != HangData::TSlowScriptData) {
     return NS_ERROR_UNEXPECTED;
   }
 
   if (!mActor) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  ProcessHangMonitor::Get()->Dispatch(NewNonOwningRunnableMethod(mActor,
-                                                                 &HangMonitorParent::BeginStartingDebugger));
+  ProcessHangMonitor::Get()->Dispatch(
+    NewNonOwningRunnableMethod("HangMonitorParent::BeginStartingDebugger",
+                               mActor,
+                               &HangMonitorParent::BeginStartingDebugger));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HangMonitoredProcess::EndStartingDebugger()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   if (mHangData.type() != HangData::TSlowScriptData) {
     return NS_ERROR_UNEXPECTED;
   }
 
   if (!mActor) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  ProcessHangMonitor::Get()->Dispatch(NewNonOwningRunnableMethod(mActor,
-                                                                 &HangMonitorParent::EndStartingDebugger));
+  ProcessHangMonitor::Get()->Dispatch(
+    NewNonOwningRunnableMethod("HangMonitorParent::EndStartingDebugger",
+                               mActor,
+                               &HangMonitorParent::EndStartingDebugger));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HangMonitoredProcess::TerminatePlugin()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   if (mHangData.type() != HangData::TPluginHangData) {
@@ -1180,39 +1199,43 @@ CreateHangMonitorParent(ContentParent* a
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
   auto* parent = new HangMonitorParent(monitor);
 
   auto* process = new HangMonitoredProcess(parent, aContentParent);
   parent->SetProcess(process);
 
-  monitor->Dispatch(NewNonOwningRunnableMethod
-                    <Endpoint<PProcessHangMonitorParent>&&>(parent,
-                                                            &HangMonitorParent::Bind,
-                                                            Move(aEndpoint)));
+  monitor->Dispatch(
+    NewNonOwningRunnableMethod<Endpoint<PProcessHangMonitorParent>&&>(
+      "HangMonitorParent::Bind",
+      parent,
+      &HangMonitorParent::Bind,
+      Move(aEndpoint)));
 
   return parent;
 }
 
 void
 mozilla::CreateHangMonitorChild(Endpoint<PProcessHangMonitorChild>&& aEndpoint)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   JSContext* cx = danger::GetJSContext();
   JS_AddInterruptCallback(cx, InterruptCallback);
 
   ProcessHangMonitor* monitor = ProcessHangMonitor::GetOrCreate();
   auto* child = new HangMonitorChild(monitor);
 
-  monitor->Dispatch(NewNonOwningRunnableMethod
-                    <Endpoint<PProcessHangMonitorChild>&&>(child,
-                                                           &HangMonitorChild::Bind,
-                                                           Move(aEndpoint)));
+  monitor->Dispatch(
+    NewNonOwningRunnableMethod<Endpoint<PProcessHangMonitorChild>&&>(
+      "HangMonitorChild::Bind",
+      child,
+      &HangMonitorChild::Bind,
+      Move(aEndpoint)));
 }
 
 void
 ProcessHangMonitor::Dispatch(already_AddRefed<nsIRunnable> aRunnable)
 {
   mThread->Dispatch(Move(aRunnable), nsIEventTarget::NS_DISPATCH_NORMAL);
 }
 
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2773,18 +2773,23 @@ TabParent::GetHasBeforeUnload(bool* aRes
 class LayerTreeUpdateRunnable final
   : public mozilla::Runnable
 {
   uint64_t mLayersId;
   uint64_t mEpoch;
   bool mActive;
 
 public:
-  explicit LayerTreeUpdateRunnable(uint64_t aLayersId, uint64_t aEpoch, bool aActive)
-    : mLayersId(aLayersId), mEpoch(aEpoch), mActive(aActive)
+  explicit LayerTreeUpdateRunnable(uint64_t aLayersId,
+                                   uint64_t aEpoch,
+                                   bool aActive)
+    : Runnable("dom::LayerTreeUpdateRunnable")
+    , mLayersId(aLayersId)
+    , mEpoch(aEpoch)
+    , mActive(aActive)
   {
     MOZ_ASSERT(!NS_IsMainThread());
   }
 
 private:
   NS_IMETHOD Run() override {
     MOZ_ASSERT(NS_IsMainThread());
     if (RefPtr<TabParent> tabParent = TabParent::GetTabParentFromLayersId(mLayersId)) {
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -658,17 +658,18 @@ nsJSChannel::AsyncOpen(nsIStreamListener
 
         // We're returning success from asyncOpen2(), but we didn't open a
         // stream channel.  We'll have to notify ourselves, but make sure to do
         // it asynchronously.
         method = &nsJSChannel::NotifyListener;
         name = "nsJSChannel::NotifyListener";
     }
 
-    nsresult rv = NS_DispatchToCurrentThread(mozilla::NewRunnableMethod(name, this, method));
+    nsresult rv = NS_DispatchToCurrentThread(
+      mozilla::NewRunnableMethod(name, this, method));
 
     if (NS_FAILED(rv)) {
         loadGroup->RemoveRequest(this, nullptr, rv);
         mIsActive = false;
         CleanupStrongRefs();
     }
     return rv;
 }
--- a/dom/locales/en-US/chrome/accessibility/mac/accessible.properties
+++ b/dom/locales/en-US/chrome/accessibility/mac/accessible.properties
@@ -35,16 +35,19 @@ navigation =    navigation
 complementary = complementary
 content =       content
 main    =       main
 # The (spoken) role description for various WAI-ARIA roles
 alert       =      alert
 alertDialog =      alert dialog
 article     =      article
 document    =      document
+# The (spoken) role description for the WAI-ARIA heading role
+# https://w3c.github.io/aria/core-aam/core-aam.html#role-map-heading
+heading     =      heading
 log         =      log
 marquee     =      marquee
 math        =      math
 note        =      note
 region      =      region
 status      =      application status
 timer       =      timer
 tooltip     =      tooltip
--- a/dom/media/Benchmark.cpp
+++ b/dom/media/Benchmark.cpp
@@ -112,18 +112,18 @@ Benchmark::~Benchmark()
 
 RefPtr<Benchmark::BenchmarkPromise>
 Benchmark::Run()
 {
   MOZ_ASSERT(OnThread());
 
   RefPtr<BenchmarkPromise> p = mPromise.Ensure(__func__);
   RefPtr<Benchmark> self = this;
-  mPlaybackState.Dispatch(
-    NS_NewRunnableFunction([self]() { self->mPlaybackState.DemuxSamples(); }));
+  mPlaybackState.Dispatch(NS_NewRunnableFunction(
+    "Benchmark::Run", [self]() { self->mPlaybackState.DemuxSamples(); }));
   return p;
 }
 
 void
 Benchmark::ReturnResult(uint32_t aDecodeFps)
 {
   MOZ_ASSERT(OnThread());
 
@@ -197,17 +197,18 @@ BenchmarkPlayback::DemuxNextSample()
   promise->Then(
     Thread(), __func__,
     [this, ref](RefPtr<MediaTrackDemuxer::SamplesHolder> aHolder) {
       mSamples.AppendElements(Move(aHolder->mSamples));
       if (ref->mParameters.mStopAtFrame
           && mSamples.Length() == (size_t)ref->mParameters.mStopAtFrame.ref()) {
         InitDecoder(Move(*mTrackDemuxer->GetInfo()));
       } else {
-        Dispatch(NS_NewRunnableFunction([this, ref]() { DemuxNextSample(); }));
+        Dispatch(NS_NewRunnableFunction("BenchmarkPlayback::DemuxNextSample",
+                                        [this, ref]() { DemuxNextSample(); }));
       }
     },
     [this, ref](const MediaResult& aError) {
       switch (aError.Code()) {
         case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
           InitDecoder(Move(*mTrackDemuxer->GetInfo()));
           break;
         default:
@@ -292,19 +293,20 @@ BenchmarkPlayback::Output(const MediaDat
   int32_t frames = mFrameCount - ref->mParameters.mStartupFrame;
   TimeDuration elapsedTime = now - mDecodeStartTime.refOr(now);
   if (!mFinished
       && (((frames == ref->mParameters.mFramesToMeasure) && frames > 0)
           || elapsedTime >= ref->mParameters.mTimeout
           || mDrained)) {
     uint32_t decodeFps = frames / elapsedTime.ToSeconds();
     MainThreadShutdown();
-    ref->Dispatch(NS_NewRunnableFunction([ref, decodeFps]() {
-      ref->ReturnResult(decodeFps);
-    }));
+    ref->Dispatch(
+      NS_NewRunnableFunction("BenchmarkPlayback::Output", [ref, decodeFps]() {
+        ref->ReturnResult(decodeFps);
+      }));
   }
 }
 
 void
 BenchmarkPlayback::InputExhausted()
 {
   MOZ_ASSERT(OnThread());
   if (mFinished || mSampleIndex >= mSamples.Length()) {
--- a/dom/media/CanvasCaptureMediaStream.cpp
+++ b/dom/media/CanvasCaptureMediaStream.cpp
@@ -139,17 +139,21 @@ public:
     if (mFPS == 0.0) {
       return;
     }
 
     mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     if (!mTimer) {
       return;
     }
-    mTimer->InitWithFuncCallback(&TimerTick, this, int(1000 / mFPS), nsITimer::TYPE_REPEATING_SLACK);
+    mTimer->InitWithNamedFuncCallback(&TimerTick,
+                                      this,
+                                      int(1000 / mFPS),
+                                      nsITimer::TYPE_REPEATING_SLACK,
+                                      "dom::TimerDriver::TimerDriver");
   }
 
   static void TimerTick(nsITimer* aTimer, void* aClosure)
   {
     MOZ_ASSERT(aClosure);
     TimerDriver* driver = static_cast<TimerDriver*>(aClosure);
 
     driver->RequestFrameCapture();
--- a/dom/media/ChannelMediaDecoder.cpp
+++ b/dom/media/ChannelMediaDecoder.cpp
@@ -94,17 +94,19 @@ ChannelMediaDecoder::ResourceCallback::N
   mTimer->InitWithFuncCallback(
     TimerCallback, this, sDelay, nsITimer::TYPE_ONE_SHOT);
 }
 
 void
 ChannelMediaDecoder::ResourceCallback::NotifyDataEnded(nsresult aStatus)
 {
   RefPtr<ResourceCallback> self = this;
-  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=]() {
+  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+    "ChannelMediaDecoder::ResourceCallback::NotifyDataEnded",
+    [=]() {
     if (!self->mDecoder) {
       return;
     }
     self->mDecoder->NotifyDownloadEnded(aStatus);
     if (NS_SUCCEEDED(aStatus)) {
       MediaDecoderOwner* owner = self->GetMediaOwner();
       MOZ_ASSERT(owner);
       owner->DownloadSuspended();
@@ -136,17 +138,19 @@ ChannelMediaDecoder::ResourceCallback::N
   }
 }
 
 void
 ChannelMediaDecoder::ResourceCallback::NotifyBytesConsumed(int64_t aBytes,
                                                            int64_t aOffset)
 {
   RefPtr<ResourceCallback> self = this;
-  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=]() {
+  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+    "ChannelMediaDecoder::ResourceCallback::NotifyBytesConsumed",
+    [=]() {
     if (self->mDecoder) {
       self->mDecoder->NotifyBytesConsumed(aBytes, aOffset);
     }
   });
   mAbstractMainThread->Dispatch(r.forget());
 }
 
 ChannelMediaDecoder::ChannelMediaDecoder(MediaDecoderInit& aInit)
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -420,17 +420,18 @@ Maybe<uint32_t> GetCubebMSGLatencyInFram
 void InitLibrary()
 {
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_VOLUME_SCALE);
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_LATENCY_MSG);
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_BACKEND);
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_LOG_LEVEL);
 #ifndef MOZ_WIDGET_ANDROID
-  NS_DispatchToMainThread(NS_NewRunnableFunction(&InitBrandName));
+  NS_DispatchToMainThread(
+    NS_NewRunnableFunction("CubebUtils::InitLibrary", &InitBrandName));
 #endif
 }
 
 void ShutdownLibrary()
 {
   Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
   Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_BACKEND);
   Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
--- a/dom/media/DOMMediaStream.cpp
+++ b/dom/media/DOMMediaStream.cpp
@@ -183,17 +183,20 @@ public:
       nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
       nsIPrincipal* principal = doc ? doc->NodePrincipal() : nullptr;
       source = new BasicTrackSource(principal);
     }
 
     RefPtr<MediaStreamTrack> newTrack =
       mStream->CreateDOMTrack(aTrackID, aType, source);
     NS_DispatchToMainThread(NewRunnableMethod<RefPtr<MediaStreamTrack>>(
-        mStream, &DOMMediaStream::AddTrackInternal, newTrack));
+      "DOMMediaStream::AddTrackInternal",
+      mStream,
+      &DOMMediaStream::AddTrackInternal,
+      newTrack));
   }
 
   void DoNotifyTrackEnded(MediaStream* aInputStream, TrackID aInputTrackID,
                           TrackID aTrackID)
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (!mStream) {
@@ -201,39 +204,53 @@ public:
     }
 
     RefPtr<MediaStreamTrack> track =
       mStream->FindOwnedDOMTrack(aInputStream, aInputTrackID, aTrackID);
     NS_ASSERTION(track, "Owned MediaStreamTracks must be known by the DOMMediaStream");
     if (track) {
       LOG(LogLevel::Debug, ("DOMMediaStream %p MediaStreamTrack %p ended at the source. Marking it ended.",
                             mStream, track.get()));
-      NS_DispatchToMainThread(NewRunnableMethod(
-        track, &MediaStreamTrack::OverrideEnded));
+      NS_DispatchToMainThread(
+        NewRunnableMethod("dom::MediaStreamTrack::OverrideEnded",
+                          track,
+                          &MediaStreamTrack::OverrideEnded));
     }
   }
 
   void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
                                 StreamTime aTrackOffset, TrackEventCommand aTrackEvents,
                                 const MediaSegment& aQueuedMedia,
                                 MediaStream* aInputStream,
                                 TrackID aInputTrackID) override
   {
     if (aTrackEvents & TrackEventCommand::TRACK_EVENT_CREATED) {
       aGraph->DispatchToMainThreadAfterStreamStateUpdate(
         mAbstractMainThread,
-        NewRunnableMethod<TrackID, MediaSegment::Type, RefPtr<MediaStream>, TrackID>(
-          this, &OwnedStreamListener::DoNotifyTrackCreated,
-          aID, aQueuedMedia.GetType(), aInputStream, aInputTrackID));
+        NewRunnableMethod<TrackID,
+                          MediaSegment::Type,
+                          RefPtr<MediaStream>,
+                          TrackID>(
+          "DOMMediaStream::OwnedStreamListener::DoNotifyTrackCreated",
+          this,
+          &OwnedStreamListener::DoNotifyTrackCreated,
+          aID,
+          aQueuedMedia.GetType(),
+          aInputStream,
+          aInputTrackID));
     } else if (aTrackEvents & TrackEventCommand::TRACK_EVENT_ENDED) {
       aGraph->DispatchToMainThreadAfterStreamStateUpdate(
         mAbstractMainThread,
         NewRunnableMethod<RefPtr<MediaStream>, TrackID, TrackID>(
-          this, &OwnedStreamListener::DoNotifyTrackEnded,
-          aInputStream, aInputTrackID, aID));
+          "DOMMediaStream::OwnedStreamListener::DoNotifyTrackEnded",
+          this,
+          &OwnedStreamListener::DoNotifyTrackEnded,
+          aInputStream,
+          aInputTrackID,
+          aID));
     }
   }
 
 private:
   // These fields may only be accessed on the main thread
   DOMMediaStream* mStream;
 
   const RefPtr<AbstractThread> mAbstractMainThread;
@@ -264,48 +281,57 @@ public:
     if (!mStream) {
       return;
     }
 
     // The owned stream listener adds its tracks after another main thread
     // dispatch. We have to do the same to notify of created tracks to stay
     // in sync. (Or NotifyTracksCreated is called before tracks are added).
     NS_DispatchToMainThread(
-        NewRunnableMethod(mStream, &DOMMediaStream::NotifyTracksCreated));
+      NewRunnableMethod("DOMMediaStream::NotifyTracksCreated",
+                        mStream,
+                        &DOMMediaStream::NotifyTracksCreated));
   }
 
   void DoNotifyFinished()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     if (!mStream) {
       return;
     }
 
-    NS_DispatchToMainThread(NewRunnableMethod(
-      mStream, &DOMMediaStream::NotifyFinished));
+    NS_DispatchToMainThread(NewRunnableMethod("DOMMediaStream::NotifyFinished",
+                                              mStream,
+                                              &DOMMediaStream::NotifyFinished));
   }
 
   // The methods below are called on the MediaStreamGraph thread.
 
   void NotifyFinishedTrackCreation(MediaStreamGraph* aGraph) override
   {
     aGraph->DispatchToMainThreadAfterStreamStateUpdate(
       mAbstractMainThread,
-      NewRunnableMethod(this, &PlaybackStreamListener::DoNotifyFinishedTrackCreation));
+      NewRunnableMethod(
+        "DOMMediaStream::PlaybackStreamListener::DoNotifyFinishedTrackCreation",
+        this,
+        &PlaybackStreamListener::DoNotifyFinishedTrackCreation));
   }
 
 
   void NotifyEvent(MediaStreamGraph* aGraph,
                    MediaStreamGraphEvent event) override
   {
     if (event == MediaStreamGraphEvent::EVENT_FINISHED) {
       aGraph->DispatchToMainThreadAfterStreamStateUpdate(
         mAbstractMainThread,
-        NewRunnableMethod(this, &PlaybackStreamListener::DoNotifyFinished));
+        NewRunnableMethod(
+          "DOMMediaStream::PlaybackStreamListener::DoNotifyFinished",
+          this,
+          &PlaybackStreamListener::DoNotifyFinished));
     }
   }
 
 private:
   // These fields may only be accessed on the main thread
   DOMMediaStream* mStream;
 
   const RefPtr<AbstractThread> mAbstractMainThread;
@@ -406,17 +432,17 @@ NS_INTERFACE_MAP_END_INHERITING(DOMMedia
 DOMMediaStream::DOMMediaStream(nsPIDOMWindowInner* aWindow,
                                MediaStreamTrackSourceGetter* aTrackSourceGetter)
   : mLogicalStreamStartTime(0), mWindow(aWindow),
     mInputStream(nullptr), mOwnedStream(nullptr), mPlaybackStream(nullptr),
     mTracksPendingRemoval(0), mTrackSourceGetter(aTrackSourceGetter),
     mPlaybackTrackListener(MakeAndAddRef<PlaybackTrackListener>(this)),
     mTracksCreated(false), mNotifiedOfMediaStreamGraphShutdown(false),
     mActive(false), mSetInactiveOnFinish(false),
-    mAbstractMainThread(aWindow->GetDocGroup()->AbstractMainThreadFor(TaskCategory::Other))
+    mAbstractMainThread(aWindow ? aWindow->GetDocGroup()->AbstractMainThreadFor(TaskCategory::Other) : nullptr)
 {
   nsresult rv;
   nsCOMPtr<nsIUUIDGenerator> uuidgen =
     do_GetService("@mozilla.org/uuid-generator;1", &rv);
 
   if (NS_SUCCEEDED(rv) && uuidgen) {
     nsID uuid;
     memset(&uuid, 0, sizeof(uuid));
@@ -850,32 +876,35 @@ void
 DOMMediaStream::SetInactiveOnFinish()
 {
   mSetInactiveOnFinish = true;
 }
 
 void
 DOMMediaStream::InitSourceStream(MediaStreamGraph* aGraph)
 {
+  MOZ_ASSERT(mAbstractMainThread);
   InitInputStreamCommon(aGraph->CreateSourceStream(mAbstractMainThread), aGraph);
   InitOwnedStreamCommon(aGraph);
   InitPlaybackStreamCommon(aGraph);
 }
 
 void
 DOMMediaStream::InitTrackUnionStream(MediaStreamGraph* aGraph)
 {
+  MOZ_ASSERT(mAbstractMainThread);
   InitInputStreamCommon(aGraph->CreateTrackUnionStream(mAbstractMainThread), aGraph);
   InitOwnedStreamCommon(aGraph);
   InitPlaybackStreamCommon(aGraph);
 }
 
 void
 DOMMediaStream::InitAudioCaptureStream(nsIPrincipal* aPrincipal, MediaStreamGraph* aGraph)
 {
+  MOZ_ASSERT(mAbstractMainThread);
   const TrackID AUDIO_TRACK = 1;
 
   RefPtr<BasicTrackSource> audioCaptureSource =
     new BasicTrackSource(aPrincipal, MediaSourceEnum::AudioCapture);
 
   AudioCaptureStream* audioCaptureStream =
     static_cast<AudioCaptureStream*>(aGraph->CreateAudioCaptureStream(AUDIO_TRACK, mAbstractMainThread));
   InitInputStreamCommon(audioCaptureStream, aGraph);
@@ -896,16 +925,17 @@ DOMMediaStream::InitInputStreamCommon(Me
 
   mInputStream = aStream;
   mInputStream->RegisterUser();
 }
 
 void
 DOMMediaStream::InitOwnedStreamCommon(MediaStreamGraph* aGraph)
 {
+  MOZ_ASSERT(mAbstractMainThread);
   MOZ_ASSERT(!mPlaybackStream, "Owned stream must be initialized before playback stream");
 
   mOwnedStream = aGraph->CreateTrackUnionStream(mAbstractMainThread);
   mOwnedStream->SetAutofinish(true);
   mOwnedStream->RegisterUser();
   if (mInputStream) {
     mOwnedPort = mOwnedStream->AllocateInputPort(mInputStream);
   }
@@ -913,16 +943,17 @@ DOMMediaStream::InitOwnedStreamCommon(Me
   // Setup track listeners
   mOwnedListener = new OwnedStreamListener(this);
   mOwnedStream->AddListener(mOwnedListener);
 }
 
 void
 DOMMediaStream::InitPlaybackStreamCommon(MediaStreamGraph* aGraph)
 {
+  MOZ_ASSERT(mAbstractMainThread);
   mPlaybackStream = aGraph->CreateTrackUnionStream(mAbstractMainThread);
   mPlaybackStream->SetAutofinish(true);
   mPlaybackStream->RegisterUser();
   if (mOwnedStream) {
     mPlaybackPort = mPlaybackStream->AllocateInputPort(mOwnedStream);
   }
 
   mPlaybackListener = new PlaybackStreamListener(this);
--- a/dom/media/EncodedBufferCache.cpp
+++ b/dom/media/EncodedBufferCache.cpp
@@ -45,17 +45,19 @@ EncodedBufferCache::AppendBuffer(nsTArra
         // resulting file descriptor from the parent process, we notify the monitor
         // and unblock the current thread and continue.
         typedef dom::ContentChild::AnonymousTemporaryFileCallback
           AnonymousTemporaryFileCallback;
         bool done = false;
         Monitor monitor("EncodeBufferCache::AppendBuffer");
         RefPtr<dom::ContentChild> cc = dom::ContentChild::GetSingleton();
         nsCOMPtr<nsIRunnable> runnable =
-          NewRunnableMethod<AnonymousTemporaryFileCallback>(cc,
+          NewRunnableMethod<AnonymousTemporaryFileCallback>(
+            "dom::ContentChild::AsyncOpenAnonymousTemporaryFile",
+            cc,
             &dom::ContentChild::AsyncOpenAnonymousTemporaryFile,
             [&](PRFileDesc* aFile) {
               rv = aFile ? NS_OK : NS_ERROR_FAILURE;
               tempFD = aFile;
               MonitorAutoLock lock(monitor);
               done = true;
               lock.Notify();
             });
--- a/dom/media/FileBlockCache.cpp
+++ b/dom/media/FileBlockCache.cpp
@@ -90,25 +90,28 @@ FileBlockCache::Init()
                                   nullptr,
                                   SharedThreadPool::kStackSize);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (XRE_IsParentProcess()) {
     RefPtr<FileBlockCache> self = this;
-    rv = mThread->Dispatch(NS_NewRunnableFunction([self] {
-      PRFileDesc* fd = nullptr;
-      nsresult rv = NS_OpenAnonymousTemporaryFile(&fd);
-      if (NS_SUCCEEDED(rv)) {
-        self->SetCacheFile(fd);
-      } else {
-        self->Close();
-      }
-    }), NS_DISPATCH_NORMAL);
+    rv = mThread->Dispatch(
+      NS_NewRunnableFunction("FileBlockCache::Init",
+                             [self] {
+                               PRFileDesc* fd = nullptr;
+                               nsresult rv = NS_OpenAnonymousTemporaryFile(&fd);
+                               if (NS_SUCCEEDED(rv)) {
+                                 self->SetCacheFile(fd);
+                               } else {
+                                 self->Close();
+                               }
+                             }),
+      NS_DISPATCH_NORMAL);
   } else {
     // We must request a temporary file descriptor from the parent process.
     RefPtr<FileBlockCache> self = this;
     rv = dom::ContentChild::GetSingleton()->AsyncOpenAnonymousTemporaryFile(
       [self](PRFileDesc* aFD) { self->SetCacheFile(aFD); });
   }
 
   if (NS_FAILED(rv)) {
@@ -152,29 +155,38 @@ FileBlockCache::Close()
     MutexAutoLock lock(mFileMutex);
     fd = mFD;
     mFD = nullptr;
   }
 
   // Let the thread close the FD, and then trigger its own shutdown.
   // Note that mThread is now empty, so no other task will be posted there.
   // Also mThread and mFD are empty and therefore can be reused immediately.
-  nsresult rv = thread->Dispatch(NS_NewRunnableFunction([thread, fd] {
-    if (fd) {
-      CloseFD(fd);
-    }
-    // We must shut down the thread in another runnable. This is called
-    // while we're shutting down the media cache, and nsIThread::Shutdown()
-    // can cause events to run before it completes, which could end up
-    // opening more streams, while the media cache is shutting down and
-    // releasing memory etc!
-    nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(thread);
-    SystemGroup::Dispatch(
-      "ShutdownThreadEvent", TaskCategory::Other, event.forget());
-  }), NS_DISPATCH_NORMAL);
+  nsresult rv = thread->Dispatch(
+    NS_NewRunnableFunction("FileBlockCache::Close",
+                           [thread, fd] {
+                             if (fd) {
+                               CloseFD(fd);
+                             }
+                             // We must shut down the thread in another
+                             // runnable. This is called
+                             // while we're shutting down the media cache, and
+                             // nsIThread::Shutdown()
+                             // can cause events to run before it completes,
+                             // which could end up
+                             // opening more streams, while the media cache is
+                             // shutting down and
+                             // releasing memory etc!
+                             nsCOMPtr<nsIRunnable> event =
+                               new ShutdownThreadEvent(thread);
+                             SystemGroup::Dispatch("ShutdownThreadEvent",
+                                                   TaskCategory::Other,
+                                                   event.forget());
+                           }),
+    NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS_VOID(rv);
 }
 
 template<typename Container, typename Value>
 bool
 ContainerContains(const Container& aContainer, const Value& value)
 {
   return std::find(aContainer.begin(), aContainer.end(), value)
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -136,18 +136,20 @@ void GraphDriver::SetPreviousDriver(Grap
 }
 
 ThreadedDriver::ThreadedDriver(MediaStreamGraphImpl* aGraphImpl)
   : GraphDriver(aGraphImpl)
 { }
 
 class MediaStreamGraphShutdownThreadRunnable : public Runnable {
 public:
-  explicit MediaStreamGraphShutdownThreadRunnable(already_AddRefed<nsIThread> aThread)
-    : mThread(aThread)
+  explicit MediaStreamGraphShutdownThreadRunnable(
+    already_AddRefed<nsIThread> aThread)
+    : Runnable("MediaStreamGraphShutdownThreadRunnable")
+    , mThread(aThread)
   {
   }
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(mThread);
 
     mThread->Shutdown();
@@ -168,17 +170,18 @@ ThreadedDriver::~ThreadedDriver()
         new MediaStreamGraphShutdownThreadRunnable(mThread.forget());
       NS_DispatchToMainThread(event);
     }
   }
 }
 class MediaStreamGraphInitThreadRunnable : public Runnable {
 public:
   explicit MediaStreamGraphInitThreadRunnable(ThreadedDriver* aDriver)
-    : mDriver(aDriver)
+    : Runnable("MediaStreamGraphInitThreadRunnable")
+    , mDriver(aDriver)
   {
   }
   NS_IMETHOD Run() override
   {
     LOG(LogLevel::Debug,
         ("Starting a new system driver for graph %p", mDriver->mGraphImpl));
 
     GraphDriver* previousDriver = nullptr;
@@ -462,20 +465,22 @@ OfflineClockDriver::WaitForNextIteration
 }
 
 void
 OfflineClockDriver::WakeUp()
 {
   MOZ_ASSERT(false, "An offline graph should not have to wake up.");
 }
 
-AsyncCubebTask::AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation aOperation)
-  : mDriver(aDriver),
-    mOperation(aOperation),
-    mShutdownGrip(aDriver->GraphImpl())
+AsyncCubebTask::AsyncCubebTask(AudioCallbackDriver* aDriver,
+                               AsyncCubebOperation aOperation)
+  : Runnable("AsyncCubebTask")
+  , mDriver(aDriver)
+  , mOperation(aOperation)
+  , mShutdownGrip(aDriver->GraphImpl())
 {
   NS_WARNING_ASSERTION(mDriver->mAudioStream || aOperation == INIT,
                        "No audio stream!");
 }
 
 AsyncCubebTask::~AsyncCubebTask()
 {
 }
@@ -487,19 +492,20 @@ AsyncCubebTask::EnsureThread()
   if (!sThreadPool) {
     nsCOMPtr<nsIThreadPool> threadPool =
       SharedThreadPool::Get(NS_LITERAL_CSTRING("CubebOperation"), 1);
     sThreadPool = threadPool;
     // Need to null this out before xpcom-shutdown-threads Observers run
     // since we don't know the order that the shutdown-threads observers
     // will run.  ClearOnShutdown guarantees it runs first.
     if (!NS_IsMainThread()) {
-      NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
-            ClearOnShutdown(&sThreadPool, ShutdownPhase::ShutdownThreads);
-      }));
+      NS_DispatchToMainThread(
+        NS_NewRunnableFunction("AsyncCubebTask::EnsureThread", []() -> void {
+          ClearOnShutdown(&sThreadPool, ShutdownPhase::ShutdownThreads);
+        }));
     } else {
       ClearOnShutdown(&sThreadPool, ShutdownPhase::ShutdownThreads);
     }
 
     const uint32_t kIdleThreadTimeoutMs = 2000;
 
     nsresult rv = sThreadPool->SetIdleThreadTimeout(PR_MillisecondsToInterval(kIdleThreadTimeoutMs));
     if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/dom/media/Latency.cpp
+++ b/dom/media/Latency.cpp
@@ -42,28 +42,34 @@ GetLatencyLog()
 {
   static LazyLogModule sLog("MediaLatency");
   return sLog;
 }
 
 class LogEvent : public Runnable
 {
 public:
-  LogEvent(AsyncLatencyLogger::LatencyLogIndex aIndex, uint64_t aID, int64_t aValue,
-           TimeStamp aTimeStamp) :
-    mIndex(aIndex),
-    mID(aID),
-    mValue(aValue),
-    mTimeStamp(aTimeStamp)
+  LogEvent(AsyncLatencyLogger::LatencyLogIndex aIndex,
+           uint64_t aID,
+           int64_t aValue,
+           TimeStamp aTimeStamp)
+    : mozilla::Runnable("LogEvent")
+    , mIndex(aIndex)
+    , mID(aID)
+    , mValue(aValue)
+    , mTimeStamp(aTimeStamp)
   {}
-  LogEvent(AsyncLatencyLogger::LatencyLogIndex aIndex, uint64_t aID, int64_t aValue) :
-    mIndex(aIndex),
-    mID(aID),
-    mValue(aValue),
-    mTimeStamp(TimeStamp())
+  LogEvent(AsyncLatencyLogger::LatencyLogIndex aIndex,
+           uint64_t aID,
+           int64_t aValue)
+    : mozilla::Runnable("LogEvent")
+    , mIndex(aIndex)
+    , mID(aID)
+    , mValue(aValue)
+    , mTimeStamp(TimeStamp())
   {}
   ~LogEvent() {}
 
   NS_IMETHOD Run() override {
     AsyncLatencyLogger::Get(true)->WriteLog(mIndex, mID, mValue, mTimeStamp);
     return NS_OK;
   }
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -137,18 +137,16 @@ MediaDecoder::InitStatics()
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter)
 
 NS_IMPL_ISUPPORTS0(MediaDecoder)
 
-
-
 void
 MediaDecoder::NotifyOwnerActivityChanged(bool aIsDocumentVisible,
                                          Visibility aElementVisibility,
                                          bool aIsElementInTree)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
   SetElementVisibility(aIsDocumentVisible, aElementVisibility, aIsElementInTree);
@@ -333,20 +331,21 @@ MediaDecoder::Shutdown()
     mDecoderStateMachine->BeginShutdown()
       ->Then(mAbstractMainThread, __func__, this,
              &MediaDecoder::FinishShutdown,
              &MediaDecoder::FinishShutdown);
   } else {
     // Ensure we always unregister asynchronously in order not to disrupt
     // the hashtable iterating in MediaShutdownManager::Shutdown().
     RefPtr<MediaDecoder> self = this;
-    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () {
-      self->mVideoFrameContainer = nullptr;
-      MediaShutdownManager::Instance().Unregister(self);
-    });
+    nsCOMPtr<nsIRunnable> r =
+      NS_NewRunnableFunction("MediaDecoder::Shutdown", [self]() {
+        self->mVideoFrameContainer = nullptr;
+        MediaShutdownManager::Instance().Unregister(self);
+      });
     mAbstractMainThread->Dispatch(r.forget());
   }
 
   // Force any outstanding seek and byterange requests to complete
   // to prevent shutdown from deadlocking.
   if (mResource) {
     mResource->Close();
   }
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -89,17 +89,20 @@ MediaDecoderReader::MediaDecoderReader(A
 nsresult
 MediaDecoderReader::Init()
 {
   if (mDecoder && mDecoder->DataArrivedEvent()) {
     mDataArrivedListener = mDecoder->DataArrivedEvent()->Connect(
       mTaskQueue, this, &MediaDecoderReader::NotifyDataArrived);
   }
   // Dispatch initialization that needs to happen on that task queue.
-  mTaskQueue->Dispatch(NewRunnableMethod(this, &MediaDecoderReader::InitializationTask));
+  mTaskQueue->Dispatch(
+    NewRunnableMethod("MediaDecoderReader::InitializationTask",
+                      this,
+                      &MediaDecoderReader::InitializationTask));
   return InitInternal();
 }
 
 void
 MediaDecoderReader::InitializationTask()
 {
   if (!mDecoder) {
     return;
@@ -241,17 +244,18 @@ MediaDecoderReader::AsyncReadMetadata()
   return MetadataPromise::CreateAndResolve(Move(metadata), __func__);
 }
 
 class ReRequestVideoWithSkipTask : public Runnable
 {
 public:
   ReRequestVideoWithSkipTask(MediaDecoderReader* aReader,
                              const media::TimeUnit& aTimeThreshold)
-    : mReader(aReader)
+    : Runnable("ReRequestVideoWithSkipTask")
+    , mReader(aReader)
     , mTimeThreshold(aTimeThreshold)
   {
   }
 
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(mReader->OnTaskQueue());
 
@@ -267,17 +271,18 @@ private:
   RefPtr<MediaDecoderReader> mReader;
   const media::TimeUnit mTimeThreshold;
 };
 
 class ReRequestAudioTask : public Runnable
 {
 public:
   explicit ReRequestAudioTask(MediaDecoderReader* aReader)
-    : mReader(aReader)
+    : Runnable("ReRequestAudioTask")
+    , mReader(aReader)
   {
   }
 
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(mReader->OnTaskQueue());
 
     // Make sure ResetDecode hasn't been called in the mean time.
--- a/dom/media/MediaDecoderReaderWrapper.cpp
+++ b/dom/media/MediaDecoderReaderWrapper.cpp
@@ -106,26 +106,29 @@ MediaDecoderReaderWrapper::WaitForData(M
                      &MediaDecoderReader::WaitForData, aType);
 }
 
 void
 MediaDecoderReaderWrapper::ReleaseResources()
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   nsCOMPtr<nsIRunnable> r =
-    NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseResources);
+    NewRunnableMethod("MediaDecoderReader::ReleaseResources",
+                      mReader,
+                      &MediaDecoderReader::ReleaseResources);
   mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 void
 MediaDecoderReaderWrapper::ResetDecode(TrackSet aTracks)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   nsCOMPtr<nsIRunnable> r =
-    NewRunnableMethod<TrackSet>(mReader,
+    NewRunnableMethod<TrackSet>("MediaDecoderReader::ResetDecode",
+                                mReader,
                                 &MediaDecoderReader::ResetDecode,
                                 aTracks);
   mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 RefPtr<ShutdownPromise>
 MediaDecoderReaderWrapper::Shutdown()
 {
@@ -156,14 +159,16 @@ MediaDecoderReaderWrapper::OnMetadataNot
   return MetadataPromise::CreateAndReject(aError, __func__);
 }
 
 void
 MediaDecoderReaderWrapper::SetVideoBlankDecode(bool aIsBlankDecode)
 {
   MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn());
   nsCOMPtr<nsIRunnable> r =
-    NewRunnableMethod<bool>(mReader, &MediaDecoderReader::SetVideoNullDecode,
+    NewRunnableMethod<bool>("MediaDecoderReader::SetVideoNullDecode",
+                            mReader,
+                            &MediaDecoderReader::SetVideoNullDecode,
                             aIsBlankDecode);
   mReader->OwnerThread()->Dispatch(r.forget());
 }
 
 } // namespace mozilla
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1658,17 +1658,19 @@ private:
       RequestVideoData();
     }
   }
 
   class AysncNextFrameSeekTask : public Runnable
   {
   public:
     explicit AysncNextFrameSeekTask(NextFrameSeekingState* aStateObject)
-      : mStateObj(aStateObject)
+      : Runnable("MediaDecoderStateMachine::NextFrameSeekingState::"
+                 "AysncNextFrameSeekTask")
+      , mStateObj(aStateObject)
     {
     }
 
     void Cancel() { mStateObj = nullptr; }
 
     NS_IMETHOD Run() override
     {
       if (mStateObj) {
@@ -2888,17 +2890,20 @@ void MediaDecoderStateMachine::SetMediaN
 }
 
 nsresult MediaDecoderStateMachine::Init(MediaDecoder* aDecoder)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Dispatch initialization that needs to happen on that task queue.
   nsCOMPtr<nsIRunnable> r = NewRunnableMethod<RefPtr<MediaDecoder>>(
-    this, &MediaDecoderStateMachine::InitializationTask, aDecoder);
+    "MediaDecoderStateMachine::InitializationTask",
+    this,
+    &MediaDecoderStateMachine::InitializationTask,
+    aDecoder);
   mTaskQueue->DispatchStateChange(r.forget());
 
   mAudioQueueListener = AudioQueue().PopEvent().Connect(
     mTaskQueue, this, &MediaDecoderStateMachine::OnAudioPopped);
   mVideoQueueListener = VideoQueue().PopEvent().Connect(
     mTaskQueue, this, &MediaDecoderStateMachine::OnVideoPopped);
 
   mMetadataManager.Connect(mReader->TimedMetadataEvent(), OwnerThread());
@@ -3095,20 +3100,21 @@ void MediaDecoderStateMachine::PlayState
     mMinimizePreroll = false;
   }
 
   mStateObj->HandlePlayStateChanged(mPlayState);
 }
 
 void MediaDecoderStateMachine::SetVideoDecodeMode(VideoDecodeMode aMode)
 {
-  nsCOMPtr<nsIRunnable> r =
-    NewRunnableMethod<VideoDecodeMode>(this,
-                                       &MediaDecoderStateMachine::SetVideoDecodeModeInternal,
-                                       aMode);
+  nsCOMPtr<nsIRunnable> r = NewRunnableMethod<VideoDecodeMode>(
+    "MediaDecoderStateMachine::SetVideoDecodeModeInternal",
+    this,
+    &MediaDecoderStateMachine::SetVideoDecodeModeInternal,
+    aMode);
   OwnerThread()->DispatchStateChange(r.forget());
 }
 
 void MediaDecoderStateMachine::SetVideoDecodeModeInternal(VideoDecodeMode aMode)
 {
   MOZ_ASSERT(OnTaskQueue());
   LOG("VideoDecodeModeChanged: VideoDecodeMode=(%s->%s), mVideoDecodeSuspended=%c",
       mVideoDecodeMode == VideoDecodeMode::Normal ? "Normal" : "Suspend",
@@ -3647,17 +3653,19 @@ MediaDecoderStateMachine::ScheduleStateM
 {
   MOZ_ASSERT(OnTaskQueue());
   if (mDispatchedStateMachine) {
     return;
   }
   mDispatchedStateMachine = true;
 
   OwnerThread()->Dispatch(
-    NewRunnableMethod(this, &MediaDecoderStateMachine::RunStateMachine));
+    NewRunnableMethod("MediaDecoderStateMachine::RunStateMachine",
+                      this,
+                      &MediaDecoderStateMachine::RunStateMachine));
 }
 
 void
 MediaDecoderStateMachine::ScheduleStateMachineIn(const TimeUnit& aTime)
 {
   MOZ_ASSERT(OnTaskQueue()); // mDelayedScheduler.Ensure() may Disconnect()
                              // the promise, which must happen on the state
                              // machine task queue.
@@ -3882,41 +3890,50 @@ MediaDecoderStateMachine::GetDebugInfo()
 }
 
 RefPtr<MediaDecoder::DebugInfoPromise>
 MediaDecoderStateMachine::RequestDebugInfo()
 {
   using PromiseType = MediaDecoder::DebugInfoPromise;
   RefPtr<PromiseType::Private> p = new PromiseType::Private(__func__);
   RefPtr<MediaDecoderStateMachine> self = this;
-  OwnerThread()->Dispatch(NS_NewRunnableFunction([self, p] () {
-    p->Resolve(self->GetDebugInfo(), __func__);
-  }), AbstractThread::AssertDispatchSuccess, AbstractThread::TailDispatch);
+  OwnerThread()->Dispatch(
+    NS_NewRunnableFunction(
+      "MediaDecoderStateMachine::RequestDebugInfo",
+      [self, p]() { p->Resolve(self->GetDebugInfo(), __func__); }),
+    AbstractThread::AssertDispatchSuccess,
+    AbstractThread::TailDispatch);
   return p.forget();
 }
 
 void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
                                                bool aFinishWhenEnded)
 {
   MOZ_ASSERT(NS_IsMainThread());
   LOG("AddOutputStream aStream=%p!", aStream);
   mOutputStreamManager->Add(aStream, aFinishWhenEnded);
-  nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>(
-    this, &MediaDecoderStateMachine::SetAudioCaptured, true);
+  nsCOMPtr<nsIRunnable> r =
+    NewRunnableMethod<bool>("MediaDecoderStateMachine::SetAudioCaptured",
+                            this,
+                            &MediaDecoderStateMachine::SetAudioCaptured,
+                            true);
   OwnerThread()->Dispatch(r.forget());
 }
 
 void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
   LOG("RemoveOutputStream=%p!", aStream);
   mOutputStreamManager->Remove(aStream);
   if (mOutputStreamManager->IsEmpty()) {
-    nsCOMPtr<nsIRunnable> r = NewRunnableMethod<bool>(
-      this, &MediaDecoderStateMachine::SetAudioCaptured, false);
+    nsCOMPtr<nsIRunnable> r =
+      NewRunnableMethod<bool>("MediaDecoderStateMachine::SetAudioCaptured",
+                              this,
+                              &MediaDecoderStateMachine::SetAudioCaptured,
+                              false);
     OwnerThread()->Dispatch(r.forget());
   }
 }
 
 size_t
 MediaDecoderStateMachine::SizeOfVideoQueue() const
 {
   return mReader->SizeOfVideoQueueInBytes();
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -179,31 +179,37 @@ public:
   // Remove an output stream added with AddOutputStream.
   void RemoveOutputStream(MediaStream* aStream);
 
   // Seeks to the decoder to aTarget asynchronously.
   RefPtr<MediaDecoder::SeekPromise> InvokeSeek(const SeekTarget& aTarget);
 
   void DispatchSetPlaybackRate(double aPlaybackRate)
   {
-    OwnerThread()->DispatchStateChange(NewRunnableMethod<double>(
-      this, &MediaDecoderStateMachine::SetPlaybackRate, aPlaybackRate));
+    OwnerThread()->DispatchStateChange(
+      NewRunnableMethod<double>("MediaDecoderStateMachine::SetPlaybackRate",
+                                this,
+                                &MediaDecoderStateMachine::SetPlaybackRate,
+                                aPlaybackRate));
   }
 
   RefPtr<ShutdownPromise> BeginShutdown();
 
   // Set the media fragment end time.
   void DispatchSetFragmentEndTime(const media::TimeUnit& aEndTime)
   {
     RefPtr<MediaDecoderStateMachine> self = this;
-    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aEndTime] () {
-      // A negative number means we don't have a fragment end time at all.
-      self->mFragmentEndTime = aEndTime >= media::TimeUnit::Zero()
-        ? aEndTime : media::TimeUnit::Invalid();
-    });
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+      "MediaDecoderStateMachine::DispatchSetFragmentEndTime",
+      [self, aEndTime]() {
+        // A negative number means we don't have a fragment end time at all.
+        self->mFragmentEndTime = aEndTime >= media::TimeUnit::Zero()
+                                   ? aEndTime
+                                   : media::TimeUnit::Invalid();
+      });
     OwnerThread()->Dispatch(r.forget());
   }
 
   // Drop reference to mResource. Only called during shutdown dance.
   void BreakCycles() {
     MOZ_ASSERT(NS_IsMainThread());
     mResource = nullptr;
   }
--- a/dom/media/MediaEventSource.h
+++ b/dom/media/MediaEventSource.h
@@ -130,19 +130,23 @@ template <typename... As>
 class Listener : public RevocableToken
 {
 public:
   template <typename... Ts>
   void Dispatch(Ts&&... aEvents)
   {
     if (CanTakeArgs()) {
       DispatchTask(NewRunnableMethod<typename Decay<Ts>::Type&&...>(
-        this, &Listener::ApplyWithArgs, Forward<Ts>(aEvents)...));
+        "detail::Listener::ApplyWithArgs",
+        this,
+        &Listener::ApplyWithArgs,
+        Forward<Ts>(aEvents)...));
     } else {
-      DispatchTask(NewRunnableMethod(this, &Listener::ApplyWithNoArgs));
+      DispatchTask(NewRunnableMethod(
+        "detail::Listener::ApplyWithNoArgs", this, &Listener::ApplyWithNoArgs));
     }
   }
 
 protected:
   virtual ~Listener()
   {
     MOZ_ASSERT(IsRevoked(), "Must disconnect the listener.");
   }
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -116,20 +116,19 @@ private:
 
 GlobalAllocPolicy::GlobalAllocPolicy()
   : mMonitor("DecoderAllocPolicy::mMonitor")
   , mDecoderLimit(MediaPrefs::MediaDecoderLimit())
 {
   SystemGroup::Dispatch(
     "GlobalAllocPolicy::ClearOnShutdown",
     TaskCategory::Other,
-    NS_NewRunnableFunction([this] () {
+    NS_NewRunnableFunction("GlobalAllocPolicy::GlobalAllocPolicy", [this]() {
       ClearOnShutdown(this, ShutdownPhase::ShutdownThreads);
-    })
-  );
+    }));
 }
 
 GlobalAllocPolicy::~GlobalAllocPolicy()
 {
   while (!mPromises.empty()) {
     RefPtr<PromisePrivate> p = mPromises.front().forget();
     mPromises.pop();
     p->Reject(true, __func__);
@@ -922,19 +921,19 @@ public:
   bool GetSamplesMayBlock() const override
   {
     return mGetSamplesMayBlock;
   }
 
   void Reset() override
   {
     RefPtr<Wrapper> self = this;
-    mTaskQueue->Dispatch(NS_NewRunnableFunction([self]() {
-      self->mTrackDemuxer->Reset();
-    }));
+    mTaskQueue->Dispatch(
+      NS_NewRunnableFunction("MediaFormatReader::DemuxerProxy::Wrapper::Reset",
+                             [self]() { self->mTrackDemuxer->Reset(); }));
   }
 
   nsresult GetNextRandomAccessPoint(TimeUnit* aTime) override
   {
     MutexAutoLock lock(mMutex);
     if (NS_SUCCEEDED(mNextRandomAccessPointResult)) {
       *aTime = mNextRandomAccessPoint;
     }
@@ -982,16 +981,17 @@ private:
   TimeUnit mNextRandomAccessPoint;
   TimeIntervals mBuffered;
   friend class DemuxerProxy;
 
   ~Wrapper()
   {
     RefPtr<MediaTrackDemuxer> trackDemuxer = mTrackDemuxer.forget();
     mTaskQueue->Dispatch(NS_NewRunnableFunction(
+      "MediaFormatReader::DemuxerProxy::Wrapper::~Wrapper",
       [trackDemuxer]() { trackDemuxer->BreakCycles(); }));
   }
 
   void UpdateRandomAccessPoint()
   {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     if (!mTrackDemuxer) {
       // Detached.
@@ -1264,17 +1264,18 @@ MediaFormatReader::InitInternal()
 }
 
 class DispatchKeyNeededEvent : public Runnable
 {
 public:
   DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
                          nsTArray<uint8_t>& aInitData,
                          const nsString& aInitDataType)
-    : mDecoder(aDecoder)
+    : Runnable("DispatchKeyNeededEvent")
+    , mDecoder(aDecoder)
     , mInitData(aInitData)
     , mInitDataType(aInitDataType)
   {
   }
   NS_IMETHOD Run() override
   {
     // Note: Null check the owner, as the decoder could have been shutdown
     // since this event was dispatched.
@@ -1291,20 +1292,21 @@ private:
   nsString mInitDataType;
 };
 
 void
 MediaFormatReader::SetCDMProxy(CDMProxy* aProxy)
 {
   RefPtr<CDMProxy> proxy = aProxy;
   RefPtr<MediaFormatReader> self = this;
-  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
-    MOZ_ASSERT(self->OnTaskQueue());
-    self->mCDMProxy = proxy;
-  });
+  nsCOMPtr<nsIRunnable> r =
+    NS_NewRunnableFunction("MediaFormatReader::SetCDMProxy", [=]() {
+      MOZ_ASSERT(self->OnTaskQueue());
+      self->mCDMProxy = proxy;
+    });
   OwnerThread()->Dispatch(r.forget());
 }
 
 bool
 MediaFormatReader::IsWaitingOnCDMResource()
 {
   MOZ_ASSERT(OnTaskQueue());
   return IsEncrypted() && !mCDMProxy;
@@ -1463,17 +1465,17 @@ MediaFormatReader::OnDemuxerInitDone(con
     if (HasVideo()) {
       RequestDemuxSamples(TrackInfo::kVideoTrack);
     }
   }
 
   if (aResult != NS_OK && mDecoder) {
     RefPtr<AbstractMediaDecoder> decoder = mDecoder;
     mDecoder->AbstractMainThread()->Dispatch(NS_NewRunnableFunction(
-      [decoder, aResult] () {
+      "MediaFormatReader::OnDemuxerInitDone", [decoder, aResult]() {
         if (decoder->GetOwner()) {
           decoder->GetOwner()->DecodeWarning(aResult);
         }
       }));
   }
 
   MaybeResolveMetadataPromise();
 }
@@ -1850,18 +1852,18 @@ MediaFormatReader::ScheduleUpdate(TrackT
     return;
   }
   auto& decoder = GetDecoderData(aTrack);
   if (decoder.mUpdateScheduled) {
     return;
   }
   LOGV("SchedulingUpdate(%s)", TrackTypeToStr(aTrack));
   decoder.mUpdateScheduled = true;
-  RefPtr<nsIRunnable> task(
-    NewRunnableMethod<TrackType>(this, &MediaFormatReader::Update, aTrack));
+  RefPtr<nsIRunnable> task(NewRunnableMethod<TrackType>(
+    "MediaFormatReader::Update", this, &MediaFormatReader::Update, aTrack));
   OwnerThread()->Dispatch(task.forget());
 }
 
 bool
 MediaFormatReader::UpdateReceivedNewData(TrackType aTrack)
 {
   MOZ_ASSERT(OnTaskQueue());
   auto& decoder = GetDecoderData(aTrack);
@@ -2714,18 +2716,18 @@ MediaFormatReader::SetSeekTarget(const S
 
 void
 MediaFormatReader::ScheduleSeek()
 {
   if (mSeekScheduled) {
     return;
   }
   mSeekScheduled = true;
-  OwnerThread()->Dispatch(
-    NewRunnableMethod(this, &MediaFormatReader::AttemptSeek));
+  OwnerThread()->Dispatch(NewRunnableMethod(
+    "MediaFormatReader::AttemptSeek", this, &MediaFormatReader::AttemptSeek));
 }
 
 void
 MediaFormatReader::AttemptSeek()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   mSeekScheduled = false;
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -646,22 +646,22 @@ private:
  * Send an error back to content.
  * Do this only on the main thread. The onSuccess callback is also passed here
  * so it can be released correctly.
  */
 template<class SuccessCallbackType>
 class ErrorCallbackRunnable : public Runnable
 {
 public:
-  ErrorCallbackRunnable(
-    nsCOMPtr<SuccessCallbackType>&& aOnSuccess,
-    nsCOMPtr<nsIDOMGetUserMediaErrorCallback>&& aOnFailure,
-    MediaMgrError& aError,
-    uint64_t aWindowID)
-    : mError(&aError)
+  ErrorCallbackRunnable(nsCOMPtr<SuccessCallbackType>&& aOnSuccess,
+                        nsCOMPtr<nsIDOMGetUserMediaErrorCallback>&& aOnFailure,
+                        MediaMgrError& aError,
+                        uint64_t aWindowID)
+    : Runnable("ErrorCallbackRunnable")
+    , mError(&aError)
     , mWindowID(aWindowID)
     , mManager(MediaManager::GetInstance())
   {
     mOnSuccess.swap(aOnSuccess);
     mOnFailure.swap(aOnFailure);
   }
 
   NS_IMETHOD
@@ -986,17 +986,18 @@ public:
     uint64_t aWindowID,
     GetUserMediaWindowListener* aWindowListener,
     SourceListener* aSourceListener,
     const ipc::PrincipalInfo& aPrincipalInfo,
     const MediaStreamConstraints& aConstraints,
     AudioDevice* aAudioDevice,
     VideoDevice* aVideoDevice,
     PeerIdentity* aPeerIdentity)
-    : mConstraints(aConstraints)
+    : Runnable("GetUserMediaStreamRunnable")
+    , mConstraints(aConstraints)
     , mAudioDevice(aAudioDevice)
     , mVideoDevice(aVideoDevice)
     , mWindowID(aWindowID)
     , mWindowListener(aWindowListener)
     , mSourceListener(aSourceListener)
     , mPrincipalInfo(aPrincipalInfo)
     , mPeerIdentity(aPeerIdentity)
     , mManager(MediaManager::GetInstance())
@@ -1285,17 +1286,18 @@ public:
       // callbacks in the TracksAvailableCallback.
       NS_DispatchToMainThread(do_AddRef(
         new GetUserMediaNotificationEvent(
           GetUserMediaNotificationEvent::STARTING,
           domStream.forget(),
           callback.forget(),
           self->mWindowID,
           self->mOnFailure.forget())));
-      NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
+      NS_DispatchToMainThread(NS_NewRunnableFunction("MediaManager::SendPendingGUMRequest",
+                                                     []() -> void {
         RefPtr<MediaManager> manager = MediaManager::GetInstance();
         manager->SendPendingGUMRequest();
       }));
       return NS_OK;
     }));
 
     if (!IsPincipalInfoPrivate(mPrincipalInfo)) {
       // Call GetPrincipalKey again, this time w/persist = true, to promote
@@ -1442,22 +1444,25 @@ MediaManager::SelectSettings(
  */
 class GetUserMediaTask : public Runnable
 {
 public:
   GetUserMediaTask(
     const MediaStreamConstraints& aConstraints,
     already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aOnSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aOnFailure,
-    uint64_t aWindowID, GetUserMediaWindowListener *aWindowListener,
-    SourceListener *aSourceListener, MediaEnginePrefs &aPrefs,
+    uint64_t aWindowID,
+    GetUserMediaWindowListener* aWindowListener,
+    SourceListener* aSourceListener,
+    MediaEnginePrefs& aPrefs,
     const ipc::PrincipalInfo& aPrincipalInfo,
     bool aIsChrome,
     MediaManager::SourceSet* aSourceSet)
-    : mConstraints(aConstraints)
+    : Runnable("GetUserMediaTask")
+    , mConstraints(aConstraints)
     , mOnSuccess(aOnSuccess)
     , mOnFailure(aOnFailure)
     , mWindowID(aWindowID)
     , mWindowListener(aWindowListener)
     , mSourceListener(aSourceListener)
     , mPrefs(aPrefs)
     , mPrincipalInfo(aPrincipalInfo)
     , mIsChrome(aIsChrome)
@@ -1478,17 +1483,20 @@ public:
         Move(mOnSuccess), Move(mOnFailure), *error, mWindowID);
     // These should be empty now
     MOZ_ASSERT(!mOnSuccess);
     MOZ_ASSERT(!mOnFailure);
 
     NS_DispatchToMainThread(errorRunnable.forget());
     // Do after ErrorCallbackRunnable Run()s, as it checks active window list
     NS_DispatchToMainThread(NewRunnableMethod<RefPtr<SourceListener>>(
-      mWindowListener, &GetUserMediaWindowListener::Remove, mSourceListener));
+      "GetUserMediaWindowListener::Remove",
+      mWindowListener,
+      &GetUserMediaWindowListener::Remove,
+      mSourceListener));
   }
 
   NS_IMETHOD
   Run() override
   {
     MOZ_ASSERT(!NS_IsMainThread());
     MOZ_ASSERT(mOnSuccess);
     MOZ_ASSERT(mOnFailure);
@@ -1537,17 +1545,18 @@ public:
       if (badConstraint) {
         Fail(NS_LITERAL_STRING("OverconstrainedError"),
              NS_LITERAL_STRING(""),
              NS_ConvertUTF8toUTF16(badConstraint));
       } else {
         Fail(NS_LITERAL_STRING("NotReadableError"),
              NS_ConvertUTF8toUTF16(errorMsg));
       }
-      NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
+      NS_DispatchToMainThread(NS_NewRunnableFunction("MediaManager::SendPendingGUMRequest",
+                                                     []() -> void {
         RefPtr<MediaManager> manager = MediaManager::GetInstance();
         manager->SendPendingGUMRequest();
       }));
       return NS_OK;
     }
     PeerIdentity* peerIdentity = nullptr;
     if (!mConstraints.mPeerIdentity.IsEmpty()) {
       peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity);
@@ -1654,18 +1663,19 @@ private:
   RefPtr<MediaManager> mManager; // get ref to this when creating the runnable
 };
 
 #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK)
 class GetUserMediaRunnableWrapper : public Runnable
 {
 public:
   // This object must take ownership of task
-  GetUserMediaRunnableWrapper(GetUserMediaTask* task) :
-    mTask(task) {
+  GetUserMediaRunnableWrapper(GetUserMediaTask* task)
+    : Runnable("GetUserMediaRunnableWrapper")
+    , mTask(task) {
   }
 
   ~GetUserMediaRunnableWrapper() {
   }
 
   NS_IMETHOD Run() override {
     mTask->Run();
     return NS_OK;
@@ -2969,20 +2979,23 @@ MediaManager::Shutdown()
 #endif
 
   // Because mMediaThread is not an nsThread, we must dispatch to it so it can
   // clean up BackgroundChild. Continue stopping thread once this is done.
 
   class ShutdownTask : public Runnable
   {
   public:
-    ShutdownTask(MediaManager* aManager,
-                 already_AddRefed<Runnable> aReply)
-      : mManager(aManager)
-      , mReply(aReply) {}
+    ShutdownTask(MediaManager* aManager, already_AddRefed<Runnable> aReply)
+      : mozilla::Runnable("ShutdownTask")
+      , mManager(aManager)
+      , mReply(aReply)
+    {
+    }
+
   private:
     NS_IMETHOD
     Run() override
     {
       LOG(("MediaManager Thread Shutdown"));
       MOZ_ASSERT(MediaManager::IsInMediaThread());
       // Must shutdown backend on MediaManager thread, since that's where we started it from!
       {
@@ -3706,29 +3719,33 @@ SourceListener::NotifyEvent(MediaStreamG
       target = GetMainThreadEventTarget();
       if (NS_WARN_IF(!target)) {
         NS_ASSERTION(false, "Mainthread not available; running on current thread");
         // Ensure this really *was* MainThread (NS_GetCurrentThread won't work)
         MOZ_RELEASE_ASSERT(mMainThreadCheck == GetCurrentVirtualThread());
         NotifyFinished();
         return;
       }
-      target->Dispatch(NewRunnableMethod(this, &SourceListener::NotifyFinished),
+      target->Dispatch(NewRunnableMethod("SourceListener::NotifyFinished",
+                                         this,
+                                         &SourceListener::NotifyFinished),
                        NS_DISPATCH_NORMAL);
       break;
     case MediaStreamGraphEvent::EVENT_REMOVED:
       target = GetMainThreadEventTarget();
       if (NS_WARN_IF(!target)) {
         NS_ASSERTION(false, "Mainthread not available; running on current thread");
         // Ensure this really *was* MainThread (NS_GetCurrentThread won't work)
         MOZ_RELEASE_ASSERT(mMainThreadCheck == GetCurrentVirtualThread());
         NotifyRemoved();
         return;
       }
-      target->Dispatch(NewRunnableMethod(this, &SourceListener::NotifyRemoved),
+      target->Dispatch(NewRunnableMethod("SourceListener::NotifyRemoved",
+                                         this,
+                                         &SourceListener::NotifyRemoved),
                        NS_DISPATCH_NORMAL);
       break;
     case MediaStreamGraphEvent::EVENT_HAS_DIRECT_LISTENERS:
       NotifyDirectListeners(aGraph, true);
       break;
     case MediaStreamGraphEvent::EVENT_HAS_NO_DIRECT_LISTENERS:
       NotifyDirectListeners(aGraph, false);
       break;
@@ -3967,47 +3984,57 @@ GetUserMediaWindowListener::NotifySource
   // We wait until stable state before notifying chrome so chrome only does one
   // update if more tracks are stopped in this event loop.
 
   if (mChromeNotificationTaskPosted) {
     return;
   }
 
   nsCOMPtr<nsIRunnable> runnable =
-    NewRunnableMethod(this, &GetUserMediaWindowListener::NotifyChromeOfTrackStops);
+    NewRunnableMethod("GetUserMediaWindowListener::NotifyChromeOfTrackStops",
+                      this,
+                      &GetUserMediaWindowListener::NotifyChromeOfTrackStops);
   nsContentUtils::RunInStableState(runnable.forget());
   mChromeNotificationTaskPosted = true;
 }
 
 void
 GetUserMediaWindowListener::NotifyChromeOfTrackStops()
 {
   MOZ_ASSERT(mChromeNotificationTaskPosted);
   mChromeNotificationTaskPosted = false;
 
   NS_DispatchToMainThread(do_AddRef(new GetUserMediaNotificationEvent(
     GetUserMediaNotificationEvent::STOPPING, mWindowID)));
 }
 
 GetUserMediaNotificationEvent::GetUserMediaNotificationEvent(
-    GetUserMediaStatus aStatus,
-    uint64_t aWindowID)
-: mStatus(aStatus), mWindowID(aWindowID) {}
+  GetUserMediaStatus aStatus,
+  uint64_t aWindowID)
+  : Runnable("GetUserMediaNotificationEvent")
+  , mStatus(aStatus)
+  , mWindowID(aWindowID)
+{
+}
 
 GetUserMediaNotificationEvent::GetUserMediaNotificationEvent(
-    GetUserMediaStatus aStatus,
-    already_AddRefed<DOMMediaStream> aStream,
-    already_AddRefed<Refcountable<UniquePtr<OnTracksAvailableCallback>>> aOnTracksAvailableCallback,
-    uint64_t aWindowID,
-    already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
-: mStream(aStream),
-  mOnTracksAvailableCallback(aOnTracksAvailableCallback),
-  mStatus(aStatus),
-  mWindowID(aWindowID),
-  mOnFailure(aError) {}
+  GetUserMediaStatus aStatus,
+  already_AddRefed<DOMMediaStream> aStream,
+  already_AddRefed<Refcountable<UniquePtr<OnTracksAvailableCallback>>>
+    aOnTracksAvailableCallback,
+  uint64_t aWindowID,
+  already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
+  : Runnable("GetUserMediaNotificationEvent")
+  , mStream(aStream)
+  , mOnTracksAvailableCallback(aOnTracksAvailableCallback)
+  , mStatus(aStatus)
+  , mWindowID(aWindowID)
+  , mOnFailure(aError)
+{
+}
 GetUserMediaNotificationEvent::~GetUserMediaNotificationEvent()
 {
 }
 
 NS_IMETHODIMP
 GetUserMediaNotificationEvent::Run()
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -163,19 +163,23 @@ typedef enum {
   MEDIA_DIRECT_LISTENERS,
 } MediaOperation;
 
 class ReleaseMediaOperationResource : public Runnable
 {
 public:
   ReleaseMediaOperationResource(
     already_AddRefed<DOMMediaStream> aStream,
-    already_AddRefed<media::Refcountable<UniquePtr<OnTracksAvailableCallback>>> aOnTracksAvailableCallback):
-    mStream(aStream),
-    mOnTracksAvailableCallback(aOnTracksAvailableCallback) {}
+    already_AddRefed<media::Refcountable<UniquePtr<OnTracksAvailableCallback>>>
+      aOnTracksAvailableCallback)
+    : Runnable("ReleaseMediaOperationResource")
+    , mStream(aStream)
+    , mOnTracksAvailableCallback(aOnTracksAvailableCallback)
+  {
+  }
   NS_IMETHOD Run() override {return NS_OK;}
 private:
   RefPtr<DOMMediaStream> mStream;
   RefPtr<media::Refcountable<UniquePtr<OnTracksAvailableCallback>>> mOnTracksAvailableCallback;
 };
 
 typedef nsRefPtrHashtable<nsUint64HashKey, GetUserMediaWindowListener> WindowTable;
 
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -172,17 +172,18 @@ class MediaRecorder::Session: public nsI
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // Main thread task.
   // Create a blob event and send back to client.
   class PushBlobRunnable : public Runnable
   {
   public:
     explicit PushBlobRunnable(Session* aSession)
-      : mSession(aSession)
+      : Runnable("dom::MediaRecorder::Session::PushBlobRunnable")
+      , mSession(aSession)
     { }
 
     NS_IMETHOD Run() override
     {
       LOG(LogLevel::Debug, ("Session.PushBlobRunnable s=(%p)", mSession.get()));
       MOZ_ASSERT(NS_IsMainThread());
 
       RefPtr<MediaRecorder> recorder = mSession->mRecorder;
@@ -202,17 +203,18 @@ class MediaRecorder::Session: public nsI
     RefPtr<Session> mSession;
   };
 
   // Notify encoder error, run in main thread task. (Bug 1095381)
   class EncoderErrorNotifierRunnable : public Runnable
   {
   public:
     explicit EncoderErrorNotifierRunnable(Session* aSession)
-      : mSession(aSession)
+      : Runnable("dom::MediaRecorder::Session::EncoderErrorNotifierRunnable")
+      , mSession(aSession)
     { }
 
     NS_IMETHOD Run() override
     {
       LOG(LogLevel::Debug, ("Session.ErrorNotifyRunnable s=(%p)", mSession.get()));
       MOZ_ASSERT(NS_IsMainThread());
 
       RefPtr<MediaRecorder> recorder = mSession->mRecorder;
@@ -229,18 +231,19 @@ class MediaRecorder::Session: public nsI
   private:
     RefPtr<Session> mSession;
   };
 
   // Fire start event and set mimeType, run in main thread task.
   class DispatchStartEventRunnable : public Runnable
   {
   public:
-    DispatchStartEventRunnable(Session* aSession, const nsAString & aEventName)
-      : mSession(aSession)
+    DispatchStartEventRunnable(Session* aSession, const nsAString& aEventName)
+      : Runnable("dom::MediaRecorder::Session::DispatchStartEventRunnable")
+      , mSession(aSession)
       , mEventName(aEventName)
     { }
 
     NS_IMETHOD Run() override
     {
       LOG(LogLevel::Debug, ("Session.DispatchStartEventRunnable s=(%p)", mSession.get()));
       MOZ_ASSERT(NS_IsMainThread());
 
@@ -259,17 +262,20 @@ class MediaRecorder::Session: public nsI
   };
 
   // Record thread task and it run in Media Encoder thread.
   // Fetch encoded Audio/Video data from MediaEncoder.
   class ExtractRunnable : public Runnable
   {
   public:
     explicit ExtractRunnable(Session* aSession)
-      : mSession(aSession) {}
+      : Runnable("dom::MediaRecorder::Session::ExtractRunnable")
+      , mSession(aSession)
+    {
+    }
 
     ~ExtractRunnable()
     {}
 
     NS_IMETHOD Run() override
     {
       MOZ_ASSERT(mSession->mReadThread->EventTarget()->IsOnCurrentThread());
 
@@ -359,20 +365,26 @@ class MediaRecorder::Session: public nsI
     TrackRate mTrackRate;
   };
   // Main thread task.
   // To delete RecordingSession object.
   class DestroyRunnable : public Runnable
   {
   public:
     explicit DestroyRunnable(Session* aSession)
-      : mSession(aSession) {}
+      : Runnable("dom::MediaRecorder::Session::DestroyRunnable")
+      , mSession(aSession)
+    {
+    }
 
     explicit DestroyRunnable(already_AddRefed<Session> aSession)
-      : mSession(aSession) {}
+      : Runnable("dom::MediaRecorder::Session::DestroyRunnable")
+      , mSession(aSession)
+    {
+    }
 
     NS_IMETHOD Run() override
     {
       LOG(LogLevel::Debug, ("Session.DestroyRunnable session refcnt = (%d) stopIssued %d s=(%p)",
                          (int)mSession->mRefCnt, mSession->mStopIssued, mSession.get()));
       MOZ_ASSERT(NS_IsMainThread() && mSession);
       RefPtr<MediaRecorder> recorder = mSession->mRecorder;
       if (!recorder) {
@@ -794,18 +806,21 @@ private:
   void DoSessionEndTask(nsresult rv)
   {
     MOZ_ASSERT(NS_IsMainThread());
     CleanupStreams();
     NS_DispatchToMainThread(
       new DispatchStartEventRunnable(this, NS_LITERAL_STRING("start")));
 
     if (NS_FAILED(rv)) {
-      NS_DispatchToMainThread(NewRunnableMethod<nsresult>(mRecorder,
-                                                          &MediaRecorder::NotifyError, rv));
+      NS_DispatchToMainThread(
+        NewRunnableMethod<nsresult>("dom::MediaRecorder::NotifyError",
+                                    mRecorder,
+                                    &MediaRecorder::NotifyError,
+                                    rv));
     }
     if (NS_FAILED(NS_DispatchToMainThread(new EncoderErrorNotifierRunnable(this)))) {
       MOZ_ASSERT(false, "NS_DispatchToMainThread EncoderErrorNotifierRunnable failed");
     }
     if (rv != NS_ERROR_DOM_SECURITY_ERR) {
       // Don't push a blob if there was a security error.
       if (NS_FAILED(NS_DispatchToMainThread(new PushBlobRunnable(this)))) {
         MOZ_ASSERT(false, "NS_DispatchToMainThread PushBlobRunnable failed");
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -62,20 +62,21 @@ namespace mozilla {
 void
 MediaResource::Destroy()
 {
   // Ensures we only delete the MediaResource on the main thread.
   if (NS_IsMainThread()) {
     delete this;
     return;
   }
-  nsresult rv =
-    SystemGroup::Dispatch("MediaResource::Destroy",
-                          TaskCategory::Other,
-                          NewNonOwningRunnableMethod(this, &MediaResource::Destroy));
+  nsresult rv = SystemGroup::Dispatch(
+    "MediaResource::Destroy",
+    TaskCategory::Other,
+    NewNonOwningRunnableMethod(
+      "MediaResource::Destroy", this, &MediaResource::Destroy));
   MOZ_ALWAYS_SUCCEEDS(rv);
 }
 
 NS_IMPL_ADDREF(MediaResource)
 NS_IMPL_RELEASE_WITH_DESTROY(MediaResource, Destroy())
 NS_IMPL_QUERY_INTERFACE0(MediaResource)
 
 ChannelMediaResource::ChannelMediaResource(
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -3633,19 +3633,20 @@ void
 MediaStreamGraphImpl::CollectSizesForMemoryReport(
   already_AddRefed<nsIHandleReportCallback> aHandleReport,
   already_AddRefed<nsISupports> aHandlerData)
 {
   class FinishCollectRunnable final : public Runnable
   {
   public:
     explicit FinishCollectRunnable(
-               already_AddRefed<nsIHandleReportCallback> aHandleReport,
-               already_AddRefed<nsISupports> aHandlerData)
-      : mHandleReport(aHandleReport)
+      already_AddRefed<nsIHandleReportCallback> aHandleReport,
+      already_AddRefed<nsISupports> aHandlerData)
+      : mozilla::Runnable("FinishCollectRunnable")
+      , mHandleReport(aHandleReport)
       , mHandlerData(aHandlerData)
     {}
 
     NS_IMETHOD Run() override
     {
       MediaStreamGraphImpl::FinishCollectReports(mHandleReport, mHandlerData,
                                                  Move(mAudioStreamSizes));
       return NS_OK;
--- a/dom/media/MediaStreamTrack.cpp
+++ b/dom/media/MediaStreamTrack.cpp
@@ -109,17 +109,21 @@ public:
   }
 
   void NotifyPrincipalHandleChanged(MediaStreamGraph* aGraph,
                                     const PrincipalHandle& aNewPrincipalHandle) override
   {
     aGraph->DispatchToMainThreadAfterStreamStateUpdate(
       mAbstractMainThread,
       NewRunnableMethod<StoreCopyPassByConstLRef<PrincipalHandle>>(
-        this, &PrincipalHandleListener::DoNotifyPrincipalHandleChanged, aNewPrincipalHandle));
+        "dom::MediaStreamTrack::PrincipalHandleListener::"
+        "DoNotifyPrincipalHandleChanged",
+        this,
+        &PrincipalHandleListener::DoNotifyPrincipalHandleChanged,
+        aNewPrincipalHandle));
   }
 
 protected:
   // These fields may only be accessed on the main thread
   MediaStreamTrack* mTrack;
   const RefPtr<AbstractThread> mAbstractMainThread;
 };
 
--- a/dom/media/MediaTimer.cpp
+++ b/dom/media/MediaTimer.cpp
@@ -36,18 +36,20 @@ MediaTimer::MediaTimer()
 
 void
 MediaTimer::DispatchDestroy()
 {
   // Hold a strong reference to the thread so that it doesn't get deleted in
   // Destroy(), which may run completely before the stack if Dispatch() begins
   // to unwind.
   nsCOMPtr<nsIEventTarget> thread = mThread;
-  nsresult rv = thread->Dispatch(NewNonOwningRunnableMethod(this, &MediaTimer::Destroy),
-                                 NS_DISPATCH_NORMAL);
+  nsresult rv =
+    thread->Dispatch(NewNonOwningRunnableMethod(
+                       "MediaTimer::Destroy", this, &MediaTimer::Destroy),
+                     NS_DISPATCH_NORMAL);
   MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   (void) rv;
 }
 
 void
 MediaTimer::Destroy()
 {
   MOZ_ASSERT(OnMediaTimerThread());
@@ -91,18 +93,19 @@ void
 MediaTimer::ScheduleUpdate()
 {
   mMonitor.AssertCurrentThreadOwns();
   if (mUpdateScheduled) {
     return;
   }
   mUpdateScheduled = true;
 
-  nsresult rv = mThread->Dispatch(NewRunnableMethod(this, &MediaTimer::Update),
-                                  NS_DISPATCH_NORMAL);
+  nsresult rv = mThread->Dispatch(
+    NewRunnableMethod("MediaTimer::Update", this, &MediaTimer::Update),
+    NS_DISPATCH_NORMAL);
   MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
   (void) rv;
 }
 
 void
 MediaTimer::Update()
 {
   MonitorAutoLock mon(mMonitor);
--- a/dom/media/TextTrack.cpp
+++ b/dom/media/TextTrack.cpp
@@ -332,21 +332,21 @@ void
 TextTrack::DispatchAsyncTrustedEvent(const nsString& aEventName)
 {
   nsPIDOMWindowInner* win = GetOwner();
   if (!win) {
     return;
   }
   RefPtr<TextTrack> self = this;
   nsGlobalWindow::Cast(win)->Dispatch(
-    "TextTrack::DispatchAsyncTrustedEvent", TaskCategory::Other,
-    NS_NewRunnableFunction([self, aEventName]() {
-      self->DispatchTrustedEvent(aEventName);
-    })
-  );
+    "TextTrack::DispatchAsyncTrustedEvent",
+    TaskCategory::Other,
+    NS_NewRunnableFunction(
+      "dom::TextTrack::DispatchAsyncTrustedEvent",
+      [self, aEventName]() { self->DispatchTrustedEvent(aEventName); }));
 }
 
 bool
 TextTrack::IsLoaded()
 {
   if (mMode == TextTrackMode::Disabled) {
     return true;
   }
--- a/dom/media/TextTrackList.cpp
+++ b/dom/media/TextTrackList.cpp
@@ -136,17 +136,18 @@ TextTrackList::DidSeek()
     mTextTracks[i]->SetDirty();
   }
 }
 
 class TrackEventRunner : public Runnable
 {
 public:
   TrackEventRunner(TextTrackList* aList, nsIDOMEvent* aEvent)
-    : mList(aList)
+    : Runnable("dom::TrackEventRunner")
+    , mList(aList)
     , mEvent(aEvent)
   {}
 
   NS_IMETHOD Run() override
   {
     return mList->DispatchTrackEvent(mEvent);
   }
 
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -390,18 +390,18 @@ SimpleTimer::Create(nsIRunnable* aTask, 
   return t.forget();
 }
 
 void
 LogToBrowserConsole(const nsAString& aMsg)
 {
   if (!NS_IsMainThread()) {
     nsString msg(aMsg);
-    nsCOMPtr<nsIRunnable> task =
-      NS_NewRunnableFunction([msg]() { LogToBrowserConsole(msg); });
+    nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
+      "LogToBrowserConsole", [msg]() { LogToBrowserConsole(msg); });
     SystemGroup::Dispatch("LogToBrowserConsole", TaskCategory::Other, task.forget());
     return;
   }
   nsCOMPtr<nsIConsoleService> console(
     do_GetService("@mozilla.org/consoleservice;1"));
   if (!console) {
     NS_WARNING("Failed to log message to console.");
     return;
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -85,17 +85,21 @@ private:
 
   ReentrantMonitor* mReentrantMonitor;
 };
 
 // Shuts down a thread asynchronously.
 class ShutdownThreadEvent : public Runnable
 {
 public:
-  explicit ShutdownThreadEvent(nsIThread* aThread) : mThread(aThread) {}
+  explicit ShutdownThreadEvent(nsIThread* aThread)
+    : Runnable("ShutdownThreadEvent")
+    , mThread(aThread)
+  {
+  }
   ~ShutdownThreadEvent() {}
   NS_IMETHOD Run() override {
     mThread->Shutdown();
     mThread = nullptr;
     return NS_OK;
   }
 private:
   nsCOMPtr<nsIThread> mThread;
@@ -260,18 +264,21 @@ RefPtr<GenericPromise> InvokeUntil(Work 
 
   struct Helper {
     static void Iteration(const RefPtr<GenericPromise::Private>& aPromise, Work aLocalWork, Condition aLocalCondition) {
       if (!aLocalWork()) {
         aPromise->Reject(NS_ERROR_FAILURE, __func__);
       } else if (aLocalCondition()) {
         aPromise->Resolve(true, __func__);
       } else {
-        nsCOMPtr<nsIRunnable> r =
-          NS_NewRunnableFunction([aPromise, aLocalWork, aLocalCondition] () { Iteration(aPromise, aLocalWork, aLocalCondition); });
+        nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+          "InvokeUntil::Helper::Iteration",
+          [aPromise, aLocalWork, aLocalCondition]() {
+            Iteration(aPromise, aLocalWork, aLocalCondition);
+          });
         AbstractThread::GetCurrent()->Dispatch(r.forget());
       }
     }
   };
 
   Helper::Iteration(p, aWork, aCondition);
   return p.forget();
 }
--- a/dom/media/android/AndroidMediaPluginHost.cpp
+++ b/dom/media/android/AndroidMediaPluginHost.cpp
@@ -41,17 +41,17 @@ namespace mozilla {
 static char* GetResource(Decoder *aDecoder)
 {
   return static_cast<char*>(aDecoder->mResource);
 }
 
 class GetIntPrefEvent : public Runnable {
 public:
   GetIntPrefEvent(const char* aPref, int32_t* aResult)
-    : mPref(aPref), mResult(aResult) {}
+    : Runnable("GetIntPrefEvent"), mPref(aPref), mResult(aResult) {}
   NS_IMETHOD Run() override {
     return Preferences::GetInt(mPref, mResult);
   }
 private:
   const char* mPref;
   int32_t*    mResult;
 };
 
--- a/dom/media/android/AndroidMediaResourceServer.cpp
+++ b/dom/media/android/AndroidMediaResourceServer.cpp
@@ -119,17 +119,21 @@ private:
   // method ensures all the data is written by checking the number
   // of bytes returned from the output streams 'Write' method and
   // looping until done.
   nsresult WriteAll(char const* aBuffer, int32_t aBufferLength);
 
 public:
   ServeResourceEvent(nsIInputStream* aInput, nsIOutputStream* aOutput,
                      AndroidMediaResourceServer* aServer)
-    : mInput(aInput), mOutput(aOutput), mServer(aServer) {}
+    : Runnable("ServeResourceEvent")
+    , mInput(aInput)
+    , mOutput(aOutput)
+    , mServer(aServer)
+  {}
 
   // This method runs on the thread and exits when it has completed the
   // HTTP request.
   NS_IMETHOD Run();
 
   // Given the first line of an HTTP request, parse the URL requested and
   // return the MediaResource for that URL.
   already_AddRefed<MediaResource> GetMediaResource(nsCString const& aHTTPRequest);
@@ -383,18 +387,19 @@ ResourceSocketListener::OnSocketAccepted
 }
 
 NS_IMETHODIMP
 ResourceSocketListener::OnStopListening(nsIServerSocket* aServ, nsresult aStatus)
 {
   return NS_OK;
 }
 
-AndroidMediaResourceServer::AndroidMediaResourceServer() :
-  mMutex("AndroidMediaResourceServer")
+AndroidMediaResourceServer::AndroidMediaResourceServer()
+  : Runnable("AndroidMediaResourceServer")
+  , mMutex("AndroidMediaResourceServer")
 {
 }
 
 NS_IMETHODIMP
 AndroidMediaResourceServer::Run()
 {
   MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
   MutexAutoLock lock(mMutex);
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
+++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.cpp
@@ -64,17 +64,18 @@ MediaDrmCDMProxy::Init(PromiseId aPromis
     if (NS_FAILED(rv)) {
       RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR,
                     NS_LITERAL_CSTRING("Couldn't create CDM thread MediaDrmCDMProxy::Init"));
       return;
     }
   }
 
   mCDM = mozilla::MakeUnique<MediaDrmProxySupport>(mKeySystem);
-  nsCOMPtr<nsIRunnable> task(NewRunnableMethod<uint32_t>(this,
+  nsCOMPtr<nsIRunnable> task(NewRunnableMethod<uint32_t>("MediaDrmCDMProxy::md_Init",
+                                                         this,
                                                          &MediaDrmCDMProxy::md_Init,
                                                          aPromiseId));
   mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
 MediaDrmCDMProxy::CreateSession(uint32_t aCreateSessionToken,
                                 MediaKeySessionType aSessionType,
@@ -88,17 +89,18 @@ MediaDrmCDMProxy::CreateSession(uint32_t
   UniquePtr<CreateSessionData> data(new CreateSessionData());
   data->mSessionType = aSessionType;
   data->mCreateSessionToken = aCreateSessionToken;
   data->mPromiseId = aPromiseId;
   data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
   data->mInitData = Move(aInitData);
 
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<CreateSessionData>&&>(this,
+    NewRunnableMethod<UniquePtr<CreateSessionData>&&>("MediaDrmCDMProxy::md_CreateSession",
+                                                      this,
                                                       &MediaDrmCDMProxy::md_CreateSession,
                                                       Move(data)));
   mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
 MediaDrmCDMProxy::LoadSession(PromiseId aPromiseId,
                               dom::MediaKeySessionType aSessionType,
@@ -128,17 +130,18 @@ MediaDrmCDMProxy::UpdateSession(const ns
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   UniquePtr<UpdateSessionData> data(new UpdateSessionData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   data->mResponse = Move(aResponse);
 
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<UpdateSessionData>&&>(this,
+    NewRunnableMethod<UniquePtr<UpdateSessionData>&&>("MediaDrmCDMProxy::md_UpdateSession",
+                                                      this,
                                                       &MediaDrmCDMProxy::md_UpdateSession,
                                                       Move(data)));
   mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
 MediaDrmCDMProxy::CloseSession(const nsAString& aSessionId,
                              PromiseId aPromiseId)
@@ -147,17 +150,18 @@ MediaDrmCDMProxy::CloseSession(const nsA
   MOZ_ASSERT(mOwnerThread);
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   UniquePtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
 
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<SessionOpData>&&>(this,
+    NewRunnableMethod<UniquePtr<SessionOpData>&&>("MediaDrmCDMProxy::md_CloseSession",
+                                                  this,
                                                   &MediaDrmCDMProxy::md_CloseSession,
                                                   Move(data)));
   mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
 }
 
 void
 MediaDrmCDMProxy::RemoveSession(const nsAString& aSessionId,
                               PromiseId aPromiseId)
@@ -168,17 +172,18 @@ MediaDrmCDMProxy::RemoveSession(const ns
 }
 
 void
 MediaDrmCDMProxy::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mOwnerThread);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod(this, &MediaDrmCDMProxy::md_Shutdown));
+    NewRunnableMethod("MediaDrmCDMProxy::md_Shutdown",
+                      this, &MediaDrmCDMProxy::md_Shutdown));
 
   mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL);
   mOwnerThread->Shutdown();
   mOwnerThread = nullptr;
 }
 
 void
 MediaDrmCDMProxy::Terminated()
@@ -321,17 +326,18 @@ MediaDrmCDMProxy::ResolvePromise(Promise
   if (NS_IsMainThread()) {
     if (!mKeys.IsNull()) {
       mKeys->ResolvePromise(aId);
     } else {
       NS_WARNING("MediaDrmCDMProxy unable to resolve promise!");
     }
   } else {
     nsCOMPtr<nsIRunnable> task;
-    task = NewRunnableMethod<PromiseId>(this,
+    task = NewRunnableMethod<PromiseId>("MediaDrmCDMProxy::ResolvePromise",
+                                        this,
                                         &MediaDrmCDMProxy::ResolvePromise,
                                         aId);
     mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
   }
 }
 
 const nsString&
 MediaDrmCDMProxy::KeySystem() const
@@ -403,17 +409,18 @@ void
 MediaDrmCDMProxy::md_Init(uint32_t aPromiseId)
 {
   MOZ_ASSERT(IsOnOwnerThread());
   MOZ_ASSERT(mCDM);
 
   mCallback.reset(new MediaDrmCDMCallbackProxy(this));
   mCDM->Init(mCallback.get());
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<uint32_t>(this,
+    NewRunnableMethod<uint32_t>("MediaDrmCDMProxy::OnCDMCreated",
+                                this,
                                 &MediaDrmCDMProxy::OnCDMCreated,
                                 aPromiseId));
   mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 MediaDrmCDMProxy::md_CreateSession(UniquePtr<CreateSessionData>&& aData)
 {
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
+++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.h
@@ -146,17 +146,18 @@ private:
   };
 
   class RejectPromiseTask : public Runnable {
   public:
     RejectPromiseTask(MediaDrmCDMProxy* aProxy,
                       PromiseId aId,
                       nsresult aCode,
                       const nsCString& aReason)
-      : mProxy(aProxy)
+      : Runnable("RejectPromiseTask")
+      , mProxy(aProxy)
       , mId(aId)
       , mCode(aCode)
       , mReason(aReason)
     {
     }
     NS_IMETHOD Run() override {
       mProxy->RejectPromise(mId, mCode, mReason);
       return NS_OK;
--- a/dom/media/gmp/ChromiumCDMParent.cpp
+++ b/dom/media/gmp/ChromiumCDMParent.cpp
@@ -282,17 +282,18 @@ ChromiumCDMParent::RecvOnResolveNewSessi
   if (token.isNothing()) {
     RejectPromise(aPromiseId,
                   NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Lost session token for new session."));
     return IPC_OK();
   }
 
   RefPtr<Runnable> task =
-    NewRunnableMethod<uint32_t, nsString>(mProxy,
+    NewRunnableMethod<uint32_t, nsString>("ChromiumCDMProxy::OnSetSessionId",
+                                          mProxy,
                                           &ChromiumCDMProxy::OnSetSessionId,
                                           token.value(),
                                           NS_ConvertUTF8toUTF16(aSessionId));
   NS_DispatchToMainThread(task);
 
   ResolvePromise(aPromiseId);
 
   return IPC_OK();
@@ -307,16 +308,17 @@ ChromiumCDMParent::RecvResolveLoadSessio
           this,
           aPromiseId,
           aSuccessful);
   if (!mProxy || mIsShutdown) {
     return IPC_OK();
   }
 
   NS_DispatchToMainThread(NewRunnableMethod<uint32_t, bool>(
+    "ChromiumCDMProxy::OnResolveLoadSessionPromise",
     mProxy,
     &ChromiumCDMProxy::OnResolveLoadSessionPromise,
     aPromiseId,
     aSuccessful));
   return IPC_OK();
 }
 void
 ChromiumCDMParent::ResolvePromise(uint32_t aPromiseId)
@@ -324,18 +326,21 @@ ChromiumCDMParent::ResolvePromise(uint32
   GMP_LOG(
     "ChromiumCDMParent::ResolvePromise(this=%p, pid=%u)", this, aPromiseId);
 
   // Note: The MediaKeys rejects all pending DOM promises when it
   // initiates shutdown.
   if (!mProxy || mIsShutdown) {
     return;
   }
-  NS_DispatchToMainThread(NewRunnableMethod<uint32_t>(
-    mProxy, &ChromiumCDMProxy::ResolvePromise, aPromiseId));
+  NS_DispatchToMainThread(
+    NewRunnableMethod<uint32_t>("ChromiumCDMProxy::ResolvePromise",
+                                mProxy,
+                                &ChromiumCDMProxy::ResolvePromise,
+                                aPromiseId));
 }
 
 ipc::IPCResult
 ChromiumCDMParent::RecvOnResolvePromise(const uint32_t& aPromiseId)
 {
   ResolvePromise(aPromiseId);
   return IPC_OK();
 }
@@ -375,16 +380,17 @@ ChromiumCDMParent::RejectPromise(uint32_
   GMP_LOG(
     "ChromiumCDMParent::RejectPromise(this=%p, pid=%u)", this, aPromiseId);
   // Note: The MediaKeys rejects all pending DOM promises when it
   // initiates shutdown.
   if (!mProxy || mIsShutdown) {
     return;
   }
   NS_DispatchToMainThread(NewRunnableMethod<uint32_t, nsresult, nsCString>(
+    "ChromiumCDMProxy::RejectPromise",
     mProxy,
     &ChromiumCDMProxy::RejectPromise,
     aPromiseId,
     aError,
     aErrorMessage));
 }
 
 ipc::IPCResult
@@ -423,19 +429,20 @@ ChromiumCDMParent::RecvOnSessionMessage(
   if (!mProxy || mIsShutdown) {
     return IPC_OK();
   }
   RefPtr<CDMProxy> proxy = mProxy;
   nsString sid = NS_ConvertUTF8toUTF16(aSessionId);
   dom::MediaKeyMessageType messageType = ToDOMMessageType(aMessageType);
   nsTArray<uint8_t> msg(Move(aMessage));
   NS_DispatchToMainThread(
-    NS_NewRunnableFunction([proxy, sid, messageType, msg]() mutable {
-      proxy->OnSessionMessage(sid, messageType, msg);
-    }));
+    NS_NewRunnableFunction("gmp::ChromiumCDMParent::RecvOnSessionMessage",
+                           [proxy, sid, messageType, msg]() mutable {
+                             proxy->OnSessionMessage(sid, messageType, msg);
+                           }));
   return IPC_OK();
 }
 
 static dom::MediaKeyStatus
 ToDOMMediaKeyStatus(uint32_t aStatus)
 {
   switch (static_cast<cdm::KeyStatus>(aStatus)) {
     case cdm::kUsable:
@@ -474,17 +481,18 @@ ChromiumCDMParent::RecvOnSessionKeysChan
         caps.SetKeyStatus(aKeysInfo[i].mKeyId(),
                           NS_ConvertUTF8toUTF16(aSessionId),
                           dom::Optional<dom::MediaKeyStatus>(
                             ToDOMMediaKeyStatus(aKeysInfo[i].mStatus())));
     }
   }
   if (keyStatusesChange) {
     NS_DispatchToMainThread(
-      NewRunnableMethod<nsString>(mProxy,
+      NewRunnableMethod<nsString>("ChromiumCDMProxy::OnKeyStatusesChange",
+                                  mProxy,
                                   &ChromiumCDMProxy::OnKeyStatusesChange,
                                   NS_ConvertUTF8toUTF16(aSessionId)));
   }
   return IPC_OK();
 }
 
 ipc::IPCResult
 ChromiumCDMParent::RecvOnExpirationChange(const nsCString& aSessionId,
@@ -492,32 +500,34 @@ ChromiumCDMParent::RecvOnExpirationChang
 {
   GMP_LOG("ChromiumCDMParent::RecvOnExpirationChange(this=%p) time=%lf",
           this,
           aSecondsSinceEpoch);
   if (!mProxy || mIsShutdown) {
     return IPC_OK();
   }
   NS_DispatchToMainThread(NewRunnableMethod<nsString, UnixTime>(
+    "ChromiumCDMProxy::OnExpirationChange",
     mProxy,
     &ChromiumCDMProxy::OnExpirationChange,
     NS_ConvertUTF8toUTF16(aSessionId),
     GMPTimestamp(aSecondsSinceEpoch * 1000)));
   return IPC_OK();
 }
 
 ipc::IPCResult
 ChromiumCDMParent::RecvOnSessionClosed(const nsCString& aSessionId)
 {
   GMP_LOG("ChromiumCDMParent::RecvOnSessionClosed(this=%p)", this);
   if (!mProxy || mIsShutdown) {
     return IPC_OK();
   }
   NS_DispatchToMainThread(
-    NewRunnableMethod<nsString>(mProxy,
+    NewRunnableMethod<nsString>("ChromiumCDMProxy::OnSessionClosed",
+                                mProxy,
                                 &ChromiumCDMProxy::OnSessionClosed,
                                 NS_ConvertUTF8toUTF16(aSessionId)));
   return IPC_OK();
 }
 
 ipc::IPCResult
 ChromiumCDMParent::RecvOnLegacySessionError(const nsCString& aSessionId,
                                             const uint32_t& aError,
@@ -525,16 +535,17 @@ ChromiumCDMParent::RecvOnLegacySessionEr
                                             const nsCString& aMessage)
 {
   GMP_LOG("ChromiumCDMParent::RecvOnLegacySessionError(this=%p)", this);
   if (!mProxy || mIsShutdown) {
     return IPC_OK();
   }
   NS_DispatchToMainThread(
     NewRunnableMethod<nsString, nsresult, uint32_t, nsString>(
+      "ChromiumCDMProxy::OnSessionError",
       mProxy,
       &ChromiumCDMProxy::OnSessionError,
       NS_ConvertUTF8toUTF16(aSessionId),
       ToNsresult(aError),
       aSystemCode,
       NS_ConvertUTF8toUTF16(aMessage)));
   return IPC_OK();
 }
@@ -889,18 +900,18 @@ ChromiumCDMParent::ActorDestroy(ActorDes
   MOZ_ASSERT(mIsShutdown);
   RefPtr<ChromiumCDMParent> kungFuDeathGrip(this);
   if (mContentParent) {
     mContentParent->ChromiumCDMDestroyed(this);
     mContentParent = nullptr;
   }
   bool abnormalShutdown = (aWhy == AbnormalShutdown);
   if (abnormalShutdown && proxy) {
-    RefPtr<Runnable> task =
-      NewRunnableMethod(proxy, &ChromiumCDMProxy::Terminated);
+    RefPtr<Runnable> task = NewRunnableMethod(
+      "ChromiumCDMProxy::Terminated", proxy, &ChromiumCDMProxy::Terminated);
     NS_DispatchToMainThread(task);
   }
   MaybeDisconnect(abnormalShutdown);
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 ChromiumCDMParent::InitializeVideoDecoder(
   const gmp::CDMVideoDecoderConfig& aConfig,
@@ -1121,18 +1132,18 @@ ChromiumCDMParent::Shutdown()
   mIsShutdown = true;
 
   // If we're shutting down due to the plugin shutting down due to application
   // shutdown, we should tell the CDM proxy to also shutdown. Otherwise the
   // proxy will shutdown when the owning MediaKeys is destroyed during cycle
   // collection, and that will not shut down cleanly as the GMP thread will be
   // shutdown by then.
   if (mProxy) {
-    RefPtr<Runnable> task =
-      NewRunnableMethod(mProxy, &ChromiumCDMProxy::Shutdown);
+    RefPtr<Runnable> task = NewRunnableMethod(
+      "ChromiumCDMProxy::Shutdown", mProxy, &ChromiumCDMProxy::Shutdown);
     NS_DispatchToMainThread(task.forget());
   }
 
   // We may be called from a task holding the last reference to the proxy, so
   // let's clear our local weak pointer to ensure it will not be used afterward
   // (including from an already-queued task, e.g.: ActorDestroy).
   mProxy = nullptr;
 
--- a/dom/media/gmp/ChromiumCDMProxy.cpp
+++ b/dom/media/gmp/ChromiumCDMProxy.cpp
@@ -69,16 +69,17 @@ ChromiumCDMProxy::Init(PromiseId aPromis
   }
 
   gmp::NodeId nodeId(aOrigin, aTopLevelOrigin, aGMPName);
   RefPtr<AbstractThread> thread = mGMPThread;
   RefPtr<GMPCrashHelper> helper(mCrashHelper);
   RefPtr<ChromiumCDMProxy> self(this);
   nsCString keySystem = NS_ConvertUTF16toUTF8(mKeySystem);
   RefPtr<Runnable> task(NS_NewRunnableFunction(
+    "ChromiumCDMProxy::Init",
     [self, nodeId, helper, aPromiseId, thread, keySystem]() -> void {
       MOZ_ASSERT(self->IsOnOwnerThread());
 
       RefPtr<gmp::GeckoMediaPluginService> service =
         gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
       if (!service) {
         self->RejectPromise(
           aPromiseId,
@@ -120,19 +121,22 @@ void
 ChromiumCDMProxy::OnCDMCreated(uint32_t aPromiseId)
 {
   EME_LOG("ChromiumCDMProxy::OnCDMCreated(pid=%u) isMainThread=%d this=%p",
           aPromiseId,
           NS_IsMainThread(),
           this);
 
   if (!NS_IsMainThread()) {
-    mMainThread->Dispatch(NewRunnableMethod<PromiseId>(
-                            this, &ChromiumCDMProxy::OnCDMCreated, aPromiseId),
-                          NS_DISPATCH_NORMAL);
+    mMainThread->Dispatch(
+      NewRunnableMethod<PromiseId>("ChromiumCDMProxy::OnCDMCreated",
+                                   this,
+                                   &ChromiumCDMProxy::OnCDMCreated,
+                                   aPromiseId),
+      NS_DISPATCH_NORMAL);
     return;
   }
   MOZ_ASSERT(NS_IsMainThread());
   if (mKeys.IsNull()) {
     return;
   }
   RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent();
   // This should only be called once the CDM has been created.
@@ -204,28 +208,29 @@ ChromiumCDMProxy::CreateSession(uint32_t
   RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent();
   if (!cdm) {
     RejectPromise(aPromiseId,
                   NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in CreateSession"));
     return;
   }
 
-  mGMPThread->Dispatch(
-    NewRunnableMethod<uint32_t,
-                      uint32_t,
-                      uint32_t,
-                      uint32_t,
-                      nsTArray<uint8_t>>(cdm,
-                                         &gmp::ChromiumCDMParent::CreateSession,
-                                         aCreateSessionToken,
-                                         sessionType,
-                                         initDataType,
-                                         aPromiseId,
-                                         Move(aInitData)));
+  mGMPThread->Dispatch(NewRunnableMethod<uint32_t,
+                                         uint32_t,
+                                         uint32_t,
+                                         uint32_t,
+                                         nsTArray<uint8_t>>(
+    "gmp::ChromiumCDMParent::CreateSession",
+    cdm,
+    &gmp::ChromiumCDMParent::CreateSession,
+    aCreateSessionToken,
+    sessionType,
+    initDataType,
+    aPromiseId,
+    Move(aInitData)));
 }
 
 void
 ChromiumCDMProxy::LoadSession(PromiseId aPromiseId,
                               dom::MediaKeySessionType aSessionType,
                               const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -234,16 +239,17 @@ ChromiumCDMProxy::LoadSession(PromiseId 
   if (!cdm) {
     RejectPromise(aPromiseId,
                   NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in LoadSession"));
     return;
   }
 
   mGMPThread->Dispatch(NewRunnableMethod<uint32_t, uint32_t, nsString>(
+    "gmp::ChromiumCDMParent::LoadSession",
     cdm,
     &gmp::ChromiumCDMParent::LoadSession,
     aPromiseId,
     ToCDMSessionType(aSessionType),
     aSessionId));
 }
 
 void
@@ -259,16 +265,17 @@ ChromiumCDMProxy::SetServerCertificate(P
   if (!cdm) {
     RejectPromise(aPromiseId,
                   NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in SetServerCertificate"));
     return;
   }
 
   mGMPThread->Dispatch(NewRunnableMethod<uint32_t, nsTArray<uint8_t>>(
+    "gmp::ChromiumCDMParent::SetServerCertificate",
     cdm,
     &gmp::ChromiumCDMParent::SetServerCertificate,
     aPromiseId,
     Move(aCert)));
 }
 
 void
 ChromiumCDMProxy::UpdateSession(const nsAString& aSessionId,
@@ -285,16 +292,17 @@ ChromiumCDMProxy::UpdateSession(const ns
   if (!cdm) {
     RejectPromise(aPromiseId,
                   NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in UpdateSession"));
     return;
   }
   mGMPThread->Dispatch(
     NewRunnableMethod<nsCString, uint32_t, nsTArray<uint8_t>>(
+      "gmp::ChromiumCDMParent::UpdateSession",
       cdm,
       &gmp::ChromiumCDMParent::UpdateSession,
       NS_ConvertUTF16toUTF8(aSessionId),
       aPromiseId,
       Move(aResponse)));
 }
 
 void
@@ -309,16 +317,17 @@ ChromiumCDMProxy::CloseSession(const nsA
   RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent();
   if (!cdm) {
     RejectPromise(aPromiseId,
                   NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in CloseSession"));
     return;
   }
   mGMPThread->Dispatch(NewRunnableMethod<nsCString, uint32_t>(
+    "gmp::ChromiumCDMParent::CloseSession",
     cdm,
     &gmp::ChromiumCDMParent::CloseSession,
     NS_ConvertUTF16toUTF8(aSessionId),
     aPromiseId));
 }
 
 void
 ChromiumCDMProxy::RemoveSession(const nsAString& aSessionId,
@@ -332,16 +341,17 @@ ChromiumCDMProxy::RemoveSession(const ns
   RefPtr<gmp::ChromiumCDMParent> cdm = GetCDMParent();
   if (!cdm) {
     RejectPromise(aPromiseId,
                   NS_ERROR_DOM_INVALID_STATE_ERR,
                   NS_LITERAL_CSTRING("Null CDM in RemoveSession"));
     return;
   }
   mGMPThread->Dispatch(NewRunnableMethod<nsCString, uint32_t>(
+    "gmp::ChromiumCDMParent::RemoveSession",
     cdm,
     &gmp::ChromiumCDMParent::RemoveSession,
     NS_ConvertUTF16toUTF8(aSessionId),
     aPromiseId));
 }
 
 void
 ChromiumCDMProxy::Shutdown()
@@ -353,31 +363,36 @@ ChromiumCDMProxy::Shutdown()
   {
     MutexAutoLock lock(mCDMMutex);
     cdm.swap(mCDM);
   }
   if (cdm) {
     // We need to keep this proxy alive until the parent has finished its
     // Shutdown (as it may still try to use the proxy until then).
     RefPtr<ChromiumCDMProxy> self(this);
-    nsCOMPtr<nsIRunnable> task =
-      NS_NewRunnableFunction([self, cdm]() { cdm->Shutdown(); });
+    nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction(
+      "ChromiumCDMProxy::Shutdown", [self, cdm]() { cdm->Shutdown(); });
     mGMPThread->Dispatch(task.forget());
   }
 }
 
 void
 ChromiumCDMProxy::RejectPromise(PromiseId aId,
                                 nsresult aCode,
                                 const nsCString& aReason)
 {
   if (!NS_IsMainThread()) {
     nsCOMPtr<nsIRunnable> task;
     task = NewRunnableMethod<PromiseId, nsresult, nsCString>(
-      this, &ChromiumCDMProxy::RejectPromise, aId, aCode, aReason);
+      "ChromiumCDMProxy::RejectPromise",
+      this,
+      &ChromiumCDMProxy::RejectPromise,
+      aId,
+      aCode,
+      aReason);
     NS_DispatchToMainThread(task);
     return;
   }
   EME_LOG("ChromiumCDMProxy::RejectPromise(pid=%u, code=0x%x, reason='%s')",
           aId,
           static_cast<uint32_t>(aCode),
           aReason.get());
   if (!mKeys.IsNull()) {
@@ -385,18 +400,20 @@ ChromiumCDMProxy::RejectPromise(PromiseI
   }
 }
 
 void
 ChromiumCDMProxy::ResolvePromise(PromiseId aId)
 {
   if (!NS_IsMainThread()) {
     nsCOMPtr<nsIRunnable> task;
-    task = NewRunnableMethod<PromiseId>(
-      this, &ChromiumCDMProxy::ResolvePromise, aId);
+    task = NewRunnableMethod<PromiseId>("ChromiumCDMProxy::ResolvePromise",
+                                        this,
+                                        &ChromiumCDMProxy::ResolvePromise,
+                                        aId);
     NS_DispatchToMainThread(task);
     return;
   }
 
   EME_LOG("ChromiumCDMProxy::ResolvePromise(pid=%u)", aId);
   if (!mKeys.IsNull()) {
     mKeys->ResolvePromise(aId);
   } else {
--- a/dom/media/gmp/GMPCDMCallbackProxy.cpp
+++ b/dom/media/gmp/GMPCDMCallbackProxy.cpp
@@ -25,57 +25,50 @@ GMPCDMCallbackProxy::GMPCDMCallbackProxy
 
 void
 GMPCDMCallbackProxy::SetDecryptorId(uint32_t aId)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   RefPtr<CDMProxy> proxy = mProxy;
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy, aId] ()
-    {
-      proxy->OnSetDecryptorId(aId);
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction("GMPCDMCallbackProxy::SetDecryptorId",
+                           [proxy, aId]() { proxy->OnSetDecryptorId(aId); }),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMCallbackProxy::SetSessionId(uint32_t aToken,
                                   const nsCString& aSessionId)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   RefPtr<CDMProxy> proxy = mProxy;
   auto sid = NS_ConvertUTF8toUTF16(aSessionId);
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy,
-                            aToken,
-                            sid] ()
-    {
-      proxy->OnSetSessionId(aToken, sid);
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction(
+      "GMPCDMCallbackProxy::SetSessionId",
+      [proxy, aToken, sid]() { proxy->OnSetSessionId(aToken, sid); }),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId,
                                                bool aSuccess)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   RefPtr<CDMProxy> proxy = mProxy;
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy, aPromiseId, aSuccess] ()
-    {
-      proxy->OnResolveLoadSessionPromise(aPromiseId, aSuccess);
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction("GMPCDMCallbackProxy::ResolveLoadSessionPromise",
+                           [proxy, aPromiseId, aSuccess]() {
+                             proxy->OnResolveLoadSessionPromise(aPromiseId,
+                                                                aSuccess);
+                           }),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMCallbackProxy::ResolvePromise(uint32_t aPromiseId)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   // Note: CDMProxy proxies this from non-main threads to main thread.
@@ -86,125 +79,103 @@ void
 GMPCDMCallbackProxy::RejectPromise(uint32_t aPromiseId,
                                    nsresult aException,
                                    const nsCString& aMessage)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   RefPtr<CDMProxy> proxy = mProxy;
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy,
-                            aPromiseId,
-                            aException,
-                            aMessage] ()
-    {
-      proxy->OnRejectPromise(aPromiseId, aException, aMessage);
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction("GMPCDMCallbackProxy::RejectPromise",
+                           [proxy, aPromiseId, aException, aMessage]() {
+                             proxy->OnRejectPromise(
+                               aPromiseId, aException, aMessage);
+                           }),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMCallbackProxy::SessionMessage(const nsCString& aSessionId,
                                     dom::MediaKeyMessageType aMessageType,
                                     const nsTArray<uint8_t>& aMessage)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   RefPtr<CDMProxy> proxy = mProxy;
   auto sid = NS_ConvertUTF8toUTF16(aSessionId);
   nsTArray<uint8_t> msg(aMessage);
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy,
-                            sid,
-                            aMessageType,
-                            msg] () mutable
-    {
-      proxy->OnSessionMessage(sid, aMessageType, msg);
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction("GMPCDMCallbackProxy::SessionMessage",
+                           [proxy, sid, aMessageType, msg]() mutable {
+                             proxy->OnSessionMessage(sid, aMessageType, msg);
+                           }),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMCallbackProxy::ExpirationChange(const nsCString& aSessionId,
                                       GMPTimestamp aExpiryTime)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   RefPtr<CDMProxy> proxy = mProxy;
   auto sid = NS_ConvertUTF8toUTF16(aSessionId);
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy,
-                            sid,
-                            aExpiryTime] ()
-    {
-      proxy->OnExpirationChange(sid, aExpiryTime);
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction("GMPCDMCallbackProxy::ExpirationChange",
+                           [proxy, sid, aExpiryTime]() {
+                             proxy->OnExpirationChange(sid, aExpiryTime);
+                           }),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMCallbackProxy::SessionClosed(const nsCString& aSessionId)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   bool keyStatusesChange = false;
   auto sid = NS_ConvertUTF8toUTF16(aSessionId);
   {
     CDMCaps::AutoLock caps(mProxy->Capabilites());
     keyStatusesChange = caps.RemoveKeysForSession(NS_ConvertUTF8toUTF16(aSessionId));
   }
   if (keyStatusesChange) {
     RefPtr<CDMProxy> proxy = mProxy;
     mMainThread->Dispatch(
-      NS_NewRunnableFunction([proxy, sid] ()
-      {
-        proxy->OnKeyStatusesChange(sid);
-      }),
-      NS_DISPATCH_NORMAL
-    );
+      NS_NewRunnableFunction(
+        "GMPCDMCallbackProxy::SessionClosed",
+        [proxy, sid]() { proxy->OnKeyStatusesChange(sid); }),
+      NS_DISPATCH_NORMAL);
   }
 
   RefPtr<CDMProxy> proxy = mProxy;
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy, sid] ()
-    {
-      proxy->OnSessionClosed(sid);
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction("GMPCDMCallbackProxy::SessionClosed",
+                           [proxy, sid]() { proxy->OnSessionClosed(sid); }),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMCallbackProxy::SessionError(const nsCString& aSessionId,
                                   nsresult aException,
                                   uint32_t aSystemCode,
                                   const nsCString& aMessage)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   RefPtr<CDMProxy> proxy = mProxy;
   auto sid = NS_ConvertUTF8toUTF16(aSessionId);
   auto msg = NS_ConvertUTF8toUTF16(aMessage);
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy,
-                            sid,
-                            aException,
-                            aSystemCode,
-                            msg] ()
-    {
-      proxy->OnSessionError(sid,
-                        aException,
-                        aSystemCode,
-                        msg);
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction("GMPCDMCallbackProxy::SessionError",
+                           [proxy, sid, aException, aSystemCode, msg]() {
+                             proxy->OnSessionError(
+                               sid, aException, aSystemCode, msg);
+                           }),
+    NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMCallbackProxy::BatchedKeyStatusChanged(const nsCString& aSessionId,
                                              const nsTArray<CDMKeyInfo>& aKeyInfos)
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
   BatchedKeyStatusChangedInternal(aSessionId, aKeyInfos);
@@ -223,22 +194,20 @@ GMPCDMCallbackProxy::BatchedKeyStatusCha
                           NS_ConvertUTF8toUTF16(aSessionId),
                           aKeyInfos[i].mStatus);
     }
   }
   if (keyStatusesChange) {
     RefPtr<CDMProxy> proxy = mProxy;
     auto sid = NS_ConvertUTF8toUTF16(aSessionId);
     mMainThread->Dispatch(
-      NS_NewRunnableFunction([proxy, sid] ()
-      {
-        proxy->OnKeyStatusesChange(sid);
-      }),
-      NS_DISPATCH_NORMAL
-    );
+      NS_NewRunnableFunction(
+        "GMPCDMCallbackProxy::BatchedKeyStatusChangedInternal",
+        [proxy, sid]() { proxy->OnKeyStatusesChange(sid); }),
+      NS_DISPATCH_NORMAL);
   }
 }
 
 void
 GMPCDMCallbackProxy::Decrypted(uint32_t aId,
                                DecryptStatus aResult,
                                const nsTArray<uint8_t>& aDecryptedData)
 {
@@ -249,17 +218,14 @@ GMPCDMCallbackProxy::Decrypted(uint32_t 
 
 void
 GMPCDMCallbackProxy::Terminated()
 {
   MOZ_ASSERT(mProxy->IsOnOwnerThread());
 
   RefPtr<CDMProxy> proxy = mProxy;
   mMainThread->Dispatch(
-    NS_NewRunnableFunction([proxy] ()
-    {
-      proxy->Terminated();
-    }),
-    NS_DISPATCH_NORMAL
-  );
+    NS_NewRunnableFunction("GMPCDMCallbackProxy::Terminated",
+                           [proxy]() { proxy->Terminated(); }),
+    NS_DISPATCH_NORMAL);
 }
 
 } // namespace mozilla
--- a/dom/media/gmp/GMPCDMProxy.cpp
+++ b/dom/media/gmp/GMPCDMProxy.cpp
@@ -87,17 +87,18 @@ GMPCDMProxy::Init(PromiseId aPromiseId,
 
   UniquePtr<InitData> data(new InitData());
   data->mPromiseId = aPromiseId;
   data->mOrigin = aOrigin;
   data->mTopLevelOrigin = aTopLevelOrigin;
   data->mGMPName = aGMPName;
   data->mCrashHelper = mCrashHelper;
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<InitData>&&>(this,
+    NewRunnableMethod<UniquePtr<InitData>&&>("GMPCDMProxy::gmp_Init",
+                                             this,
                                              &GMPCDMProxy::gmp_Init,
                                              Move(data)));
   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 #ifdef DEBUG
 bool
 GMPCDMProxy::IsOnOwnerThread()
@@ -134,17 +135,18 @@ GMPCDMProxy::gmp_InitDone(GMPDecryptorPr
   mCreatePromiseId = aData->mPromiseId;
 }
 
 void GMPCDMProxy::OnSetDecryptorId(uint32_t aId)
 {
   MOZ_ASSERT(mCreatePromiseId);
   mDecryptorId = aId;
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<uint32_t>(this,
+    NewRunnableMethod<uint32_t>("GMPCDMProxy::OnCDMCreated",
+                                this,
                                 &GMPCDMProxy::OnCDMCreated,
                                 mCreatePromiseId));
   mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 class gmp_InitDoneCallback : public GetGMPDecryptorCallback
 {
 public:
@@ -289,17 +291,18 @@ GMPCDMProxy::CreateSession(uint32_t aCre
   UniquePtr<CreateSessionData> data(new CreateSessionData());
   data->mSessionType = aSessionType;
   data->mCreateSessionToken = aCreateSessionToken;
   data->mPromiseId = aPromiseId;
   data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType);
   data->mInitData = Move(aInitData);
 
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<CreateSessionData>&&>(this,
+    NewRunnableMethod<UniquePtr<CreateSessionData>&&>("GMPCDMProxy::gmp_CreateSession",
+                                                      this,
                                                       &GMPCDMProxy::gmp_CreateSession,
                                                       Move(data)));
   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 GMPSessionType
 ToGMPSessionType(dom::MediaKeySessionType aSessionType) {
   switch (aSessionType) {
@@ -332,17 +335,18 @@ GMPCDMProxy::LoadSession(PromiseId aProm
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mOwnerThread);
 
   UniquePtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<SessionOpData>&&>(this,
+    NewRunnableMethod<UniquePtr<SessionOpData>&&>("GMPCDMProxy::gmp_LoadSession",
+                                                  this,
                                                   &GMPCDMProxy::gmp_LoadSession,
                                                   Move(data)));
   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_LoadSession(UniquePtr<SessionOpData>&& aData)
 {
@@ -362,17 +366,18 @@ GMPCDMProxy::SetServerCertificate(Promis
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mOwnerThread);
 
   UniquePtr<SetServerCertificateData> data(new SetServerCertificateData());
   data->mPromiseId = aPromiseId;
   data->mCert = Move(aCert);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<SetServerCertificateData>&&>(this,
+    NewRunnableMethod<UniquePtr<SetServerCertificateData>&&>("GMPCDMProxy::gmp_SetServerCertificate",
+                                                             this,
                                                              &GMPCDMProxy::gmp_SetServerCertificate,
                                                              Move(data)));
   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_SetServerCertificate(UniquePtr<SetServerCertificateData>&& aData)
 {
@@ -394,17 +399,18 @@ GMPCDMProxy::UpdateSession(const nsAStri
   MOZ_ASSERT(mOwnerThread);
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   UniquePtr<UpdateSessionData> data(new UpdateSessionData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   data->mResponse = Move(aResponse);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<UpdateSessionData>&&>(this,
+    NewRunnableMethod<UniquePtr<UpdateSessionData>&&>("GMPCDMProxy::gmp_UpdateSession",
+                                                      this,
                                                       &GMPCDMProxy::gmp_UpdateSession,
                                                       Move(data)));
   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_UpdateSession(UniquePtr<UpdateSessionData>&& aData)
 {
@@ -425,17 +431,18 @@ GMPCDMProxy::CloseSession(const nsAStrin
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   UniquePtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<SessionOpData>&&>(this,
+    NewRunnableMethod<UniquePtr<SessionOpData>&&>("GMPCDMProxy::gmp_CloseSession",
+                                                  this,
                                                   &GMPCDMProxy::gmp_CloseSession,
                                                   Move(data)));
   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_CloseSession(UniquePtr<SessionOpData>&& aData)
 {
@@ -454,17 +461,18 @@ GMPCDMProxy::RemoveSession(const nsAStri
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
 
   UniquePtr<SessionOpData> data(new SessionOpData());
   data->mPromiseId = aPromiseId;
   data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId);
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<UniquePtr<SessionOpData>&&>(this,
+    NewRunnableMethod<UniquePtr<SessionOpData>&&>("GMPCDMProxy::gmp_RemoveSession",
+                                                  this,
                                                   &GMPCDMProxy::gmp_RemoveSession,
                                                   Move(data)));
   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
 }
 
 void
 GMPCDMProxy::gmp_RemoveSession(UniquePtr<SessionOpData>&& aData)
 {
@@ -478,17 +486,18 @@ GMPCDMProxy::gmp_RemoveSession(UniquePtr
 }
 
 void
 GMPCDMProxy::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mKeys.Clear();
   // Note: This may end up being the last owning reference to the GMPCDMProxy.
-  nsCOMPtr<nsIRunnable> task(NewRunnableMethod(this, &GMPCDMProxy::gmp_Shutdown));
+  nsCOMPtr<nsIRunnable> task(NewRunnableMethod(
+    "GMPCDMProxy::gmp_Shutdown", this, &GMPCDMProxy::gmp_Shutdown));
   if (mOwnerThread) {
     mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
   }
 }
 
 void
 GMPCDMProxy::gmp_Shutdown()
 {
@@ -530,19 +539,18 @@ GMPCDMProxy::ResolvePromise(PromiseId aI
   if (NS_IsMainThread()) {
     if (!mKeys.IsNull()) {
       mKeys->ResolvePromise(aId);
     } else {
       NS_WARNING("GMPCDMProxy unable to resolve promise!");
     }
   } else {
     nsCOMPtr<nsIRunnable> task;
-    task = NewRunnableMethod<PromiseId>(this,
-                                        &GMPCDMProxy::ResolvePromise,
-                                        aId);
+    task = NewRunnableMethod<PromiseId>(
+      "GMPCDMProxy::ResolvePromise", this, &GMPCDMProxy::ResolvePromise, aId);
     mMainThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
   }
 }
 
 const nsCString&
 GMPCDMProxy::GetNodeId() const
 {
   return mNodeId;
@@ -679,17 +687,18 @@ GMPCDMProxy::Capabilites() {
 
 RefPtr<DecryptPromise>
 GMPCDMProxy::Decrypt(MediaRawData* aSample)
 {
   RefPtr<DecryptJob> job(new DecryptJob(aSample));
   RefPtr<DecryptPromise> promise(job->Ensure());
 
   nsCOMPtr<nsIRunnable> task(
-    NewRunnableMethod<RefPtr<DecryptJob>>(this, &GMPCDMProxy::gmp_Decrypt, job));
+    NewRunnableMethod<RefPtr<DecryptJob>>("GMPCDMProxy::gmp_Decrypt",
+                                          this, &GMPCDMProxy::gmp_Decrypt, job));
   mOwnerThread->EventTarget()->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
   return promise;
 }
 
 void
 GMPCDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob)
 {
   MOZ_ASSERT(IsOnOwnerThread());
--- a/dom/media/gmp/GMPCDMProxy.h
+++ b/dom/media/gmp/GMPCDMProxy.h
@@ -186,17 +186,18 @@ private:
                      const nsTArray<uint8_t>& aDecryptedData);
 
   class RejectPromiseTask : public Runnable {
   public:
     RejectPromiseTask(GMPCDMProxy* aProxy,
                       PromiseId aId,
                       nsresult aCode,
                       const nsCString& aReason)
-      : mProxy(aProxy)
+      : Runnable("GMPCDMProxy::RejectPromiseTask")
+      , mProxy(aProxy)
       , mId(aId)
       , mCode(aCode)
       , mReason(aReason)
     {
     }
     NS_IMETHOD Run() override {
       mProxy->RejectPromise(mId, mCode, mReason);
       return NS_OK;
--- a/dom/media/gmp/GMPContentParent.cpp
+++ b/dom/media/gmp/GMPContentParent.cpp
@@ -45,17 +45,18 @@ GMPContentParent::GMPContentParent(GMPPa
 GMPContentParent::~GMPContentParent()
 {
 }
 
 class ReleaseGMPContentParent : public Runnable
 {
 public:
   explicit ReleaseGMPContentParent(GMPContentParent* aToRelease)
-    : mToRelease(aToRelease)
+    : Runnable("gmp::ReleaseGMPContentParent")
+    , mToRelease(aToRelease)
   {
   }
 
   NS_IMETHOD Run() override
   {
     return NS_OK;
   }
 
@@ -140,18 +141,18 @@ GMPContentParent::CloseIfUnused()
     if (mParent) {
       toClose = mParent->ForgetGMPContentParent();
     } else {
       toClose = this;
       RefPtr<GeckoMediaPluginServiceChild> gmp(
         GeckoMediaPluginServiceChild::GetSingleton());
       gmp->RemoveGMPContentParent(toClose);
     }
-    NS_DispatchToCurrentThread(NewRunnableMethod(toClose,
-                                                 &GMPContentParent::Close));
+    NS_DispatchToCurrentThread(NewRunnableMethod(
+      "gmp::GMPContentParent::Close", toClose, &GMPContentParent::Close));
   }
 }
 
 nsresult
 GMPContentParent::GetGMPDecryptor(GMPDecryptorParent** aGMPDP)
 {
   PGMPDecryptorParent* pdp = SendPGMPDecryptorConstructor();
   if (!pdp) {
--- a/dom/media/gmp/GMPCrashHelper.cpp
+++ b/dom/media/gmp/GMPCrashHelper.cpp
@@ -14,15 +14,17 @@ NS_IMPL_RELEASE_WITH_DESTROY(GMPCrashHel
 
 void
 GMPCrashHelper::Destroy()
 {
   if (NS_IsMainThread()) {
     delete this;
   } else {
     // Don't addref, as then we'd end up releasing after the detele runs!
-    SystemGroup::Dispatch(
-      "GMPCrashHelper::Destroy", TaskCategory::Other,
-      NewNonOwningRunnableMethod(this, &GMPCrashHelper::Destroy));
+    SystemGroup::Dispatch("GMPCrashHelper::Destroy",
+                          TaskCategory::Other,
+                          NewNonOwningRunnableMethod("GMPCrashHelper::Destroy",
+                                                     this,
+                                                     &GMPCrashHelper::Destroy));
   }
 }
 
 } // namespace mozilla
--- a/dom/media/gmp/GMPDecryptorChild.cpp
+++ b/dom/media/gmp/GMPDecryptorChild.cpp
@@ -191,20 +191,22 @@ GMPDecryptorChild::BatchedKeyStatusChang
 }
 
 void
 GMPDecryptorChild::Decrypted(GMPBuffer* aBuffer, GMPErr aResult)
 {
   if (!ON_GMP_THREAD()) {
     // We should run this whole method on the GMP thread since the buffer needs
     // to be deleted after the SendDecrypted call.
-    mPlugin->GMPMessageLoop()->PostTask(NewRunnableMethod
-                                        <GMPBuffer*, GMPErr>(this,
-                                                             &GMPDecryptorChild::Decrypted,
-                                                             aBuffer, aResult));
+    mPlugin->GMPMessageLoop()->PostTask(
+      NewRunnableMethod<GMPBuffer*, GMPErr>("gmp::GMPDecryptorChild::Decrypted",
+                                            this,
+                                            &GMPDecryptorChild::Decrypted,
+                                            aBuffer,
+                                            aResult));
     return;
   }
 
   if (!aBuffer) {
     NS_WARNING("GMPDecryptorCallback passed bull GMPBuffer");
     return;
   }
 
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -329,16 +329,17 @@ GMPParent::ChildTerminated()
   if (!gmpEventTarget) {
     // Bug 1163239 - this can happen on shutdown.
     // PluginTerminated removes the GMP from the GMPService.
     // On shutdown we can have this case where it is already been
     // removed so there is no harm in not trying to remove it again.
     LOGD("%s::%s: GMPEventTarget() returned nullptr.", __CLASS__, __FUNCTION__);
   } else {
     gmpEventTarget->Dispatch(NewRunnableMethod<RefPtr<GMPParent>>(
+                               "gmp::GeckoMediaPluginServiceParent::PluginTerminated",
                                mService,
                                &GeckoMediaPluginServiceParent::PluginTerminated,
                                self),
                              NS_DISPATCH_NORMAL);
   }
 }
 
 void
@@ -347,17 +348,18 @@ GMPParent::DeleteProcess()
   LOGD("%s", __FUNCTION__);
 
   if (mState != GMPStateClosing) {
     // Don't Close() twice!
     // Probably remove when bug 1043671 is resolved
     mState = GMPStateClosing;
     Close();
   }
-  mProcess->Delete(NewRunnableMethod(this, &GMPParent::ChildTerminated));
+  mProcess->Delete(NewRunnableMethod(
+    "gmp::GMPParent::ChildTerminated", this, &GMPParent::ChildTerminated));
   LOGD("%s: Shut down process", __FUNCTION__);
   mProcess = nullptr;
   mState = GMPStateNotLoaded;
 
   nsCOMPtr<nsIRunnable> r
     = new NotifyGMPShutdownTask(NS_ConvertUTF8toUTF16(mNodeId));
   mMainThread->Dispatch(r.forget());
 
--- a/dom/media/gmp/GMPPlatform.cpp
+++ b/dom/media/gmp/GMPPlatform.cpp
@@ -72,17 +72,18 @@ public:
   void Post()
   {
     // We assert here for two reasons.
     // 1) Nobody should be blocking the main thread.
     // 2) This prevents deadlocks when doing sync calls to main which if the
     //    main thread tries to do a sync call back to the calling thread.
     MOZ_ASSERT(!IsOnChildMainThread());
 
-    mMessageLoop->PostTask(NewRunnableMethod(this, &GMPSyncRunnable::Run));
+    mMessageLoop->PostTask(NewRunnableMethod(
+      "gmp::GMPSyncRunnable::Run", this, &GMPSyncRunnable::Run));
     MonitorAutoLock lock(mMonitor);
     while (!mDone) {
       lock.Wait();
     }
   }
 
   void Run()
   {
@@ -135,17 +136,18 @@ CreateThread(GMPThread** aThread)
 GMPErr
 RunOnMainThread(GMPTask* aTask)
 {
   if (!aTask || !sMainLoop) {
     return GMPGenericErr;
   }
 
   RefPtr<GMPRunnable> r = new GMPRunnable(aTask);
-  sMainLoop->PostTask(NewRunnableMethod(r, &GMPRunnable::Run));
+  sMainLoop->PostTask(
+    NewRunnableMethod("gmp::GMPRunnable::Run", r, &GMPRunnable::Run));
 
   return GMPNoErr;
 }
 
 GMPErr
 SyncRunOnMainThread(GMPTask* aTask)
 {
   if (!aTask || !sMainLoop || IsOnChildMainThread()) {
@@ -269,17 +271,18 @@ GMPThreadImpl::Post(GMPTask* aTask)
     bool started = mThread.Start();
     if (!started) {
       NS_WARNING("Unable to start GMPThread!");
       return;
     }
   }
 
   RefPtr<GMPRunnable> r = new GMPRunnable(aTask);
-  mThread.message_loop()->PostTask(NewRunnableMethod(r.get(), &GMPRunnable::Run));
+  mThread.message_loop()->PostTask(
+    NewRunnableMethod("gmp::GMPRunnable::Run", r.get(), &GMPRunnable::Run));
 }
 
 void
 GMPThreadImpl::Join()
 {
   {
     MutexAutoLock lock(mMutex);
     if (mThread.IsRunning()) {
--- a/dom/media/gmp/GMPProcessParent.cpp
+++ b/dom/media/gmp/GMPProcessParent.cpp
@@ -80,17 +80,18 @@ GMPProcessParent::Launch(int32_t aTimeou
 
   return SyncLaunch(args, aTimeoutMs, base::GetCurrentProcessArchitecture());
 }
 
 void
 GMPProcessParent::Delete(nsCOMPtr<nsIRunnable> aCallback)
 {
   mDeletedCallback = aCallback;
-  XRE_GetIOMessageLoop()->PostTask(NewNonOwningRunnableMethod(this, &GMPProcessParent::DoDelete));
+  XRE_GetIOMessageLoop()->PostTask(NewNonOwningRunnableMethod(
+    "gmp::GMPProcessParent::DoDelete", this, &GMPProcessParent::DoDelete));
 }
 
 void
 GMPProcessParent::DoDelete()
 {
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
   Join();
 
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -485,18 +485,19 @@ GMPServiceChild::GetAlreadyBridgedTo(nsT
   }
 }
 
 class OpenPGMPServiceChild : public mozilla::Runnable
 {
 public:
   OpenPGMPServiceChild(UniquePtr<GMPServiceChild>&& aGMPServiceChild,
                        ipc::Endpoint<PGMPServiceChild>&& aEndpoint)
-    : mGMPServiceChild(Move(aGMPServiceChild)),
-      mEndpoint(Move(aEndpoint))
+    : Runnable("gmp::OpenPGMPServiceChild")
+    , mGMPServiceChild(Move(aGMPServiceChild))
+    , mEndpoint(Move(aEndpoint))
   {
   }
 
   NS_IMETHOD Run() override
   {
     RefPtr<GeckoMediaPluginServiceChild> gmp =
       GeckoMediaPluginServiceChild::GetSingleton();
     MOZ_ASSERT(!gmp->mServiceChild);
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -136,18 +136,20 @@ GeckoMediaPluginServiceParent::Init()
     return rv;
   }
 
   // Detect if GMP storage has an incompatible version, and if so nuke it.
   int32_t version = Preferences::GetInt("media.gmp.storage.version.observed", 0);
   int32_t expected = Preferences::GetInt("media.gmp.storage.version.expected", 0);
   if (version != expected) {
     Preferences::SetInt("media.gmp.storage.version.observed", expected);
-    return GMPDispatch(NewRunnableMethod(
-      this, &GeckoMediaPluginServiceParent::ClearStorage));
+    return GMPDispatch(
+      NewRunnableMethod("gmp::GeckoMediaPluginServiceParent::ClearStorage",
+                        this,
+                        &GeckoMediaPluginServiceParent::ClearStorage));
   }
   return NS_OK;
 }
 
 already_AddRefed<nsIFile>
 CloneAndAppend(nsIFile* aFile, const nsAString& aDir)
 {
   nsCOMPtr<nsIFile> f;
@@ -293,17 +295,18 @@ GeckoMediaPluginServicePare