merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 17 Oct 2017 11:45:16 +0200
changeset 386585 0d9c6250f99dc4b6aa1a94f5260737d046c52b1e
parent 386521 3bd3448d9684f3acd5d6da862630a6ff44224fb6 (current diff)
parent 386584 1498abcee79d232125fb44846849160ec3c1fa51 (diff)
child 386586 f27105b62753c71ecadad2f8d632ec7e5ac96bbd
child 386606 ae8209659b665bc2b11b11258290594fae79d4aa
child 386652 c44b13d3ac6a014b095372e7dbe3e6b825d9db44
push id32695
push userarchaeopteryx@coole-files.de
push dateTue, 17 Oct 2017 09:45:44 +0000
treeherdermozilla-central@0d9c6250f99d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.0a1
first release with
nightly linux32
0d9c6250f99d / 58.0a1 / 20171017100127 / files
nightly linux64
0d9c6250f99d / 58.0a1 / 20171017100127 / files
nightly mac
0d9c6250f99d / 58.0a1 / 20171017100127 / files
nightly win32
0d9c6250f99d / 58.0a1 / 20171017100127 / files
nightly win64
0d9c6250f99d / 58.0a1 / 20171017100127 / 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. r=merge a=merge MozReview-Commit-ID: 1h3kZyrtqSt
devtools/client/debugger/new/test/mochitest/browser.ini
dom/html/HTMLMediaElement.cpp
dom/media/ChannelMediaDecoder.cpp
layout/base/nsPresContext.cpp
layout/printing/nsPagePrintTimer.cpp
modules/libpref/init/all.js
netwerk/base/Predictor.cpp
netwerk/protocol/http/nsHttpChannel.cpp
security/sandbox/linux/SandboxFilter.cpp
taskcluster/ci/test/tests.yml
widget/headless/HeadlessLookAndFeelGTK.cpp
xpcom/threads/nsThreadUtils.h
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -463,19 +463,20 @@ nsAccessibilityService::CreatePluginAcce
 #if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
   RefPtr<nsNPAPIPluginInstance> pluginInstance;
   if (NS_SUCCEEDED(aFrame->GetPluginInstance(getter_AddRefs(pluginInstance))) &&
       pluginInstance) {
 #ifdef XP_WIN
     if (!sPendingPlugins->Contains(aContent) &&
         (Preferences::GetBool("accessibility.delay_plugins") ||
          Compatibility::IsJAWS() || Compatibility::IsWE())) {
-      nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
       RefPtr<PluginTimerCallBack> cb = new PluginTimerCallBack(aContent);
-      timer->InitWithCallback(cb, Preferences::GetUint("accessibility.delay_plugin_time"),
+      nsCOMPtr<nsITimer> timer;
+      NS_NewTimerWithCallback(getter_AddRefs(timer),
+                              cb, Preferences::GetUint("accessibility.delay_plugin_time"),
                               nsITimer::TYPE_ONE_SHOT);
       sPluginTimers->AppendElement(timer);
       sPendingPlugins->AppendElement(aContent);
       return nullptr;
     }
 
     // We need to remove aContent from the pending plugins here to avoid
     // reentrancy.  When the timer fires it calls
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -645,25 +645,24 @@ DocAccessible::ScrollPositionDidChange(n
 {
   // Start new timer, if the timer cycles at least 1 full cycle without more scroll position changes,
   // then the ::Notify() method will fire the accessibility event for scroll position changes
   const uint32_t kScrollPosCheckWait = 50;
   if (mScrollWatchTimer) {
     mScrollWatchTimer->SetDelay(kScrollPosCheckWait);  // Create new timer, to avoid leaks
   }
   else {
-    mScrollWatchTimer = do_CreateInstance("@mozilla.org/timer;1");
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mScrollWatchTimer),
+                                ScrollTimerCallback,
+                                this,
+                                kScrollPosCheckWait,
+                                nsITimer::TYPE_REPEATING_SLACK,
+                                "a11y::DocAccessible::ScrollPositionDidChange");
     if (mScrollWatchTimer) {
       NS_ADDREF_THIS(); // Kung fu death grip
-      mScrollWatchTimer->InitWithNamedFuncCallback(
-        ScrollTimerCallback,
-        this,
-        kScrollPosCheckWait,
-        nsITimer::TYPE_REPEATING_SLACK,
-        "a11y::DocAccessible::ScrollPositionDidChange");
     }
   }
   mScrollPositionChangedTicks = 1;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIObserver
 
--- a/accessible/xpcom/xpcAccessibilityService.cpp
+++ b/accessible/xpcom/xpcAccessibilityService.cpp
@@ -72,25 +72,22 @@ xpcAccessibilityService::Release(void)
     return 0;
   }
 
   // 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->InitWithNamedFuncCallback(
-        ShutdownCallback,
-        this,
-        100,
-        nsITimer::TYPE_ONE_SHOT,
-        "xpcAccessibilityService::Release");
-    }
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mShutdownTimer),
+                                ShutdownCallback,
+                                this,
+                                100,
+                                nsITimer::TYPE_ONE_SHOT,
+                                "xpcAccessibilityService::Release");
   }
 
   return count;
 }
 
 NS_IMPL_QUERY_INTERFACE(xpcAccessibilityService, nsIAccessibilityService)
 
 NS_IMETHODIMP
--- a/browser/base/content/sanitize.js
+++ b/browser/base/content/sanitize.js
@@ -22,17 +22,17 @@ XPCOMUtils.defineLazyModuleGetters(this,
 
 XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager",
                                    "@mozilla.org/serviceworkers/manager;1",
                                    "nsIServiceWorkerManager");
 XPCOMUtils.defineLazyServiceGetter(this, "quotaManagerService",
                                    "@mozilla.org/dom/quota-manager-service;1",
                                    "nsIQuotaManagerService");
 
-var {classes: Cc, interfaces: Ci} = Components;
+var {classes: Cc, interfaces: Ci, results: Cr} = Components;
 
 /**
  * A number of iterations after which to yield time back
  * to the system.
  */
 const YIELD_PERIOD = 10;
 
 function Sanitizer() {
@@ -303,16 +303,23 @@ Sanitizer.prototype = {
           let host = sw.principal.URI.host;
           serviceWorkerManager.removeAndPropagate(host);
         }
 
         // QuotaManager
         let promises = [];
         await new Promise(resolve => {
           quotaManagerService.getUsage(request => {
+            if (request.resultCode != Cr.NS_OK) {
+              // We are probably shutting down. We don't want to propagate the
+              // error, rejecting the promise.
+              resolve();
+              return;
+            }
+
             for (let item of request.result) {
               let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
               let uri = principal.URI;
               if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") {
                 promises.push(new Promise(r => {
                   let req = quotaManagerService.clearStoragesForPrincipal(principal, null, false);
                   req.callback = () => { r(); };
                 }));
--- a/browser/components/extensions/ext-browsingData.js
+++ b/browser/components/extensions/ext-browsingData.js
@@ -83,16 +83,23 @@ const clearHistory = options => {
   return sanitizer.items.history.clear(makeRange(options));
 };
 
 const clearIndexedDB = async function(options) {
   let promises = [];
 
   await new Promise(resolve => {
     quotaManagerService.getUsage(request => {
+      if (request.resultCode != Components.results.NS_OK) {
+        // We are probably shutting down. We don't want to propagate the error,
+        // rejecting the promise.
+        resolve();
+        return;
+      }
+
       for (let item of request.result) {
         let principal = Services.scriptSecurityManager.createCodebasePrincipalFromOrigin(item.origin);
         let uri = principal.URI;
         if (uri.scheme == "http" || uri.scheme == "https" || uri.scheme == "file") {
           promises.push(new Promise(r => {
             let req = quotaManagerService.clearStoragesForPrincipal(principal, null, false);
             req.callback = () => { r(); };
           }));
--- a/browser/components/places/tests/browser/browser_click_bookmarks_on_toolbar.js
+++ b/browser/components/places/tests/browser/browser_click_bookmarks_on_toolbar.js
@@ -123,8 +123,41 @@ add_task(async function clickWithPrefSet
   let open = document.getElementById("placesContext_open");
   EventUtils.synthesizeMouseAtCenter(open, {
     button: 0
   });
   await promise;
 
   await SpecialPowers.popPrefEnv();
 });
+
+// Open a tab, then quickly open the context menu to ensure that the command
+// enabled state of the menuitems is updated properly.
+add_task(async function quickContextMenu() {
+  await SpecialPowers.pushPrefEnv({set: [
+    [PREF_LOAD_BOOKMARKS_IN_TABS, true]
+  ]});
+
+  let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, TEST_PAGES[0]);
+
+  EventUtils.synthesizeMouseAtCenter(gBookmarkElements[0], {
+    button: 0
+  });
+  let newTab = await tabPromise;
+
+  let placesContext = document.getElementById("placesContext");
+  let promise = BrowserTestUtils.waitForEvent(placesContext, "popupshown");
+  EventUtils.synthesizeMouseAtCenter(gBookmarkElements[1], {
+    button: 2,
+    type: "contextmenu"
+  });
+  await promise;
+
+  Assert.ok(!document.getElementById("placesContext_open").disabled,
+            "Commands in context menu are enabled");
+
+  promise = BrowserTestUtils.waitForEvent(placesContext, "popuphidden");
+  placesContext.hidePopup();
+  await promise;
+  await BrowserTestUtils.removeTab(newTab);
+
+  await SpecialPowers.popPrefEnv();
+});
--- a/devtools/client/aboutdebugging/test/browser.ini
+++ b/devtools/client/aboutdebugging/test/browser.ini
@@ -17,24 +17,26 @@ support-files =
   service-workers/empty-sw.js
   service-workers/fetch-sw.html
   service-workers/fetch-sw.js
   service-workers/push-sw.html
   service-workers/push-sw.js
   !/devtools/client/framework/test/shared-head.js
 
 [browser_addons_debug_bootstrapped.js]
+skip-if = coverage # Bug 1387827
 [browser_addons_debug_info.js]
 [browser_addons_debug_webextension.js]
 tags = webextensions
 [browser_addons_debug_webextension_inspector.js]
 tags = webextensions
 [browser_addons_debug_webextension_nobg.js]
 tags = webextensions
 [browser_addons_debug_webextension_popup.js]
+skip-if = coverage # Bug 1387827
 tags = webextensions
 [browser_addons_debugging_initial_state.js]
 [browser_addons_install.js]
 [browser_addons_reload.js]
 [browser_addons_remove.js]
 [browser_addons_toggle_debug.js]
 [browser_page_not_found.js]
 [browser_service_workers.js]
--- a/devtools/client/framework/test/browser.ini
+++ b/devtools/client/framework/test/browser.ini
@@ -43,16 +43,17 @@ support-files =
   browser_toolbox_options_enable_serviceworkers_testing.html
   serviceworker.js
   sjs_code_reload.sjs
   sjs_code_bundle_reload_map.sjs
   test_browser_toolbox_debugger.js
   !/devtools/client/debugger/new/test/mochitest/head.js
 
 [browser_browser_toolbox.js]
+skip-if = coverage # Bug 1387827
 [browser_browser_toolbox_debugger.js]
 skip-if = debug # Bug 1282269
 [browser_devtools_api.js]
 [browser_devtools_api_destroy.js]
 [browser_dynamic_tool_enabling.js]
 [browser_ignore_toolbox_network_requests.js]
 [browser_keybindings_01.js]
 [browser_keybindings_02.js]
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -21,16 +21,17 @@
 #include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/workers/ServiceWorkerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/ResultExtensions.h"
 #include "mozilla/Services.h"
 #include "mozilla/StartupTimeline.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Unused.h"
 #include "Navigator.h"
 #include "URIUtils.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/TabGroup.h"
@@ -451,33 +452,23 @@ nsPingListener::~nsPingListener()
   }
 }
 
 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->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;
+  return NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+                                     OnPingTimeout,
+                                     mLoadGroup,
+                                     PING_TIMEOUT,
+                                     nsITimer::TYPE_ONE_SHOT,
+                                     "nsPingListener::StartTimeout",
+                                     aDocGroup->EventTargetFor(TaskCategory::Network));
 }
 
 NS_IMETHODIMP
 nsPingListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
 {
   return NS_OK;
 }
 
@@ -6853,24 +6844,25 @@ nsDocShell::RefreshURI(nsIURI* aURI, int
 
   if (busyFlags & BUSY_FLAGS_BUSY || (!mIsActive && mDisableMetaRefreshWhenInactive)) {
     // We don't  want to create the timer right now. Instead queue up the request
     // and trigger the timer in EndPageLoad() or whenever we become active.
     mRefreshURIList->AppendElement(refreshTimer, /*weak =*/ false);
   } else {
     // There is no page loading going on right now.  Create the
     // timer and fire it right away.
-    nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
-    NS_ENSURE_TRUE(timer, NS_ERROR_FAILURE);
     nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
     NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
 
+    nsCOMPtr<nsITimer> timer;
+    MOZ_TRY_VAR(timer,
+                NS_NewTimerWithCallback(refreshTimer, aDelay, nsITimer::TYPE_ONE_SHOT,
+                                        win->TabGroup()->EventTargetFor(TaskCategory::Network)));
+
     mRefreshURIList->AppendElement(timer, /*weak =*/ false);  // owning timer ref
-    timer->SetTarget(win->TabGroup()->EventTargetFor(TaskCategory::Network));
-    timer->InitWithCallback(refreshTimer, aDelay, nsITimer::TYPE_ONE_SHOT);
   }
   return NS_OK;
 }
 
 nsresult
 nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
                                      int32_t aDelay,
                                      bool aMetaRefresh,
@@ -7340,26 +7332,30 @@ nsDocShell::RefreshURIFromQueue()
 
     if (refreshInfo) {
       // This is the nsRefreshTimer object, waiting to be
       // setup in a timer object and fired.
       // Create the timer and  trigger it.
       uint32_t delay =
         static_cast<nsRefreshTimer*>(
           static_cast<nsITimerCallback*>(refreshInfo))->GetDelay();
-      nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
       nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
-      if (timer && win) {
-        // Replace the nsRefreshTimer element in the queue with
-        // its corresponding timer object, so that in case another
-        // load comes through before the timer can go off, the timer will
-        // get cancelled in CancelRefreshURITimer()
-        mRefreshURIList->ReplaceElementAt(timer, n, /*weak =*/ false);
-        timer->SetTarget(win->TabGroup()->EventTargetFor(TaskCategory::Network));
-        timer->InitWithCallback(refreshInfo, delay, nsITimer::TYPE_ONE_SHOT);
+      if (win) {
+        nsCOMPtr<nsITimer> timer;
+        NS_NewTimerWithCallback(getter_AddRefs(timer),
+                                refreshInfo, delay, nsITimer::TYPE_ONE_SHOT,
+                                win->TabGroup()->EventTargetFor(TaskCategory::Network));
+
+        if (timer) {
+          // Replace the nsRefreshTimer element in the queue with
+          // its corresponding timer object, so that in case another
+          // load comes through before the timer can go off, the timer will
+          // get cancelled in CancelRefreshURITimer()
+          mRefreshURIList->ReplaceElementAt(timer, n, /*weak =*/ false);
+        }
       }
     }
   }
 
   return NS_OK;
 }
 
 //*****************************************************************************
--- a/docshell/base/nsDocShellTreeOwner.cpp
+++ b/docshell/base/nsDocShellTreeOwner.cpp
@@ -1239,40 +1239,41 @@ ChromeTooltipListener::MouseMove(nsIDOME
   mouseEvent->GetScreenX(&mMouseScreenX);
   mouseEvent->GetScreenY(&mMouseScreenY);
 
   if (mTooltipTimer) {
     mTooltipTimer->Cancel();
   }
 
   if (!mShowingTooltip && !mTooltipShownOnce) {
-    mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
-    if (mTooltipTimer) {
-      nsCOMPtr<EventTarget> eventTarget =
-        aMouseEvent->InternalDOMEvent()->GetTarget();
-      if (eventTarget) {
-        mPossibleTooltipNode = do_QueryInterface(eventTarget);
-        nsCOMPtr<nsIGlobalObject> global(eventTarget->GetOwnerGlobal());
-        if (global) {
-          mTooltipTimer->SetTarget(global->EventTargetFor(TaskCategory::UI));
-        }
+    nsIEventTarget* target = nullptr;
+
+    nsCOMPtr<EventTarget> eventTarget =
+      aMouseEvent->InternalDOMEvent()->GetTarget();
+    if (eventTarget) {
+      mPossibleTooltipNode = do_QueryInterface(eventTarget);
+      nsCOMPtr<nsIGlobalObject> global(eventTarget->GetOwnerGlobal());
+      if (global) {
+        target = global->EventTargetFor(TaskCategory::UI);
       }
-      if (mPossibleTooltipNode) {
-        nsresult rv = mTooltipTimer->InitWithNamedFuncCallback(
-          sTooltipCallback,
-          this,
-          LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
-          nsITimer::TYPE_ONE_SHOT,
-          "ChromeTooltipListener::MouseMove");
-        if (NS_FAILED(rv)) {
-          mPossibleTooltipNode = nullptr;
-        }
+    }
+
+    if (mPossibleTooltipNode) {
+      nsresult rv = NS_NewTimerWithFuncCallback(
+        getter_AddRefs(mTooltipTimer),
+        sTooltipCallback,
+        this,
+        LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
+        nsITimer::TYPE_ONE_SHOT,
+        "ChromeTooltipListener::MouseMove",
+        target);
+      if (NS_FAILED(rv)) {
+        mPossibleTooltipNode = nullptr;
+        NS_WARNING("Could not create a timer for tooltip tracking");
       }
-    } else {
-      NS_WARNING("Could not create a timer for tooltip tracking");
     }
   } else {
     mTooltipShownOnce = true;
     return HideTooltip();
   }
 
   return NS_OK;
 }
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -314,21 +314,19 @@ namespace {
       SetDeadline(TimeStamp::Now());
       return Run();
     }
 
     void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) override
     {
       MOZ_ASSERT(aTarget);
       MOZ_ASSERT(!mTimer);
-      mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-      if (mTimer) {
-        mTimer->SetTarget(aTarget);
-        mTimer->InitWithCallback(this, aDelay, nsITimer::TYPE_ONE_SHOT);
-      }
+      NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                              this, aDelay, nsITimer::TYPE_ONE_SHOT,
+                              aTarget);
     }
 
   protected:
     virtual ~IdleDispatchRunnable()
     {
       CancelTimer();
     }
 
--- a/dom/base/EventSource.cpp
+++ b/dom/base/EventSource.cpp
@@ -1197,17 +1197,17 @@ EventSourceImpl::SetReconnectionTimeout(
 {
   AssertIsOnMainThread();
   if (IsClosed()) {
     return NS_ERROR_ABORT;
   }
 
   // the timer will be used whenever the requests are going finished.
   if (!mTimer) {
-    mTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mTimer = NS_NewTimer();
     NS_ENSURE_STATE(mTimer);
   }
 
   nsresult rv = mTimer->InitWithNamedFuncCallback(
     TimerCallback,
     this,
     mReconnectionTime,
     nsITimer::TYPE_ONE_SHOT,
--- a/dom/base/Selection.cpp
+++ b/dom/base/Selection.cpp
@@ -172,23 +172,21 @@ public:
 
     // Store the presentation context. The timer will be
     // stopped by the selection if the prescontext is destroyed.
     mPresContext = aPresContext;
 
     mContent = nsIPresShell::GetCapturingContent();
 
     if (!mTimer) {
-      nsresult result;
-      mTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
-      mTimer->SetTarget(
+      mTimer = NS_NewTimer(
         mPresContext->Document()->EventTargetFor(TaskCategory::Other));
 
-      if (NS_FAILED(result)) {
-        return result;
+      if (!mTimer) {
+        return NS_ERROR_OUT_OF_MEMORY;
       }
     }
 
     return mTimer->InitWithCallback(this, mDelay, nsITimer::TYPE_ONE_SHOT);
   }
 
   nsresult Stop()
   {
--- a/dom/base/TimeoutExecutor.cpp
+++ b/dom/base/TimeoutExecutor.cpp
@@ -50,18 +50,18 @@ TimeoutExecutor::ScheduleDelayed(const T
   MOZ_DIAGNOSTIC_ASSERT(mDeadline.IsNull());
   MOZ_DIAGNOSTIC_ASSERT(mMode == Mode::None);
   MOZ_DIAGNOSTIC_ASSERT(!aMinDelay.IsZero() ||
                         aDeadline > (aNow + mAllowedEarlyFiringTime));
 
   nsresult rv = NS_OK;
 
   if (!mTimer) {
-    mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    mTimer = NS_NewTimer();
+    NS_ENSURE_TRUE(mTimer, NS_ERROR_OUT_OF_MEMORY);
 
     uint32_t earlyMicros = 0;
     MOZ_ALWAYS_SUCCEEDS(mTimer->GetAllowedEarlyFiringMicroseconds(&earlyMicros));
     mAllowedEarlyFiringTime = TimeDuration::FromMicroseconds(earlyMicros);
   }
 
   // Always call Cancel() in case we are re-using a timer.  Otherwise
   // the subsequent SetTarget() may fail.
--- a/dom/base/TimeoutManager.cpp
+++ b/dom/base/TimeoutManager.cpp
@@ -1304,29 +1304,22 @@ TimeoutManager::MaybeStartThrottleTimeou
   }
 
   MOZ_DIAGNOSTIC_ASSERT(!mThrottleTimeouts);
 
   MOZ_LOG(gLog, LogLevel::Debug,
           ("TimeoutManager %p delaying tracking timeout throttling by %dms\n",
            this, gTimeoutThrottlingDelay));
 
-  mThrottleTimeoutsTimer =
-    do_CreateInstance("@mozilla.org/timer;1");
-  if (!mThrottleTimeoutsTimer) {
-    return;
-  }
-
   nsCOMPtr<nsITimerCallback> callback =
     new ThrottleTimeoutsCallback(&mWindow);
 
-  mThrottleTimeoutsTimer->SetTarget(EventTarget());
-
-  mThrottleTimeoutsTimer->InitWithCallback(
-    callback, gTimeoutThrottlingDelay, nsITimer::TYPE_ONE_SHOT);
+  NS_NewTimerWithCallback(getter_AddRefs(mThrottleTimeoutsTimer),
+                          callback, gTimeoutThrottlingDelay, nsITimer::TYPE_ONE_SHOT,
+                          EventTarget());
 }
 
 void
 TimeoutManager::BeginSyncOperation()
 {
   // If we're beginning a sync operation, the currently running
   // timeout will be put on hold. To not get into an inconsistent
   // state, where the currently running timeout appears to take time
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -1397,30 +1397,24 @@ nsContentSink::WillInterruptImpl()
         }
       } else if (!mNotificationTimer) {
         interval -= diff;
         int32_t delay = interval;
 
         // Convert to milliseconds
         delay /= PR_USEC_PER_MSEC;
 
-        mNotificationTimer = do_CreateInstance("@mozilla.org/timer;1",
-                                               &result);
-        if (NS_SUCCEEDED(result)) {
+        NS_NewTimerWithCallback(getter_AddRefs(mNotificationTimer),
+                                this, delay,
+                                nsITimer::TYPE_ONE_SHOT);
+        if (mNotificationTimer) {
           SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
                      SINK_TRACE_REFLOW,
                      ("nsContentSink::WillInterrupt: setting up timer with "
                       "delay %d", delay));
-
-          result =
-            mNotificationTimer->InitWithCallback(this, delay,
-                                                 nsITimer::TYPE_ONE_SHOT);
-          if (NS_FAILED(result)) {
-            mNotificationTimer = nullptr;
-          }
         }
       }
     }
   } else {
     SINK_TRACE(static_cast<LogModule*>(gContentSinkLogModuleInfo),
                SINK_TRACE_REFLOW,
                ("nsContentSink::WillInterrupt: flushing tags "
                 "unconditionally"));
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7093,20 +7093,20 @@ FullscreenTransitionTask::Run()
     // 2. the user has switched to another tab before we get here.
     // Completely fixing those cases seems to be tricky, and since they
     // should rarely happen, it probably isn't worth to fix. Hence we
     // simply add a timeout here to ensure we never hang forever.
     // In addition, if the page is complicated or the machine is less
     // powerful, layout could take a long time, in which case, staying
     // in black screen for that long could hurt user experience even
     // more than exposing an intermediate state.
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     uint32_t timeout =
       Preferences::GetUint("full-screen-api.transition.timeout", 1000);
-    mTimer->Init(observer, timeout, nsITimer::TYPE_ONE_SHOT);
+    NS_NewTimerWithObserver(getter_AddRefs(mTimer),
+                            observer, timeout, nsITimer::TYPE_ONE_SHOT);
   } else if (stage == eAfterToggle) {
     Telemetry::AccumulateTimeDelta(Telemetry::FULLSCREEN_TRANSITION_BLACK_MS,
                                    mFullscreenChangeStartTime);
     mWidget->PerformFullscreenTransition(nsIWidget::eAfterFullscreenToggle,
                                          mDuration.mFadeOut, mTransitionData,
                                          this);
   } else if (stage == eEnd) {
     PROFILER_ADD_MARKER("Fullscreen transition end");
@@ -12012,18 +12012,18 @@ nsGlobalWindow::RegisterIdleObserver(nsI
   if (mIdleObservers.IsEmpty()) {
     mIdleService = do_GetService("@mozilla.org/widget/idleservice;1", &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = mIdleService->AddIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!mIdleTimer) {
-      mIdleTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-      NS_ENSURE_SUCCESS(rv, rv);
+      mIdleTimer = NS_NewTimer();
+      NS_ENSURE_TRUE(mIdleTimer, NS_ERROR_OUT_OF_MEMORY);
     } else {
       mIdleTimer->Cancel();
     }
   }
 
   MOZ_ASSERT(mIdleService);
   MOZ_ASSERT(mIdleTimer);
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2110,59 +2110,47 @@ nsJSContext::PokeGC(JS::gcreason::Reason
 
   if (sICCRunner) {
     // Make sure GC is called after the current CC completes.
     // No need to set sNeedsFullCC because we are currently running a CC.
     sNeedsGCAfterCC = true;
     return;
   }
 
-  CallCreateInstance("@mozilla.org/timer;1", &sGCTimer);
-
-  if (!sGCTimer) {
-    // Failed to create timer (probably because we're in XPCOM shutdown)
-    return;
-  }
-
   static bool first = true;
 
-  sGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
-  sGCTimer->InitWithNamedFuncCallback(GCTimerFired,
-                                      reinterpret_cast<void *>(aReason),
-                                      aDelay
-                                      ? aDelay
-                                      : (first
-                                         ? NS_FIRST_GC_DELAY
-                                         : NS_GC_DELAY),
-                                      nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
-                                      "GCTimerFired");
+  NS_NewTimerWithFuncCallback(&sGCTimer,
+                              GCTimerFired,
+                              reinterpret_cast<void *>(aReason),
+                              aDelay
+                              ? aDelay
+                              : (first
+                                 ? NS_FIRST_GC_DELAY
+                                 : NS_GC_DELAY),
+                              nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
+                              "GCTimerFired",
+                              SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
 
   first = false;
 }
 
 // static
 void
 nsJSContext::PokeShrinkingGC()
 {
   if (sShrinkingGCTimer || sShuttingDown) {
     return;
   }
 
-  CallCreateInstance("@mozilla.org/timer;1", &sShrinkingGCTimer);
-
-  if (!sShrinkingGCTimer) {
-    // Failed to create timer (probably because we're in XPCOM shutdown)
-    return;
-  }
-
-  sShrinkingGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
-  sShrinkingGCTimer->InitWithNamedFuncCallback(ShrinkingGCTimerFired, nullptr,
-                                               sCompactOnUserInactiveDelay,
-                                               nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
-                                               "ShrinkingGCTimerFired");
+  NS_NewTimerWithFuncCallback(&sShrinkingGCTimer,
+                              ShrinkingGCTimerFired, nullptr,
+                              sCompactOnUserInactiveDelay,
+                              nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
+                              "ShrinkingGCTimerFired",
+                              SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
 }
 
 // static
 void
 nsJSContext::MaybePokeCC()
 {
   if (sCCRunner || sICCRunner || sShuttingDown || !sHasRunGC) {
     return;
@@ -2330,23 +2318,23 @@ DOMGCSliceCallback(JSContext* aCx, JS::G
       sLikelyShortLivingObjectsNeedingGC = 0;
       sCleanupsSinceLastGC = 0;
       sNeedsFullCC = true;
       sHasRunGC = true;
       nsJSContext::MaybePokeCC();
 
       if (aDesc.isZone_) {
         if (!sFullGCTimer && !sShuttingDown) {
-          CallCreateInstance("@mozilla.org/timer;1", &sFullGCTimer);
-          sFullGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
-          sFullGCTimer->InitWithNamedFuncCallback(FullGCTimerFired,
-                                                  nullptr,
-                                                  NS_FULL_GC_DELAY,
-                                                  nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
-                                                  "FullGCTimerFired");
+          NS_NewTimerWithFuncCallback(&sFullGCTimer,
+                                      FullGCTimerFired,
+                                      nullptr,
+                                      NS_FULL_GC_DELAY,
+                                      nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
+                                      "FullGCTimerFired",
+                                      SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
         }
       } else {
         nsJSContext::KillFullGCTimer();
       }
 
       if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
         nsCycleCollector_dispatchDeferredDeletion();
       }
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -822,23 +822,20 @@ nsWindowMemoryReporter::AsyncCheckForGho
   // If more than kTimeBetweenChecks seconds have elapsed since the last check,
   // timerDelay is 0.  Otherwise, it is kTimeBetweenChecks, reduced by the time
   // since the last check.  Reducing the delay by the time since the last check
   // prevents the timer from being completely starved if it is repeatedly killed
   // and restarted.
   int32_t timeSinceLastCheck = (TimeStamp::NowLoRes() - mLastCheckForGhostWindows).ToSeconds();
   int32_t timerDelay = (kTimeBetweenChecks - std::min(timeSinceLastCheck, kTimeBetweenChecks)) * PR_MSEC_PER_SEC;
 
-  mCheckTimer = do_CreateInstance("@mozilla.org/timer;1");
-
-  if (mCheckTimer) {
-    mCheckTimer->InitWithNamedFuncCallback(CheckTimerFired, nullptr,
-                                           timerDelay, nsITimer::TYPE_ONE_SHOT,
-                                           "nsWindowMemoryReporter::AsyncCheckForGhostWindows_timer");
-  }
+  NS_NewTimerWithFuncCallback(getter_AddRefs(mCheckTimer),
+                              CheckTimerFired, nullptr,
+                              timerDelay, nsITimer::TYPE_ONE_SHOT,
+                              "nsWindowMemoryReporter::AsyncCheckForGhostWindows_timer");
 }
 
 void
 nsWindowMemoryReporter::ObserveAfterMinimizeMemoryUsage()
 {
   // Someone claims they've done enough GC/CCs so that all eligible windows
   // have been free'd.  So we deem that any windows which satisfy ghost
   // criteria (1) and (2) now satisfy criterion (3) as well.
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -253,16 +253,17 @@ support-files =
 
 [test_anchor_area_referrer.html]
 [test_anchor_area_referrer_changing.html]
 [test_anchor_area_referrer_invalid.html]
 [test_anchor_area_referrer_rel.html]
 [test_anonymousContent_api.html]
 [test_anonymousContent_append_after_reflow.html]
 [test_anonymousContent_canvas.html]
+skip-if = headless # Bug 1405867
 [test_anonymousContent_insert.html]
 [test_anonymousContent_manipulate_content.html]
 [test_anonymousContent_style_csp.html]
 [test_appname_override.html]
 [test_async_setTimeout_stack.html]
 [test_async_setTimeout_stack_across_globals.html]
 [test_audioWindowUtils.html]
 [test_audioNotification.html]
@@ -301,17 +302,17 @@ skip-if = toolkit == 'android'
 [test_bug311681.xml]
 [test_bug313646.html]
 [test_bug320799.html]
 [test_bug322317.html]
 [test_bug326337.html]
 [test_bug330925.xhtml]
 [test_bug331959.html]
 [test_bug333064.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || headless # Headless: Bug 1405868
 [test_bug333198.html]
 [test_bug333673.html]
 [test_bug337631.html]
 [test_bug338541.xhtml]
 [test_bug338583.html]
 skip-if = toolkit == 'android'
 [test_bug338679.html]
 [test_bug339494.html]
--- a/dom/cache/FileUtils.cpp
+++ b/dom/cache/FileUtils.cpp
@@ -6,18 +6,18 @@
 
 #include "mozilla/dom/cache/FileUtils.h"
 
 #include "mozilla/dom/InternalResponse.h"
 #include "mozilla/dom/quota/FileStreams.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/SnappyCompressOutputStream.h"
 #include "mozilla/Unused.h"
-#include "nsIBinaryInputStream.h"
-#include "nsIBinaryOutputStream.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
 #include "nsIFile.h"
 #include "nsIUUIDGenerator.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsISimpleEnumerator.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
@@ -415,24 +415,20 @@ LockedDirectoryPaddingWrite(nsIFile* aBa
     rv = file->Append(NS_LITERAL_STRING(PADDING_FILE_NAME));
   }
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   nsCOMPtr<nsIOutputStream> outputStream;
   rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  nsCOMPtr<nsIBinaryOutputStream> binaryStream =
-    do_CreateInstance("@mozilla.org/binaryoutputstream;1");
-  if (NS_WARN_IF(!binaryStream)) { return NS_ERROR_FAILURE; }
+  nsCOMPtr<nsIObjectOutputStream> objectStream =
+    NS_NewObjectOutputStream(outputStream);
 
-  rv = binaryStream->SetOutputStream(outputStream);
-  if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
-
-  rv = binaryStream->Write64(aPaddingSize);
+  rv = objectStream->Write64(aPaddingSize);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   return rv;
 }
 
 } // namespace
 
 nsresult
@@ -739,25 +735,21 @@ LockedDirectoryPaddingGet(nsIFile* aBase
   nsCOMPtr<nsIInputStream> stream;
   rv = NS_NewLocalFileInputStream(getter_AddRefs(stream), file);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   nsCOMPtr<nsIInputStream> bufferedStream;
   rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream), stream, 512);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  nsCOMPtr<nsIBinaryInputStream> binaryStream =
-    do_CreateInstance("@mozilla.org/binaryinputstream;1");
-  if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
-
-  rv = binaryStream->SetInputStream(bufferedStream);
-  if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
+  nsCOMPtr<nsIObjectInputStream> objectStream =
+    NS_NewObjectInputStream(bufferedStream);
 
   uint64_t paddingSize = 0;
-  rv = binaryStream->Read64(&paddingSize);
+  rv = objectStream->Read64(&paddingSize);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   *aPaddingSizeOut = paddingSize;
 
   return rv;
 }
 
 // static
--- a/dom/canvas/WebGLContextLossHandler.cpp
+++ b/dom/canvas/WebGLContextLossHandler.cpp
@@ -44,17 +44,17 @@ private:
 };
 
 NS_IMPL_ISUPPORTS(WatchdogTimerEvent, nsITimerCallback, nsINamed)
 
 ////////////////////////////////////////
 
 WebGLContextLossHandler::WebGLContextLossHandler(WebGLContext* webgl)
     : mWebGL(webgl)
-    , mTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
+    , mTimer(NS_NewTimer())
     , mTimerPending(false)
     , mShouldRunTimerAgain(false)
 #ifdef DEBUG
     , mEventTarget(GetCurrentThreadSerialEventTarget())
 #endif
 {
     MOZ_ASSERT(mEventTarget);
 }
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -14,18 +14,18 @@
 #include "nsIScriptSecurityManager.h"
 #include "mozilla/dom/DOMStringList.h"
 #include "nsArray.h"
 #include "nsError.h"
 #include "nsIDragService.h"
 #include "nsIClipboard.h"
 #include "nsContentUtils.h"
 #include "nsIContent.h"
-#include "nsIBinaryInputStream.h"
-#include "nsIBinaryOutputStream.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
 #include "nsIStorageStream.h"
 #include "nsStringStream.h"
 #include "nsCRT.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIDocument.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsVariant.h"
@@ -991,17 +991,17 @@ DataTransfer::GetTransferable(uint32_t a
   nsCOMPtr<nsITransferable> transferable =
     do_CreateInstance("@mozilla.org/widget/transferable;1");
   if (!transferable) {
     return nullptr;
   }
   transferable->Init(aLoadContext);
 
   nsCOMPtr<nsIStorageStream> storageStream;
-  nsCOMPtr<nsIBinaryOutputStream> stream;
+  nsCOMPtr<nsIObjectOutputStream> stream;
 
   bool added = false;
   bool handlingCustomFormats = true;
 
   // When writing the custom data, we need to ensure that there is sufficient
   // space for a (uint32_t) data ending type, and the null byte character at
   // the end of the nsCString. We claim that space upfront and store it in
   // baseLength. This value will be set to zero if a write error occurs
@@ -1082,18 +1082,17 @@ DataTransfer::GetTransferable(uint32_t a
 
             if (!stream) {
               // Create a storage stream to write to.
               NS_NewStorageStream(1024, UINT32_MAX, getter_AddRefs(storageStream));
 
               nsCOMPtr<nsIOutputStream> outputStream;
               storageStream->GetOutputStream(0, getter_AddRefs(outputStream));
 
-              stream = do_CreateInstance("@mozilla.org/binaryoutputstream;1");
-              stream->SetOutputStream(outputStream);
+              stream = NS_NewObjectOutputStream(outputStream);
             }
 
             CheckedInt<uint32_t> formatLength =
               CheckedInt<uint32_t>(type.Length()) * sizeof(nsString::char_type);
 
             // The total size of the stream is the format length, the data
             // length, two integers to hold the lengths and one integer for
             // the string flag. Guard against large data by ignoring any that
@@ -1588,24 +1587,18 @@ DataTransfer::FillInExternalCustomTypes(
   }
 
   nsAutoCString str;
   str.Adopt(chrs, len);
 
   nsCOMPtr<nsIInputStream> stringStream;
   NS_NewCStringInputStream(getter_AddRefs(stringStream), str);
 
-  nsCOMPtr<nsIBinaryInputStream> stream =
-    do_CreateInstance("@mozilla.org/binaryinputstream;1");
-  if (!stream) {
-    return;
-  }
-
-  rv = stream->SetInputStream(stringStream);
-  NS_ENSURE_SUCCESS_VOID(rv);
+  nsCOMPtr<nsIObjectInputStream> stream =
+    NS_NewObjectInputStream(stringStream);
 
   uint32_t type;
   do {
     rv = stream->Read32(&type);
     NS_ENSURE_SUCCESS_VOID(rv);
     if (type == eCustomClipboardTypeId_String) {
       uint32_t formatLength;
       rv = stream->Read32(&formatLength);
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -314,21 +314,18 @@ EventStateManager::EventStateManager()
 
 nsresult
 EventStateManager::UpdateUserActivityTimer()
 {
   if (!gUserInteractionTimerCallback)
     return NS_OK;
 
   if (!gUserInteractionTimer) {
-    CallCreateInstance("@mozilla.org/timer;1", &gUserInteractionTimer);
-    if (gUserInteractionTimer) {
-      gUserInteractionTimer->SetTarget(
-        SystemGroup::EventTargetFor(TaskCategory::Other));
-    }
+    gUserInteractionTimer = NS_NewTimer(
+      SystemGroup::EventTargetFor(TaskCategory::Other)).take();
   }
 
   if (gUserInteractionTimer) {
     gUserInteractionTimer->InitWithCallback(gUserInteractionTimerCallback,
                                             NS_USER_INTERACTION_INTERVAL,
                                             nsITimer::TYPE_ONE_SHOT);
   }
   return NS_OK;
@@ -1449,28 +1446,25 @@ EventStateManager::CreateClickHoldTimer(
                                         nsGkAtoms::popup))
       return;
 
     // check for a <menubutton> like bookmarks
     if (mGestureDownContent->IsXULElement(nsGkAtoms::menubutton))
       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->InitWithNamedFuncCallback(
-      sClickHoldCallback,
-      this,
-      clickHoldDelay,
-      nsITimer::TYPE_ONE_SHOT,
-      "EventStateManager::CreateClickHoldTimer");
-  }
+  int32_t clickHoldDelay =
+    Preferences::GetInt("ui.click_hold_context_menus.delay", 500);
+  NS_NewTimerWithFuncCallback(getter_AddRefs(mClickHoldTimer),
+                              sClickHoldCallback,
+                              this,
+                              clickHoldDelay,
+                              nsITimer::TYPE_ONE_SHOT,
+                              "EventStateManager::CreateClickHoldTimer",
+                              SystemGroup::EventTargetFor(TaskCategory::Other));
 } // CreateClickHoldTimer
 
 //
 // KillClickHoldTimer
 //
 // Stop the timer that would show the context menu dead in its tracks
 //
 void
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -319,21 +319,20 @@ WheelTransaction::OnTimeout(nsITimer* aT
                       true, true);
   }
 }
 
 /* static */ void
 WheelTransaction::SetTimeout()
 {
   if (!sTimer) {
-    nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (!timer) {
+    sTimer = NS_NewTimer().take();
+    if (!sTimer) {
       return;
     }
-    timer.swap(sTimer);
   }
   sTimer->Cancel();
   DebugOnly<nsresult> rv =
     sTimer->InitWithNamedFuncCallback(OnTimeout,
                                       nullptr,
                                       GetTimeoutTime(),
                                       nsITimer::TYPE_ONE_SHOT,
                                       "WheelTransaction::SetTimeout");
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -170,16 +170,17 @@ skip-if = toolkit == 'android' #CRASH_DU
 [test_legacy_event.html]
 [test_messageEvent.html]
 [test_messageEvent_init.html]
 [test_moz_mouse_pixel_scroll_event.html]
 [test_offsetxy.html]
 [test_onerror_handler_args.html]
 [test_passive_listeners.html]
 [test_paste_image.html]
+skip-if = headless # Bug 1405869
 [test_wheel_default_action.html]
 [test_bug687787.html]
 [test_bug1305458.html]
 [test_bug1298970.html]
 [test_bug1304044.html]
 [test_bug1332699.html]
 [test_bug1339758.html]
 [test_bug1369072.html]
--- a/dom/file/FileReader.cpp
+++ b/dom/file/FileReader.cpp
@@ -524,17 +524,17 @@ FileReader::WrapObject(JSContext* aCx, J
 {
   return FileReaderBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 FileReader::StartProgressEventTimer()
 {
   if (!mProgressNotifier) {
-    mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mProgressNotifier = NS_NewTimer();
   }
 
   if (mProgressNotifier) {
     mProgressEventWasDelayed = false;
     mTimerIsActive = true;
     mProgressNotifier->Cancel();
     mProgressNotifier->SetTarget(mTarget);
     mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
--- a/dom/file/nsHostObjectProtocolHandler.cpp
+++ b/dom/file/nsHostObjectProtocolHandler.cpp
@@ -429,28 +429,20 @@ class ReleasingTimerHolder final : publi
 {
 public:
   NS_DECL_ISUPPORTS
 
   static void
   Create(nsTArray<nsWeakPtr>&& aArray)
   {
     RefPtr<ReleasingTimerHolder> holder = new ReleasingTimerHolder(Move(aArray));
-    holder->mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-
-    // If we are shutting down, we are not able to create a timer.
-    if (!holder->mTimer) {
-      return;
-    }
-
-    MOZ_ALWAYS_SUCCEEDS(holder->mTimer->SetTarget(
-      SystemGroup::EventTargetFor(TaskCategory::Other)));
-
-    nsresult rv = holder->mTimer->InitWithCallback(holder, RELEASING_TIMER,
-                                                   nsITimer::TYPE_ONE_SHOT);
+    nsresult rv = NS_NewTimerWithCallback(getter_AddRefs(holder->mTimer),
+                                          holder, RELEASING_TIMER,
+                                          nsITimer::TYPE_ONE_SHOT,
+                                          SystemGroup::EventTargetFor(TaskCategory::Other));
     NS_ENSURE_SUCCESS_VOID(rv);
   }
 
   NS_IMETHOD
   Notify(nsITimer* aTimer) override
   {
     for (uint32_t i = 0; i < mURIs.Length(); ++i) {
       nsCOMPtr<nsIURI> uri = do_QueryReferent(mURIs[i]);
--- a/dom/flyweb/FlyWebService.cpp
+++ b/dom/flyweb/FlyWebService.cpp
@@ -665,22 +665,22 @@ FlyWebMDNSService::Notify(nsITimer* time
   return NS_OK;
 }
 
 nsresult
 FlyWebMDNSService::Init()
 {
   MOZ_ASSERT(mDiscoveryState == DISCOVERY_IDLE);
 
-  mDiscoveryStartTimer = do_CreateInstance("@mozilla.org/timer;1");
+  mDiscoveryStartTimer = NS_NewTimer();
   if (!mDiscoveryStartTimer) {
     return NS_ERROR_FAILURE;
   }
 
-  mDiscoveryStopTimer = do_CreateInstance("@mozilla.org/timer;1");
+  mDiscoveryStopTimer = NS_NewTimer();
   if (!mDiscoveryStopTimer) {
     return NS_ERROR_FAILURE;
   }
 
   nsresult rv;
   mDNSServiceDiscovery = do_GetService(DNSSERVICEDISCOVERY_CONTRACT_ID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
--- a/dom/gamepad/windows/WindowsGamepad.cpp
+++ b/dom/gamepad/windows/WindowsGamepad.cpp
@@ -349,19 +349,19 @@ DirectInputMessageLoopOnceCallback(nsITi
   }
 }
 
 class WindowsGamepadService
 {
  public:
   WindowsGamepadService()
   {
-    mDirectInputTimer = do_CreateInstance("@mozilla.org/timer;1");
-    mXInputTimer = do_CreateInstance("@mozilla.org/timer;1");
-    mDeviceChangeTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mDirectInputTimer = NS_NewTimer();
+    mXInputTimer = NS_NewTimer();
+    mDeviceChangeTimer = NS_NewTimer();
   }
   virtual ~WindowsGamepadService()
   {
     Cleanup();
   }
 
   void DevicesChanged(bool aIsStablizing);
 
--- a/dom/geolocation/MLSFallback.cpp
+++ b/dom/geolocation/MLSFallback.cpp
@@ -23,21 +23,18 @@ MLSFallback::~MLSFallback()
 nsresult
 MLSFallback::Startup(nsIGeolocationUpdate* aWatcher)
 {
   if (mHandoffTimer || mMLSFallbackProvider) {
     return NS_OK;
   }
 
   mUpdateWatcher = aWatcher;
-  nsresult rv;
-  mHandoffTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = mHandoffTimer->InitWithCallback(this, mDelayMs, nsITimer::TYPE_ONE_SHOT);
-  return rv;
+  return NS_NewTimerWithCallback(getter_AddRefs(mHandoffTimer),
+                                 this, mDelayMs, nsITimer::TYPE_ONE_SHOT);
 }
 
 nsresult
 MLSFallback::Shutdown()
 {
   mUpdateWatcher = nullptr;
 
   if (mHandoffTimer) {
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/nsGeolocation.cpp
@@ -517,19 +517,19 @@ nsGeolocationRequest::GetRequester(nsICo
 void
 nsGeolocationRequest::SetTimeoutTimer()
 {
   MOZ_ASSERT(!mShutdown, "set timeout after shutdown");
 
   StopTimeoutTimer();
 
   if (mOptions && mOptions->mTimeout != 0 && mOptions->mTimeout != 0x7fffffff) {
-    mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
     RefPtr<TimerCallbackHolder> holder = new TimerCallbackHolder(this);
-    mTimeoutTimer->InitWithCallback(holder, mOptions->mTimeout, nsITimer::TYPE_ONE_SHOT);
+    NS_NewTimerWithCallback(getter_AddRefs(mTimeoutTimer),
+                            holder, mOptions->mTimeout, nsITimer::TYPE_ONE_SHOT);
   }
 }
 
 void
 nsGeolocationRequest::StopTimeoutTimer()
 {
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
@@ -862,17 +862,17 @@ nsGeolocationService::StartDevice(nsIPri
 
   return NS_OK;
 }
 
 void
 nsGeolocationService::SetDisconnectTimer()
 {
   if (!mDisconnectTimer) {
-    mDisconnectTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mDisconnectTimer = NS_NewTimer();
   } else {
     mDisconnectTimer->Cancel();
   }
 
   mDisconnectTimer->Init(this,
                          sProviderTimeout,
                          nsITimer::TYPE_ONE_SHOT);
 }
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4575,22 +4575,21 @@ void HTMLMediaElement::VideoDecodeSuspen
 void HTMLMediaElement::HiddenVideoStart()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mHiddenPlayTime.Start();
   if (mVideoDecodeSuspendTimer) {
     // Already started, just keep it running.
     return;
   }
-  mVideoDecodeSuspendTimer = do_CreateInstance("@mozilla.org/timer;1");
-  mVideoDecodeSuspendTimer->SetTarget(mMainThreadEventTarget);
-  mVideoDecodeSuspendTimer->InitWithNamedFuncCallback(
-    VideoDecodeSuspendTimerCallback, this,
-    MediaPrefs::MDSMSuspendBackgroundVideoDelay(), nsITimer::TYPE_ONE_SHOT,
-    "HTMLMediaElement::VideoDecodeSuspendTimerCallback");
+  NS_NewTimerWithFuncCallback(getter_AddRefs(mVideoDecodeSuspendTimer),
+                              VideoDecodeSuspendTimerCallback, this,
+                              MediaPrefs::MDSMSuspendBackgroundVideoDelay(), nsITimer::TYPE_ONE_SHOT,
+                              "HTMLMediaElement::VideoDecodeSuspendTimerCallback",
+                              mMainThreadEventTarget);
 }
 
 void HTMLMediaElement::HiddenVideoStop()
 {
   MOZ_ASSERT(NS_IsMainThread());
   mHiddenPlayTime.Pause();
   mVideoDecodeSuspendTime.Pause();
   if (!mVideoDecodeSuspendTimer) {
@@ -5784,21 +5783,20 @@ void HTMLMediaElement::ProgressTimerCall
 }
 
 void HTMLMediaElement::StartProgressTimer()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING);
   NS_ASSERTION(!mProgressTimer, "Already started progress timer.");
 
-  mProgressTimer = do_CreateInstance("@mozilla.org/timer;1");
-  mProgressTimer->SetTarget(mMainThreadEventTarget);
-  mProgressTimer->InitWithNamedFuncCallback(
-    ProgressTimerCallback, this, PROGRESS_MS, nsITimer::TYPE_REPEATING_SLACK,
-    "HTMLMediaElement::ProgressTimerCallback");
+  NS_NewTimerWithFuncCallback(getter_AddRefs(mProgressTimer),
+                              ProgressTimerCallback, this, PROGRESS_MS, nsITimer::TYPE_REPEATING_SLACK,
+                              "HTMLMediaElement::ProgressTimerCallback",
+                              mMainThreadEventTarget);
 }
 
 void HTMLMediaElement::StartProgress()
 {
   // Record the time now for detecting stalled.
   mDataTime = TimeStamp::NowLoRes();
   // Reset mProgressTime so that mDataTime is not indicating bytes received
   // after the last progress event.
--- a/dom/html/nsHTMLDNSPrefetch.cpp
+++ b/dom/html/nsHTMLDNSPrefetch.cpp
@@ -273,17 +273,17 @@ nsHTMLDNSPrefetch::nsListener::OnLookupC
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLDNSPrefetch::nsDeferrals::nsDeferrals()
   : mHead(0),
     mTail(0),
     mActiveLoaderCount(0),
     mTimerArmed(false)
 {
-  mTimer = do_CreateInstance("@mozilla.org/timer;1");
+  mTimer = NS_NewTimer();;
 }
 
 nsHTMLDNSPrefetch::nsDeferrals::~nsDeferrals()
 {
   if (mTimerArmed) {
     mTimerArmed = false;
     mTimer->Cancel();
   }
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -11987,17 +11987,17 @@ DatabaseUpdateFunction::UpdateInternal(i
 }
 
 /*******************************************************************************
  * ConnectionPool implementation
  ******************************************************************************/
 
 ConnectionPool::ConnectionPool()
   : mDatabasesMutex("ConnectionPool::mDatabasesMutex")
-  , mIdleTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
+  , mIdleTimer(NS_NewTimer())
   , mNextTransactionId(0)
   , mTotalThreadCount(0)
   , mShutdownRequested(false)
   , mShutdownComplete(false)
 {
   AssertIsOnOwningThread();
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(mIdleTimer);
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -383,17 +383,17 @@ IndexedDatabaseManager::Init()
   if (sIsMainProcess) {
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     NS_ENSURE_STATE(obs);
 
     nsresult rv =
       obs->AddObserver(this, DISKSPACEWATCHER_OBSERVER_TOPIC, false);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    mDeleteTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mDeleteTimer = NS_NewTimer();
     NS_ENSURE_STATE(mDeleteTimer);
 
     if (QuotaManager* quotaManager = QuotaManager::Get()) {
       NoteLiveQuotaManager(quotaManager);
     }
   }
 
   Preferences::RegisterCallbackAndCall(AtomicBoolPrefChangedCallback,
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2945,24 +2945,23 @@ void
 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");
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
+                                ContentChild::ForceKillTimerCallback,
+                                this,
+                                timeoutSecs * 1000,
+                                nsITimer::TYPE_ONE_SHOT,
+                                "dom::ContentChild::StartForceKillTimer");
     MOZ_ASSERT(mForceKillTimer);
-    mForceKillTimer->InitWithNamedFuncCallback(
-      ContentChild::ForceKillTimerCallback,
-      this,
-      timeoutSecs * 1000,
-      nsITimer::TYPE_ONE_SHOT,
-      "dom::ContentChild::StartForceKillTimer");
   }
 }
 
 /* static */ void
 ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
 {
   ProcessChild::QuickExit();
 }
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1901,24 +1901,23 @@ void
 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");
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mForceKillTimer),
+                                ContentParent::ForceKillTimerCallback,
+                                this,
+                                timeoutSecs * 1000,
+                                nsITimer::TYPE_ONE_SHOT,
+                                "dom::ContentParent::StartForceKillTimer");
     MOZ_ASSERT(mForceKillTimer);
-    mForceKillTimer->InitWithNamedFuncCallback(
-      ContentParent::ForceKillTimerCallback,
-      this,
-      timeoutSecs * 1000,
-      nsITimer::TYPE_ONE_SHOT,
-      "dom::ContentParent::StartForceKillTimer");
   }
 }
 
 void
 ContentParent::NotifyTabDestroyed(const TabId& aTabId,
                                   bool aNotifiedDestroying)
 {
   if (aNotifiedDestroying) {
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -808,18 +808,18 @@ ParticularProcessPriorityManager::Schedu
       timeout = sBackgroundGracePeriodMS;
       break;
     default:
       MOZ_ASSERT(false, "Unrecognized timeout pref");
       break;
   }
 
   LOGP("Scheduling reset timer to fire in %dms.", timeout);
-  mResetPriorityTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  mResetPriorityTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
+  NS_NewTimerWithCallback(getter_AddRefs(mResetPriorityTimer),
+                          this, timeout, nsITimer::TYPE_ONE_SHOT);
 }
 
 NS_IMETHODIMP
 ParticularProcessPriorityManager::Notify(nsITimer* aTimer)
 {
   LOGP("Reset priority timer callback; about to ResetPriorityNow.");
   ResetPriorityNow();
   mResetPriorityTimer = nullptr;
--- a/dom/media/CanvasCaptureMediaStream.cpp
+++ b/dom/media/CanvasCaptureMediaStream.cpp
@@ -135,25 +135,22 @@ public:
     : OutputStreamDriver(aSourceStream, aTrackId, aPrincipalHandle)
     , mFPS(aFPS)
     , mTimer(nullptr)
   {
     if (mFPS == 0.0) {
       return;
     }
 
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (!mTimer) {
-      return;
-    }
-    mTimer->InitWithNamedFuncCallback(&TimerTick,
-                                      this,
-                                      int(1000 / mFPS),
-                                      nsITimer::TYPE_REPEATING_SLACK,
-                                      "dom::TimerDriver::TimerDriver");
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+                                &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
@@ -25,18 +25,17 @@ ChannelMediaDecoder::ResourceCallback::R
   MOZ_ASSERT(aMainThread);
 }
 
 void
 ChannelMediaDecoder::ResourceCallback::Connect(ChannelMediaDecoder* aDecoder)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mDecoder = aDecoder;
-  mTimer = do_CreateInstance("@mozilla.org/timer;1");
-  mTimer->SetTarget(mAbstractMainThread->AsEventTarget());
+  mTimer = NS_NewTimer(mAbstractMainThread->AsEventTarget());
 }
 
 void
 ChannelMediaDecoder::ResourceCallback::Disconnect()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mDecoder) {
     mDecoder = nullptr;
--- a/dom/media/MediaDevices.cpp
+++ b/dom/media/MediaDevices.cpp
@@ -229,17 +229,17 @@ MediaDevices::OnDeviceChange()
 
   if (!(MediaManager::Get()->IsActivelyCapturingOrHasAPermission(GetOwner()->WindowID()) ||
     Preferences::GetBool("media.navigator.permission.disabled", false))) {
     return;
   }
 
   if (!mFuzzTimer)
   {
-    mFuzzTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mFuzzTimer = NS_NewTimer();
   }
 
   if (!mFuzzTimer) {
     MOZ_ASSERT(false);
     return;
   }
 
   mFuzzTimer->Cancel();
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1497,23 +1497,20 @@ MediaStreamGraphImpl::ForceShutDown(medi
   LOG(LogLevel::Debug, ("MediaStreamGraph %p ForceShutdown", this));
 
   MonitorAutoLock lock(mMonitor);
   if (aShutdownTicket) {
     MOZ_ASSERT(!mForceShutdownTicket);
     // Avoid waiting forever for a graph to shut down
     // synchronously.  Reports are that some 3rd-party audio drivers
     // occasionally hang in shutdown (both for us and Chrome).
-    mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (!mShutdownTimer) {
-      return;
-    }
-    mShutdownTimer->InitWithCallback(this,
-                                     MediaStreamGraph::AUDIO_CALLBACK_DRIVER_SHUTDOWN_TIMEOUT,
-                                     nsITimer::TYPE_ONE_SHOT);
+    NS_NewTimerWithCallback(getter_AddRefs(mShutdownTimer),
+                            this,
+                            MediaStreamGraph::AUDIO_CALLBACK_DRIVER_SHUTDOWN_TIMEOUT,
+                            nsITimer::TYPE_ONE_SHOT);
   }
   mForceShutDown = true;
   mForceShutdownTicket = aShutdownTicket;
   if (mLifecycleState == LIFECYCLE_THREAD_NOT_STARTED) {
     // We *could* have just sent this a message to start up, so don't
     // yank the rug out from under it.  Tell it to startup and let it
     // shut down.
     RefPtr<GraphDriver> driver = CurrentDriver();
--- a/dom/media/MediaTimer.cpp
+++ b/dom/media/MediaTimer.cpp
@@ -15,17 +15,17 @@
 
 namespace mozilla {
 
 NS_IMPL_ADDREF(MediaTimer)
 NS_IMPL_RELEASE_WITH_DESTROY(MediaTimer, DispatchDestroy())
 
 MediaTimer::MediaTimer()
   : mMonitor("MediaTimer Monitor")
-  , mTimer(do_CreateInstance("@mozilla.org/timer;1"))
+  , mTimer(NS_NewTimer())
   , mCreationTimeStamp(TimeStamp::Now())
   , mUpdateScheduled(false)
 {
   TIMER_LOG("MediaTimer::MediaTimer");
 
   // Use the SharedThreadPool to create an nsIThreadPool with a maximum of one
   // thread, which is equivalent to an nsIThread for our purposes.
   RefPtr<SharedThreadPool> threadPool(
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -362,33 +362,23 @@ SimpleTimer::Init(nsIRunnable* aTask, ui
     target = aTarget;
   } else {
     target = GetMainThreadEventTarget();
     if (!target) {
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
-  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  // Note: set target before InitWithCallback in case the timer fires before
-  // we change the event target.
-  rv = timer->SetTarget(target);
-  if (NS_FAILED(rv)) {
-    timer->Cancel();
-    return rv;
-  }
-  rv = timer->InitWithCallback(this, aTimeoutMs, nsITimer::TYPE_ONE_SHOT);
+  rv = NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                               this, aTimeoutMs, nsITimer::TYPE_ONE_SHOT,
+                               target);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  mTimer = timer.forget();
   mTask = aTask;
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS(SimpleTimer, nsITimerCallback, nsINamed)
 
 already_AddRefed<SimpleTimer>
 SimpleTimer::Create(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIEventTarget* aTarget)
--- a/dom/media/doctor/DecoderDoctorDiagnostics.cpp
+++ b/dom/media/doctor/DecoderDoctorDiagnostics.cpp
@@ -222,25 +222,18 @@ DecoderDoctorDocumentWatcher::StopWatchi
 }
 
 void
 DecoderDoctorDocumentWatcher::EnsureTimerIsStarted()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mTimer) {
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (NS_WARN_IF(!mTimer)) {
-      return;
-    }
-    if (NS_WARN_IF(NS_FAILED(
-          mTimer->InitWithCallback(
-            this, sAnalysisPeriod_ms, nsITimer::TYPE_ONE_SHOT)))) {
-      mTimer = nullptr;
-    }
+    NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                            this, sAnalysisPeriod_ms, nsITimer::TYPE_ONE_SHOT);
   }
 }
 
 enum class ReportParam : uint8_t
 {
   // Marks the end of the parameter list.
   // Keep this zero! (For implicit zero-inits when used in definitions below.)
   None = 0,
--- a/dom/media/eme/MediaKeySystemAccessManager.cpp
+++ b/dom/media/eme/MediaKeySystemAccessManager.cpp
@@ -276,18 +276,20 @@ MediaKeySystemAccessManager::AwaitInstal
 {
   EME_LOG("MediaKeySystemAccessManager::AwaitInstall %s", NS_ConvertUTF16toUTF8(aKeySystem).get());
 
   if (!EnsureObserversAdded()) {
     NS_WARNING("Failed to add pref observer");
     return false;
   }
 
-  nsCOMPtr<nsITimer> timer(do_CreateInstance("@mozilla.org/timer;1"));
-  if (!timer || NS_FAILED(timer->Init(this, 60 * 1000, nsITimer::TYPE_ONE_SHOT))) {
+  nsCOMPtr<nsITimer> timer;
+  NS_NewTimerWithObserver(getter_AddRefs(timer),
+                          this, 60 * 1000, nsITimer::TYPE_ONE_SHOT);
+  if (!timer) {
     NS_WARNING("Failed to create timer to await CDM install.");
     return false;
   }
 
   mRequests.AppendElement(PendingRequest(aPromise, aKeySystem, aConfigs, timer));
   return true;
 }
 
--- a/dom/media/gmp/GMPTimerParent.cpp
+++ b/dom/media/gmp/GMPTimerParent.cpp
@@ -41,32 +41,29 @@ GMPTimerParent::RecvSetTimer(const uint3
   MOZ_ASSERT(mGMPEventTarget->IsOnCurrentThread());
 
   if (!mIsOpen) {
     return IPC_OK();
   }
 
   nsresult rv;
   nsAutoPtr<Context> ctx(new Context());
-  ctx->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
+
+  rv = NS_NewTimerWithFuncCallback(getter_AddRefs(ctx->mTimer),
+                                   &GMPTimerParent::GMPTimerExpired,
+                                   ctx,
+                                   aTimeoutMs,
+                                   nsITimer::TYPE_ONE_SHOT,
+                                   "gmp::GMPTimerParent::RecvSetTimer",
+                                   mGMPEventTarget);
   NS_ENSURE_SUCCESS(rv, IPC_OK());
 
   ctx->mId = aTimerId;
-  rv = ctx->mTimer->SetTarget(mGMPEventTarget);
-  NS_ENSURE_SUCCESS(rv, IPC_OK());
   ctx->mParent = this;
 
-  rv =
-    ctx->mTimer->InitWithNamedFuncCallback(&GMPTimerParent::GMPTimerExpired,
-                                           ctx,
-                                           aTimeoutMs,
-                                           nsITimer::TYPE_ONE_SHOT,
-                                           "gmp::GMPTimerParent::RecvSetTimer");
-  NS_ENSURE_SUCCESS(rv, IPC_OK());
-
   mTimers.PutEntry(ctx.forget());
 
   return IPC_OK();
 }
 
 void
 GMPTimerParent::Shutdown()
 {
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -173,17 +173,17 @@ static void ReleaseFrame(layers::PlanarY
 nsresult
 MediaEngineDefaultVideoSource::Start(SourceMediaStream* aStream, TrackID aID,
                                      const PrincipalHandle& aPrincipalHandle)
 {
   if (mState != kAllocated) {
     return NS_ERROR_FAILURE;
   }
 
-  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mTimer = NS_NewTimer();
   if (!mTimer) {
     return NS_ERROR_FAILURE;
   }
 
   aStream->AddTrack(aID, 0, new VideoSegment(), SourceMediaStream::ADDTRACK_QUEUED);
 
   // Remember TrackID so we can end it later
   mTrackID = aID;
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -46,18 +46,19 @@ MediaEngineTabVideoSource::MediaEngineTa
   , mDataSize(0)
   , mBlackedoutWindow(false)
   , mMonitor("MediaEngineTabVideoSource") {}
 
 nsresult
 MediaEngineTabVideoSource::StartRunnable::Run()
 {
   mVideoSource->Draw();
-  mVideoSource->mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  mVideoSource->mTimer->InitWithCallback(mVideoSource, mVideoSource->mTimePerFrame, nsITimer:: TYPE_REPEATING_SLACK);
+  NS_NewTimerWithCallback(getter_AddRefs(mVideoSource->mTimer),
+                          mVideoSource, mVideoSource->mTimePerFrame,
+                          nsITimer::TYPE_REPEATING_SLACK);
   if (mVideoSource->mTabSource) {
     mVideoSource->mTabSource->NotifyStreamStart(mVideoSource->mWindow);
   }
   return NS_OK;
 }
 
 nsresult
 MediaEngineTabVideoSource::StopRunnable::Run()
--- a/dom/media/webspeech/recognition/SpeechRecognition.cpp
+++ b/dom/media/webspeech/recognition/SpeechRecognition.cpp
@@ -112,17 +112,17 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEvent
 
 NS_IMPL_ADDREF_INHERITED(SpeechRecognition, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SpeechRecognition, DOMEventTargetHelper)
 
 SpeechRecognition::SpeechRecognition(nsPIDOMWindowInner* aOwnerWindow)
   : DOMEventTargetHelper(aOwnerWindow)
   , mEndpointer(kSAMPLE_RATE)
   , mAudioSamplesPerChunk(mEndpointer.FrameSize())
-  , mSpeechDetectionTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
+  , mSpeechDetectionTimer(NS_NewTimer())
   , mSpeechGrammarList(new SpeechGrammarList(GetParentObject()))
   , mInterimResults(false)
   , mMaxAlternatives(1)
 {
   SR_LOG("created SpeechRecognition");
 
   if (MediaPrefs::WebSpeechTestEnabled()) {
     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -1026,28 +1026,27 @@ nsNPAPIPluginInstance::ScheduleTimer(uin
   // generate ID that is unique to this instance
   uint32_t uniqueID = mTimers.Length();
   while ((uniqueID == 0) || TimerWithID(uniqueID, nullptr))
     uniqueID++;
   newTimer->id = uniqueID;
 
   // create new xpcom timer, scheduled correctly
   nsresult rv;
-  nsCOMPtr<nsITimer> xpcomTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
+  const short timerType = (repeat ? (short)nsITimer::TYPE_REPEATING_SLACK : (short)nsITimer::TYPE_ONE_SHOT);
+  rv = NS_NewTimerWithFuncCallback(getter_AddRefs(newTimer->timer),
+                                   PluginTimerCallback,
+                                   newTimer,
+                                   interval,
+                                   timerType,
+                                   "nsNPAPIPluginInstance::ScheduleTimer");
   if (NS_FAILED(rv)) {
     delete newTimer;
     return 0;
   }
-  const short timerType = (repeat ? (short)nsITimer::TYPE_REPEATING_SLACK : (short)nsITimer::TYPE_ONE_SHOT);
-  xpcomTimer->InitWithNamedFuncCallback(PluginTimerCallback,
-                                        newTimer,
-                                        interval,
-                                        timerType,
-                                        "nsNPAPIPluginInstance::ScheduleTimer");
-  newTimer->timer = xpcomTimer;
 
   // save callback function
   newTimer->callback = timerFunc;
 
   // add timer to timers array
   mTimers.AppendElement(newTimer);
 
   return newTimer->id;
--- a/dom/plugins/base/nsNPAPIPluginStreamListener.cpp
+++ b/dom/plugins/base/nsNPAPIPluginStreamListener.cpp
@@ -267,24 +267,20 @@ nsNPAPIPluginStreamListener::ResumeReque
     mStreamListenerPeer->ResumeRequests();
   }
   mIsSuspended = false;
 }
 
 nsresult
 nsNPAPIPluginStreamListener::StartDataPump()
 {
-  nsresult rv;
-  mDataPumpTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   // Start pumping data to the plugin every 100ms until it obeys and
   // eats the data.
-  return mDataPumpTimer->InitWithCallback(this, 100,
-                                          nsITimer::TYPE_REPEATING_SLACK);
+  return NS_NewTimerWithCallback(getter_AddRefs(mDataPumpTimer),
+                                 this, 100, nsITimer::TYPE_REPEATING_SLACK);
 }
 
 void
 nsNPAPIPluginStreamListener::StopDataPump()
 {
   if (mDataPumpTimer) {
     mDataPumpTimer->Cancel();
     mDataPumpTimer = nullptr;
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -652,17 +652,17 @@ void nsPluginHost::OnPluginInstanceDestr
   // retention and avoid perf hits for loading popular plugins.
   if (!hasInstance) {
     if (UnloadPluginsASAP()) {
       aPluginTag->TryUnloadPlugin(false);
     } else {
       if (aPluginTag->mUnloadTimer) {
         aPluginTag->mUnloadTimer->Cancel();
       } else {
-        aPluginTag->mUnloadTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+        aPluginTag->mUnloadTimer = NS_NewTimer();
       }
       uint32_t unloadTimeout = Preferences::GetUint(kPrefUnloadPluginTimeoutSecs,
                                                     kDefaultPluginUnloadingTimeout);
       aPluginTag->mUnloadTimer->InitWithCallback(this,
                                                  1000 * unloadTimeout,
                                                  nsITimer::TYPE_ONE_SHOT);
     }
   }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1282,18 +1282,17 @@ bool nsPluginInstanceOwner::IsRemoteDraw
 }
 
 NPEventModel nsPluginInstanceOwner::GetEventModel()
 {
   return mEventModel;
 }
 
 #define DEFAULT_REFRESH_RATE 20 // 50 FPS
-
-nsCOMPtr<nsITimer>               *nsPluginInstanceOwner::sCATimer = nullptr;
+StaticRefPtr<nsITimer>            nsPluginInstanceOwner::sCATimer;
 nsTArray<nsPluginInstanceOwner*> *nsPluginInstanceOwner::sCARefreshListeners = nullptr;
 
 void nsPluginInstanceOwner::CARefresh(nsITimer *aTimer, void *aClosure) {
   if (!sCARefreshListeners) {
     return;
   }
   for (size_t i = 0; i < sCARefreshListeners->Length(); i++) {
     nsPluginInstanceOwner* instanceOwner = (*sCARefreshListeners)[i];
@@ -1329,39 +1328,36 @@ void nsPluginInstanceOwner::AddToCARefre
   }
 
   if (sCARefreshListeners->Contains(this)) {
     return;
   }
 
   sCARefreshListeners->AppendElement(this);
 
-  if (!sCATimer) {
-    sCATimer = new nsCOMPtr<nsITimer>();
-  }
-
   if (sCARefreshListeners->Length() == 1) {
-    *sCATimer = do_CreateInstance("@mozilla.org/timer;1");
-    (*sCATimer)->InitWithNamedFuncCallback(CARefresh, nullptr,
-                                           DEFAULT_REFRESH_RATE, nsITimer::TYPE_REPEATING_SLACK,
-                                           "nsPluginInstanceOwner::CARefresh");
+    nsCOMPtr<nsITimer> timer;
+    NS_NewTimerWithFuncCallback(getter_AddRefs(timer),
+                                CARefresh, nullptr,
+                                DEFAULT_REFRESH_RATE, nsITimer::TYPE_REPEATING_SLACK,
+                                "nsPluginInstanceOwner::CARefresh");
+    sCATimer = timer.forget();
   }
 }
 
 void nsPluginInstanceOwner::RemoveFromCARefreshTimer() {
   if (!sCARefreshListeners || sCARefreshListeners->Contains(this) == false) {
     return;
   }
 
   sCARefreshListeners->RemoveElement(this);
 
   if (sCARefreshListeners->Length() == 0) {
     if (sCATimer) {
-      (*sCATimer)->Cancel();
-      delete sCATimer;
+      sCATimer->Cancel();
       sCATimer = nullptr;
     }
     delete sCARefreshListeners;
     sCARefreshListeners = nullptr;
   }
 }
 
 void nsPluginInstanceOwner::SetPluginPort()
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsPluginInstanceOwner_h_
 #define nsPluginInstanceOwner_h_
 
 #include "mozilla/Attributes.h"
+#include "mozilla/StaticPtr.h"
 #include "npapi.h"
 #include "nsCOMPtr.h"
 #include "nsIKeyEventInPluginCallback.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsIPrivacyTransitionObserver.h"
 #include "nsIDOMEventListener.h"
 #include "nsPluginHost.h"
 #include "nsPluginNativeWindow.h"
@@ -303,17 +304,17 @@ private:
   nsPluginFrame              *mPluginFrame;
   nsWeakPtr                   mContent; // WEAK, content owns us
   nsCString                   mDocumentBase;
   bool                        mWidgetCreationComplete;
   nsCOMPtr<nsIWidget>         mWidget;
   RefPtr<nsPluginHost>      mPluginHost;
 
 #ifdef XP_MACOSX
-  static nsCOMPtr<nsITimer>                *sCATimer;
+  static mozilla::StaticRefPtr<nsITimer>    sCATimer;
   static nsTArray<nsPluginInstanceOwner*>  *sCARefreshListeners;
   bool                                      mSentInitialTopLevelWindowEvent;
   bool                                      mLastWindowIsActive;
   bool                                      mLastContentFocused;
   // True if, the next time the window is activated, we should blur ourselves.
   bool                                      mShouldBlurOnActivate;
 #endif
   double                                    mLastScaleFactor;
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -1167,21 +1167,18 @@ PresentationPresentingInfo::Init(nsIPres
 {
   PresentationSessionInfo::Init(aControlChannel);
 
   // Add a timer to prevent waiting indefinitely in case the receiver page fails
   // to become ready.
   nsresult rv;
   int32_t timeout =
     Preferences::GetInt("presentation.receiver.loading.timeout", 10000);
-  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  rv = mTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
+  rv = NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                               this, timeout, nsITimer::TYPE_ONE_SHOT);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 void
--- a/dom/presentation/provider/MulticastDNSDeviceProvider.cpp
+++ b/dom/presentation/provider/MulticastDNSDeviceProvider.cpp
@@ -139,24 +139,24 @@ MulticastDNSDeviceProvider::Init()
     return rv;
   }
 
   mPresentationService = do_CreateInstance(PRESENTATION_CONTROL_SERVICE_CONTACT_ID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  mDiscoveryTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
+  mDiscoveryTimer = NS_NewTimer();
+  if (NS_WARN_IF(!mDiscoveryTimer)) {
+    return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  mServerRetryTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
+  mServerRetryTimer = NS_NewTimer();
+  if (NS_WARN_IF(!mServerRetryTimer)) {
+    return NS_ERROR_OUT_OF_MEMORY;
   }
   Preferences::AddStrongObservers(this, kObservedPrefs);
 
   mDiscoveryEnabled = Preferences::GetBool(PREF_PRESENTATION_DISCOVERY);
   mDiscoveryTimeoutMs = Preferences::GetUint(PREF_PRESENTATION_DISCOVERY_TIMEOUT_MS);
   mDiscoverable = Preferences::GetBool(PREF_PRESENTATION_DISCOVERABLE);
   mDiscoverableEncrypted = Preferences::GetBool(PREF_PRESENTATION_DISCOVERABLE_ENCRYPTED);
   mServerRetryMs = Preferences::GetUint(PREF_PRESENTATION_DISCOVERABLE_RETRY_MS);
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -3,18 +3,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ActorsParent.h"
 
 #include "mozIStorageConnection.h"
 #include "mozIStorageService.h"
-#include "nsIBinaryInputStream.h"
-#include "nsIBinaryOutputStream.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
 #include "nsIFile.h"
 #include "nsIFileStreams.h"
 #include "nsIObserverService.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
 #include "nsIRunnable.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIScriptObjectPrincipal.h"
@@ -2135,28 +2135,24 @@ GetBinaryOutputStream(nsIFile* aFile,
   nsCOMPtr<nsIOutputStream> outputStream;
   nsresult rv = GetOutputStream(aFile,
                                 aFileFlag,
                                 getter_AddRefs(outputStream));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsCOMPtr<nsIBinaryOutputStream> binaryStream =
-    do_CreateInstance("@mozilla.org/binaryoutputstream;1");
-  if (NS_WARN_IF(!binaryStream)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  rv = binaryStream->SetOutputStream(outputStream);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  binaryStream.forget(aStream);
+  if (NS_WARN_IF(!outputStream)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  nsCOMPtr<nsIObjectOutputStream> objectOutputStream =
+    NS_NewObjectOutputStream(outputStream);
+
+  objectOutputStream.forget(aStream);
   return NS_OK;
 }
 
 void
 GetJarPrefix(uint32_t aAppId,
              bool aInIsolatedMozBrowser,
              nsACString& aJarPrefix)
 {
@@ -3618,17 +3614,17 @@ QuotaManager::Init(const nsAString& aBas
 
   rv = NS_NewNamedThread("QuotaManager IO", getter_AddRefs(mIOThread));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Make a timer here to avoid potential failures later. We don't actually
   // initialize the timer until shutdown.
-  mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mShutdownTimer = NS_NewTimer();
   if (NS_WARN_IF(!mShutdownTimer)) {
     return NS_ERROR_FAILURE;
   }
 
   static_assert(Client::IDB == 0 && Client::ASMJS == 1 && Client::DOMCACHE == 2 &&
                 Client::TYPE_MAX == 3, "Fix the registration!");
 
   MOZ_ASSERT(mClients.Capacity() == Client::TYPE_MAX,
--- a/dom/security/test/mixedcontentblocker/mochitest.ini
+++ b/dom/security/test/mixedcontentblocker/mochitest.ini
@@ -15,12 +15,12 @@ support-files =
   !/dom/media/test/320x240.ogv
   !/image/test/mochitest/blue.png
   file_redirect.html
   file_redirect_handler.sjs
 
 [test_main.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_bug803225.html]
-skip-if = toolkit == 'android' || (os=='linux' && bits==32) #Android: TIMED_OUT; Linux32:bug 1324870
+skip-if = toolkit == 'android' || (os=='linux' && bits==32) || headless #Android: TIMED_OUT; Linux32:bug 1324870; Headless:bug 1405870
 [test_frameNavigation.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_redirect.html]
--- a/dom/storage/StorageObserver.cpp
+++ b/dom/storage/StorageObserver.cpp
@@ -206,24 +206,18 @@ StorageObserver::Observe(nsISupports* aS
 
   // Start the thread that opens the database.
   if (!strcmp(aTopic, kStartupTopic)) {
     MOZ_ASSERT(XRE_IsParentProcess());
 
     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     obs->RemoveObserver(this, kStartupTopic);
 
-    mDBThreadStartDelayTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (!mDBThreadStartDelayTimer) {
-      return NS_ERROR_UNEXPECTED;
-    }
-
-    mDBThreadStartDelayTimer->Init(this, nsITimer::TYPE_ONE_SHOT, kStartupDelay);
-
-    return NS_OK;
+    return NS_NewTimerWithObserver(getter_AddRefs(mDBThreadStartDelayTimer),
+                                   this, nsITimer::TYPE_ONE_SHOT, kStartupDelay);
   }
 
   // Timer callback used to start the database a short timer after startup
   if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) {
     MOZ_ASSERT(XRE_IsParentProcess());
 
     nsCOMPtr<nsITimer> timer = do_QueryInterface(aSubject);
     if (!timer) {
--- a/dom/vr/VREventObserver.h
+++ b/dom/vr/VREventObserver.h
@@ -29,18 +29,17 @@ public:
   void NotifyVRDisplayDisconnect(uint32_t aDisplayID);
   void NotifyVRDisplayPresentChange(uint32_t aDisplayID);
 
   void DisconnectFromOwner();
 
 private:
   ~VREventObserver();
 
-  // Weak pointer, instance is owned by mWindow.
-  nsGlobalWindow* MOZ_NON_OWNING_REF mWindow;
+  RefPtr<nsGlobalWindow> mWindow;
   // For WebVR telemetry for tracking users who view content
   // in the 2D view.
   TimeStamp mSpendTimeIn2DView;
   bool mIs2DView;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -1979,17 +1979,17 @@ RuntimeService::Init()
 
   // nsIStreamTransportService is thread-safe but it must be initialized on the
   // main-thread. FileReader needs it, so, let's initialize it now.
   nsresult rv;
   nsCOMPtr<nsIStreamTransportService> sts =
     do_GetService(kStreamTransportServiceCID, &rv);
   NS_ENSURE_TRUE(sts, NS_ERROR_FAILURE);
 
-  mIdleThreadTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mIdleThreadTimer = NS_NewTimer();
   NS_ENSURE_STATE(mIdleThreadTimer);
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
 
   rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -4335,33 +4335,28 @@ ServiceWorkerManager::ScheduleUpdateTime
   if (timer) {
     // There is already a timer scheduled.  In this case just use the original
     // schedule time.  We don't want to push it out to a later time since that
     // could allow updates to be starved forever if events are continuously
     // fired.
     return;
   }
 
-  timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    data->mUpdateTimers.Remove(aScope); // another lookup, but very rare
-    return;
-  }
-
-  // Label with SystemGroup because UpdateTimerCallback only sends an IPC message
-  // (PServiceWorkerUpdaterConstructor) without touching any web contents.
-  timer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::Other));
-
   nsCOMPtr<nsITimerCallback> callback = new UpdateTimerCallback(aPrincipal,
                                                                 aScope);
 
   const uint32_t UPDATE_DELAY_MS = 1000;
 
-  rv = timer->InitWithCallback(callback, UPDATE_DELAY_MS,
-                               nsITimer::TYPE_ONE_SHOT);
+  // Label with SystemGroup because UpdateTimerCallback only sends an IPC message
+  // (PServiceWorkerUpdaterConstructor) without touching any web contents.
+  rv = NS_NewTimerWithCallback(getter_AddRefs(timer),
+                               callback, UPDATE_DELAY_MS,
+                               nsITimer::TYPE_ONE_SHOT,
+                               SystemGroup::EventTargetFor(TaskCategory::Other));
+
   if (NS_WARN_IF(NS_FAILED(rv))) {
     data->mUpdateTimers.Remove(aScope); // another lookup, but very rare
     return;
   }
 }
 
 void
 ServiceWorkerManager::UpdateTimerFired(nsIPrincipal* aPrincipal,
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -84,17 +84,17 @@ NS_IMPL_ISUPPORTS0(KeepAliveToken)
 ServiceWorkerPrivate::ServiceWorkerPrivate(ServiceWorkerInfo* aInfo)
   : mInfo(aInfo)
   , mDebuggerCount(0)
   , mTokenCount(0)
 {
   AssertIsOnMainThread();
   MOZ_ASSERT(aInfo);
 
-  mIdleWorkerTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mIdleWorkerTimer = NS_NewTimer();
   MOZ_ASSERT(mIdleWorkerTimer);
 }
 
 ServiceWorkerPrivate::~ServiceWorkerPrivate()
 {
   MOZ_ASSERT(!mWorkerPrivate);
   MOZ_ASSERT(!mTokenCount);
   MOZ_ASSERT(!mInfo);
@@ -1095,23 +1095,18 @@ class AllowWindowInteractionHandler fina
   void
   StartClearWindowTimer(WorkerPrivate* aWorkerPrivate)
   {
     MOZ_ASSERT(aWorkerPrivate);
     aWorkerPrivate->AssertIsOnWorkerThread();
     MOZ_ASSERT(!mTimer);
 
     nsresult rv;
-    nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return;
-    }
-
-    rv = timer->SetTarget(aWorkerPrivate->ControlEventTarget());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
+    nsCOMPtr<nsITimer> timer = NS_NewTimer(aWorkerPrivate->ControlEventTarget());
+    if (NS_WARN_IF(!timer)) {
       return;
     }
 
     if (!HoldWorker(aWorkerPrivate, Closing)) {
       return;
     }
 
     aWorkerPrivate->GlobalScope()->AllowWindowInteraction();
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -5291,17 +5291,17 @@ WorkerPrivate::InitializeGCTimers()
 {
   AssertIsOnWorkerThread();
 
   // We need a timer for GC. The basic plan is to run a non-shrinking GC
   // periodically (PERIODIC_GC_TIMER_DELAY_SEC) while the worker is running.
   // Once the worker goes idle we set a short (IDLE_GC_TIMER_DELAY_SEC) timer to
   // run a shrinking GC. If the worker receives more messages then the short
   // timer is canceled and the periodic timer resumes.
-  mGCTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mGCTimer = NS_NewTimer();
   MOZ_ASSERT(mGCTimer);
 
   mPeriodicGCTimerRunning = false;
   mIdleGCTimerRunning = false;
 }
 
 void
 WorkerPrivate::SetGCTimerMode(GCTimerMode aMode)
@@ -6477,22 +6477,20 @@ WorkerPrivate::SetTimeout(JSContext* aCx
     mTimeouts.InsertElementSorted(newInfo.forget(), GetAutoPtrComparator(mTimeouts));
 
   LOG(TimeoutsLog(), ("Worker %p has new timeout: delay=%d interval=%s\n",
                       this, aTimeout, aIsInterval ? "yes" : "no"));
 
   // If the timeout we just made is set to fire next then we need to update the
   // timer, unless we're currently running timeouts.
   if (insertedInfo == mTimeouts.Elements() && !mRunningExpiredTimeouts) {
-    nsresult rv;
-
     if (!mTimer) {
-      mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-      if (NS_FAILED(rv)) {
-        aRv.Throw(rv);
+      mTimer = NS_NewTimer();
+      if (!mTimer) {
+        aRv.Throw(NS_ERROR_UNEXPECTED);
         return 0;
       }
 
       mTimerRunnable = new TimerRunnable(this);
     }
 
     if (!mTimerRunning) {
       if (!ModifyBusyCountFromWorker(true)) {
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -388,25 +388,23 @@ nsBindingManager::DoProcessAttachedQueue
   } else {
     // Someone's doing event processing from inside a constructor.
     // They're evil, but we'll fight back!  Just poll on them being
     // done and repost the attached queue event.
     //
     // But don't poll in a tight loop -- otherwise we keep the Gecko
     // event loop non-empty and trigger bug 1021240 on OS X.
     nsresult rv = NS_ERROR_FAILURE;
-    nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (timer) {
-      rv = timer->InitWithNamedFuncCallback(
-        PostPAQEventCallback,
-        this,
-        100,
-        nsITimer::TYPE_ONE_SHOT,
-        "nsBindingManager::DoProcessAttachedQueue");
-    }
+    nsCOMPtr<nsITimer> timer;
+    rv = NS_NewTimerWithFuncCallback(getter_AddRefs(timer),
+                                     PostPAQEventCallback,
+                                     this,
+                                     100,
+                                     nsITimer::TYPE_ONE_SHOT,
+                                     "nsBindingManager::DoProcessAttachedQueue");
     if (NS_SUCCEEDED(rv)) {
       NS_ADDREF_THIS();
       // We drop our reference to the timer here, since the timer callback is
       // responsible for releasing the object.
       Unused << timer.forget().take();
     }
   }
 
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -3285,17 +3285,17 @@ XMLHttpRequestMainThread::StartTimeoutTi
     mTimeoutTimer->Cancel();
   }
 
   if (!mTimeoutMilliseconds) {
     return;
   }
 
   if (!mTimeoutTimer) {
-    mTimeoutTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mTimeoutTimer = NS_NewTimer();
     SetTimerEventTarget(mTimeoutTimer);
   }
   uint32_t elapsed =
     (uint32_t)((PR_Now() - mRequestSentTime) / PR_USEC_PER_MSEC);
   mTimeoutTimer->InitWithCallback(
     this,
     mTimeoutMilliseconds > elapsed ? mTimeoutMilliseconds - elapsed : 0,
     nsITimer::TYPE_ONE_SHOT
@@ -3764,17 +3764,17 @@ XMLHttpRequestMainThread::StopProgressEv
     mProgressNotifier->Cancel();
   }
 }
 
 void
 XMLHttpRequestMainThread::StartProgressEventTimer()
 {
   if (!mProgressNotifier) {
-    mProgressNotifier = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mProgressNotifier = NS_NewTimer();
     SetTimerEventTarget(mProgressNotifier);
   }
   if (mProgressNotifier) {
     mProgressTimerIsActive = true;
     mProgressNotifier->Cancel();
     mProgressNotifier->InitWithCallback(this, NS_PROGRESS_EVENT_INTERVAL,
                                         nsITimer::TYPE_ONE_SHOT);
   }
@@ -3791,17 +3791,17 @@ XMLHttpRequestMainThread::MaybeStartSync
   }
 
   // If we are in a beforeunload or a unload event, we must force a timeout.
   TimeDuration diff = (TimeStamp::NowLoRes() - doc->GetPageUnloadingEventTimeStamp());
   if (diff.ToMilliseconds() > MAX_SYNC_TIMEOUT_WHEN_UNLOADING) {
     return eErrorOrExpired;
   }
 
-  mSyncTimeoutTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mSyncTimeoutTimer = NS_NewTimer();
   SetTimerEventTarget(mSyncTimeoutTimer);
   if (!mSyncTimeoutTimer) {
     return eErrorOrExpired;
   }
 
   uint32_t timeout = MAX_SYNC_TIMEOUT_WHEN_UNLOADING - diff.ToMilliseconds();
   nsresult rv = mSyncTimeoutTimer->InitWithCallback(this, timeout,
                                                     nsITimer::TYPE_ONE_SHOT);
--- a/dom/xul/nsXULPrototypeCache.cpp
+++ b/dom/xul/nsXULPrototypeCache.cpp
@@ -394,21 +394,25 @@ nsXULPrototypeCache::FinishInputStream(n
 nsresult
 nsXULPrototypeCache::GetOutputStream(nsIURI* uri, nsIObjectOutputStream** stream)
 {
     nsresult rv;
     nsCOMPtr<nsIObjectOutputStream> objectOutput;
     nsCOMPtr<nsIStorageStream> storageStream;
     bool found = mOutputStreamTable.Get(uri, getter_AddRefs(storageStream));
     if (found) {
-        objectOutput = do_CreateInstance("mozilla.org/binaryoutputstream;1");
-        if (!objectOutput) return NS_ERROR_OUT_OF_MEMORY;
+        // Setting an output stream here causes crashes on Windows. The previous
+        // version of this code always returned NS_ERROR_OUT_OF_MEMORY here,
+        // because it used a mistyped contract ID to create its object stream.
+        return NS_ERROR_NOT_IMPLEMENTED;
+#if 0
         nsCOMPtr<nsIOutputStream> outputStream
             = do_QueryInterface(storageStream);
-        objectOutput->SetOutputStream(outputStream);
+        objectOutput = NS_NewObjectOutputStream(outputStream);
+#endif
     } else {
         rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(objectOutput),
                                                  getter_AddRefs(storageStream),
                                                  false);
         NS_ENSURE_SUCCESS(rv, rv);
         mOutputStreamTable.Put(uri, storageStream);
     }
     objectOutput.forget(stream);
--- a/editor/composer/nsComposerCommandsUpdater.cpp
+++ b/editor/composer/nsComposerCommandsUpdater.cpp
@@ -220,19 +220,18 @@ nsComposerCommandsUpdater::Init(nsPIDOMW
   mDocShell = do_GetWeakReference(aDOMWindow->GetDocShell());
   return NS_OK;
 }
 
 nsresult
 nsComposerCommandsUpdater::PrimeUpdateTimer()
 {
   if (!mUpdateTimer) {
-    nsresult rv = NS_OK;
-    mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    mUpdateTimer = NS_NewTimer();;
+    NS_ENSURE_TRUE(mUpdateTimer, NS_ERROR_OUT_OF_MEMORY);
   }
 
   const uint32_t kUpdateTimerDelay = 150;
   return mUpdateTimer->InitWithCallback(static_cast<nsITimerCallback*>(this),
                                         kUpdateTimerDelay,
                                         nsITimer::TYPE_ONE_SHOT);
 }
 
--- a/editor/composer/nsEditingSession.cpp
+++ b/editor/composer/nsEditingSession.cpp
@@ -962,26 +962,26 @@ nsEditingSession::EndDocumentLoad(nsIWeb
         if (NS_FAILED(rv)) {
           // If we had an error, setup timer to load a blank page later
           if (mLoadBlankDocTimer) {
             // Must cancel previous timer?
             mLoadBlankDocTimer->Cancel();
             mLoadBlankDocTimer = nullptr;
           }
 
-          mLoadBlankDocTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-          NS_ENSURE_SUCCESS(rv, rv);
-
-          mEditorStatus = eEditorCreationInProgress;
-          mLoadBlankDocTimer->InitWithNamedFuncCallback(
+          rv = NS_NewTimerWithFuncCallback(
+            getter_AddRefs(mLoadBlankDocTimer),
             nsEditingSession::TimerCallback,
             static_cast<void*>(mDocShell.get()),
             10,
             nsITimer::TYPE_ONE_SHOT,
             "nsEditingSession::EndDocumentLoad");
+          NS_ENSURE_SUCCESS(rv, rv);
+
+          mEditorStatus = eEditorCreationInProgress;
         }
       }
     }
   }
   return rv;
 }
 
 
--- a/editor/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -708,18 +708,18 @@ TextEditRules::WillInsertText(EditAction
 
     if (LookAndFeel::GetEchoPassword() && !DontEchoPassword()) {
       HideLastPWInput();
       mLastStart = start;
       mLastLength = outString->Length();
       if (mTimer) {
         mTimer->Cancel();
       } else {
-        mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-        NS_ENSURE_SUCCESS(rv, rv);
+        mTimer = NS_NewTimer();
+        NS_ENSURE_TRUE(mTimer, NS_ERROR_OUT_OF_MEMORY);
       }
       mTimer->InitWithCallback(this, LookAndFeel::GetPasswordMaskDelay(),
                                nsITimer::TYPE_ONE_SHOT);
     } else {
       FillBufWithPWChars(outString, outString->Length());
     }
   }
 
--- a/extensions/pref/autoconfig/src/nsAutoConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsAutoConfig.cpp
@@ -1,13 +1,14 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/ResultExtensions.h"
 #include "nsAutoConfig.h"
 #include "nsIURI.h"
 #include "nsIHttpChannel.h"
 #include "nsIFileStreams.h"
 #include "nsThreadUtils.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIObserverService.h"
 #include "nsLiteralString.h"
@@ -330,23 +331,18 @@ nsresult nsAutoConfig::downloadAutoConfi
         }
 
         int32_t minutes;
         rv = mPrefBranch->GetIntPref("autoadmin.refresh_interval",
                                      &minutes);
         if (NS_SUCCEEDED(rv) && minutes > 0) {
             // Create a new timer and pass this nsAutoConfig
             // object as a timer callback.
-            mTimer = do_CreateInstance("@mozilla.org/timer;1",&rv);
-            if (NS_FAILED(rv))
-                return rv;
-            rv = mTimer->InitWithCallback(this, minutes * 60 * 1000,
-                             nsITimer::TYPE_REPEATING_SLACK);
-            if (NS_FAILED(rv))
-                return rv;
+            MOZ_TRY_VAR(mTimer, NS_NewTimerWithCallback(this, minutes * 60 * 1000,
+                                                        nsITimer::TYPE_REPEATING_SLACK));
         }
     } //first_time
 
     return NS_OK;
 } // nsPref::downloadAutoConfig()
 
 
 
--- a/gfx/layers/apz/util/APZEventState.cpp
+++ b/gfx/layers/apz/util/APZEventState.cpp
@@ -202,17 +202,17 @@ APZEventState::ProcessSingleTap(const CS
 
   if (mTouchEndCancelled) {
     return;
   }
 
   LayoutDevicePoint ldPoint = aPoint * aScale;
 
   APZES_LOG("Scheduling timer for click event\n");
-  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  nsCOMPtr<nsITimer> timer = NS_NewTimer();
   dom::TabChild* tabChild = widget->GetOwningTabChild();
 
   if (tabChild && XRE_IsContentProcess()) {
     timer->SetTarget(
       tabChild->TabGroup()->EventTargetFor(TaskCategory::Other));
   }
   RefPtr<DelayedFireSingleTapEvent> callback =
     new DelayedFireSingleTapEvent(mWidget, ldPoint, aModifiers, aClickCount,
--- a/gfx/layers/client/TextureClientPool.cpp
+++ b/gfx/layers/client/TextureClientPool.cpp
@@ -57,18 +57,18 @@ TextureClientPool::TextureClientPool(Lay
   , mInitialPoolSize(aInitialPoolSize)
   , mPoolUnusedSize(aPoolUnusedSize)
   , mOutstandingClients(0)
   , mSurfaceAllocator(aAllocator)
   , mDestroyed(false)
 {
   TCP_LOG("TexturePool %p created with maximum unused texture clients %u\n",
       this, mInitialPoolSize);
-  mShrinkTimer = do_CreateInstance("@mozilla.org/timer;1");
-  mClearTimer = do_CreateInstance("@mozilla.org/timer;1");
+  mShrinkTimer = NS_NewTimer();
+  mClearTimer = NS_NewTimer();
   if (aFormat == gfx::SurfaceFormat::UNKNOWN) {
     gfxWarning() << "Creating texture pool for SurfaceFormat::UNKNOWN format";
   }
 }
 
 TextureClientPool::~TextureClientPool()
 {
   mShrinkTimer->Cancel();
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -1245,25 +1245,23 @@ gfxFcPlatformFontList::gfxFcPlatformFont
     , mFcSubstituteCache(64)
     , mLastConfig(nullptr)
     , mAlwaysUseFontconfigGenerics(true)
 {
     // if the rescan interval is set, start the timer
     int rescanInterval = FcConfigGetRescanInterval(nullptr);
     if (rescanInterval) {
         mLastConfig = FcConfigGetCurrent();
-        mCheckFontUpdatesTimer = do_CreateInstance("@mozilla.org/timer;1");
-        if (mCheckFontUpdatesTimer) {
-          mCheckFontUpdatesTimer->InitWithNamedFuncCallback(
-            CheckFontUpdates,
-            this,
-            (rescanInterval + 1) * 1000,
-            nsITimer::TYPE_REPEATING_SLACK,
-            "gfxFcPlatformFontList::gfxFcPlatformFontList");
-        } else {
+        NS_NewTimerWithFuncCallback(getter_AddRefs(mCheckFontUpdatesTimer),
+                                    CheckFontUpdates,
+                                    this,
+                                    (rescanInterval + 1) * 1000,
+                                    nsITimer::TYPE_REPEATING_SLACK,
+                                    "gfxFcPlatformFontList::gfxFcPlatformFontList");
+        if (!mCheckFontUpdatesTimer) {
             NS_WARNING("Failure to create font updates timer");
         }
     }
 
 #ifdef MOZ_BUNDLED_FONTS
     mBundledFontsInitialized = false;
 #endif
 }
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -179,28 +179,27 @@ gfxFontCache::gfxFontCache(nsIEventTarge
     nsCOMPtr<nsIObserverService> obs = GetObserverService();
     if (obs) {
         obs->AddObserver(new Observer, "memory-pressure", false);
     }
 
 #ifndef RELEASE_OR_BETA
     // Currently disabled for release builds, due to unexplained crashes
     // during expiration; see bug 717175 & 894798.
-    mWordCacheExpirationTimer = do_CreateInstance("@mozilla.org/timer;1");
-    if (mWordCacheExpirationTimer) {
-        if (XRE_IsContentProcess() && NS_IsMainThread()) {
-            mWordCacheExpirationTimer->SetTarget(aEventTarget);
-        }
-        mWordCacheExpirationTimer->InitWithNamedFuncCallback(
-          WordCacheExpirationTimerCallback,
-          this,
-          SHAPED_WORD_TIMEOUT_SECONDS * 1000,
-          nsITimer::TYPE_REPEATING_SLACK,
-          "gfxFontCache::gfxFontCache");
+    nsIEventTarget* target = nullptr;
+    if (XRE_IsContentProcess() && NS_IsMainThread()) {
+      target = aEventTarget;
     }
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mWordCacheExpirationTimer),
+                                WordCacheExpirationTimerCallback,
+                                this,
+                                SHAPED_WORD_TIMEOUT_SECONDS * 1000,
+                                nsITimer::TYPE_REPEATING_SLACK,
+                                "gfxFontCache::gfxFontCache",
+                                target);
 #endif
 }
 
 gfxFontCache::~gfxFontCache()
 {
     // Ensure the user font cache releases its references to font entries,
     // so they aren't kept alive after the font instances and font-list
     // have been shut down.
--- a/gfx/thebes/gfxFontInfoLoader.cpp
+++ b/gfx/thebes/gfxFontInfoLoader.cpp
@@ -147,17 +147,17 @@ gfxFontInfoLoader::StartLoader(uint32_t 
     if (mState != stateInitial &&
         mState != stateTimerOff &&
         mState != stateTimerOnDelay) {
         CancelLoader();
     }
 
     // set up timer
     if (!mTimer) {
-        mTimer = do_CreateInstance("@mozilla.org/timer;1");
+        mTimer = NS_NewTimer();
         if (!mTimer) {
             NS_WARNING("Failure to create font info loader timer");
             return;
         }
     }
 
     AddShutdownObserver();
 
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -394,17 +394,17 @@ public:
 
   class OSXDisplay final : public VsyncSource::Display
   {
   public:
     OSXDisplay()
       : mDisplayLink(nullptr)
     {
       MOZ_ASSERT(NS_IsMainThread());
-      mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+      mTimer = NS_NewTimer();
     }
 
     ~OSXDisplay() override
     {
       MOZ_ASSERT(NS_IsMainThread());
     }
 
     static void RetryEnableVsync(nsITimer* aTimer, void* aOsxDisplay)
--- a/ipc/glue/BackgroundImpl.cpp
+++ b/ipc/glue/BackgroundImpl.cpp
@@ -1025,19 +1025,18 @@ ParentImpl::CreateBackgroundThread()
     NS_WARNING("Trying to create background thread after shutdown has "
                "already begun!");
     return false;
   }
 
   nsCOMPtr<nsITimer> newShutdownTimer;
 
   if (!sShutdownTimer) {
-    nsresult rv;
-    newShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
+    newShutdownTimer = NS_NewTimer();
+    if (!newShutdownTimer) {
       return false;
     }
   }
 
   if (!sShutdownObserverRegistered) {
     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     if (NS_WARN_IF(!obs)) {
       return false;
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -81,17 +81,17 @@ MessagePump::Run(MessagePump::Delegate* 
   MOZ_ASSERT(keep_running_);
   MOZ_RELEASE_ASSERT(NS_IsMainThread(),
                      "Use mozilla::ipc::MessagePumpForNonMainThreads instead!");
   MOZ_RELEASE_ASSERT(!mEventTarget);
 
   nsIThread* thisThread = NS_GetCurrentThread();
   MOZ_ASSERT(thisThread);
 
-  mDelayedWorkTimer = do_CreateInstance(kNS_TIMER_CID);
+  mDelayedWorkTimer = NS_NewTimer();
   MOZ_ASSERT(mDelayedWorkTimer);
 
   base::ScopedNSAutoreleasePool autoReleasePool;
 
   for (;;) {
     autoReleasePool.Recycle();
 
     bool did_work = NS_ProcessNextEvent(thisThread, false) ? true : false;
@@ -157,17 +157,17 @@ void
 MessagePump::ScheduleDelayedWork(const base::TimeTicks& aDelayedTime)
 {
   // To avoid racing on mDelayedWorkTimer, we need to be on the same thread as
   // ::Run().
   MOZ_RELEASE_ASSERT((!mEventTarget && NS_IsMainThread())
                      || mEventTarget->IsOnCurrentThread());
 
   if (!mDelayedWorkTimer) {
-    mDelayedWorkTimer = do_CreateInstance(kNS_TIMER_CID);
+    mDelayedWorkTimer = NS_NewTimer();
     if (!mDelayedWorkTimer) {
         // Called before XPCOM has started up? We can't do this correctly.
         NS_WARNING("Delayed task might not run!");
         delayed_work_time_ = aDelayedTime;
         return;
     }
   }
 
@@ -305,23 +305,19 @@ void
 MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate* aDelegate)
 {
   MOZ_ASSERT(keep_running_);
   MOZ_RELEASE_ASSERT(!NS_IsMainThread(), "Use mozilla::ipc::MessagePump instead!");
 
   nsIThread* thread = NS_GetCurrentThread();
   MOZ_RELEASE_ASSERT(mEventTarget->IsOnCurrentThread());
 
-  mDelayedWorkTimer = do_CreateInstance(kNS_TIMER_CID);
+  mDelayedWorkTimer = NS_NewTimer(mEventTarget);
   MOZ_ASSERT(mDelayedWorkTimer);
 
-  if (NS_FAILED(mDelayedWorkTimer->SetTarget(mEventTarget))) {
-    MOZ_CRASH("Failed to set timer target!");
-  }
-
   // Chromium event notifications to be processed will be received by this
   // event loop as a DoWorkRunnables via ScheduleWork. Chromium events that
   // were received before our thread is valid, however, will not generate
   // runnable wrappers. We must process any of these before we enter this
   // loop, or we will forever have unprocessed chromium messages in our queue.
   //
   // Note we would like to request a flush of the chromium event queue
   // using a runnable on the xpcom side, but some thread implementations
--- a/layout/base/AccessibleCaretEventHub.cpp
+++ b/layout/base/AccessibleCaretEventHub.cpp
@@ -435,20 +435,20 @@ AccessibleCaretEventHub::Init()
   }
 
   docShell->AddWeakReflowObserver(this);
   docShell->AddWeakScrollObserver(this);
 
   mDocShell = static_cast<nsDocShell*>(docShell);
 
   if (sUseLongTapInjector) {
-    mLongTapInjectorTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mLongTapInjectorTimer = NS_NewTimer();
   }
 
-  mScrollEndInjectorTimer = do_CreateInstance("@mozilla.org/timer;1");
+  mScrollEndInjectorTimer = NS_NewTimer();
 
   mManager = MakeUnique<AccessibleCaretManager>(mPresShell);
 
   mInitialized = true;
 }
 
 void
 AccessibleCaretEventHub::Terminate()
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -1817,17 +1817,17 @@ PresShell::Initialize(nscoord aWidth, ns
   if (!mPresContext->IsPaginated()) {
     // Kick off a one-shot timer based off our pref value.  When this timer
     // fires, if painting is still locked down, then we will go ahead and
     // trigger a full invalidate and allow painting to proceed normally.
     mPaintingSuppressed = true;
     // Don't suppress painting if the document isn't loading.
     nsIDocument::ReadyState readyState = mDocument->GetReadyStateEnum();
     if (readyState != nsIDocument::READYSTATE_COMPLETE) {
-      mPaintSuppressionTimer = do_CreateInstance("@mozilla.org/timer;1");
+      mPaintSuppressionTimer = NS_NewTimer();
     }
     if (!mPaintSuppressionTimer) {
       mPaintingSuppressed = false;
     } else {
       // Initialize the timer.
 
       // Default to PAINTLOCK_EVENT_DELAY if we can't get the pref value.
       int32_t delay =
@@ -1973,17 +1973,17 @@ PresShell::ResizeReflowIgnoreOverride(ns
       }
     }
   }
 
   if (!mIsDestroying && !mResizeEvent.IsPending() &&
       !mAsyncResizeTimerIsActive) {
     if (mInResize) {
       if (!mAsyncResizeEventTimer) {
-        mAsyncResizeEventTimer = do_CreateInstance("@mozilla.org/timer;1");
+        mAsyncResizeEventTimer = NS_NewTimer();
       }
       if (mAsyncResizeEventTimer) {
         mAsyncResizeTimerIsActive = true;
         mAsyncResizeEventTimer->SetTarget(
             mDocument->EventTargetFor(TaskCategory::Other));
         mAsyncResizeEventTimer->InitWithNamedFuncCallback(AsyncResizeEventCallback,
                                                           this, 15,
                                                           nsITimer::TYPE_ONE_SHOT,
@@ -3660,24 +3660,23 @@ PresShell::ScheduleViewManagerFlush(Pain
           // The passed-in PresShell is always alive here. Because if PresShell
           // died, mDelayedPaintTimer->Cancel() would be called during the
           // destruction and this callback would never be invoked.
           auto self = static_cast<PresShell*>(aClosure);
           self->SetNextPaintCompressed();
           self->ScheduleViewManagerFlush();
       };
 
-      mDelayedPaintTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-      mDelayedPaintTimer->SetTarget(
-          mDocument->EventTargetFor(TaskCategory::Other));
-      mDelayedPaintTimer->InitWithNamedFuncCallback(PaintTimerCallBack,
-                                                    this,
-                                                    kPaintDelayPeriod,
-                                                    nsITimer::TYPE_ONE_SHOT,
-                                                    "PaintTimerCallBack");
+      NS_NewTimerWithFuncCallback(getter_AddRefs(mDelayedPaintTimer),
+                                  PaintTimerCallBack,
+                                  this,
+                                  kPaintDelayPeriod,
+                                  nsITimer::TYPE_ONE_SHOT,
+                                  "PaintTimerCallBack",
+                                  mDocument->EventTargetFor(TaskCategory::Other));
     }
     return;
   }
 
   nsPresContext* presContext = GetPresContext();
   if (presContext) {
     presContext->RefreshDriver()->ScheduleViewManagerFlush();
   }
@@ -8809,26 +8808,23 @@ PresShell::sReflowContinueCallback(nsITi
 
 bool
 PresShell::ScheduleReflowOffTimer()
 {
   NS_PRECONDITION(!mObservingLayoutFlushes, "Shouldn't get here");
   ASSERT_REFLOW_SCHEDULED_STATE();
 
   if (!mReflowContinueTimer) {
-    mReflowContinueTimer = do_CreateInstance("@mozilla.org/timer;1");
-    mReflowContinueTimer->SetTarget(
+    nsresult rv = NS_NewTimerWithFuncCallback(
+        getter_AddRefs(mReflowContinueTimer),
+        sReflowContinueCallback, this, 30,
+        nsITimer::TYPE_ONE_SHOT,
+        "sReflowContinueCallback",
         mDocument->EventTargetFor(TaskCategory::Other));
-    if (!mReflowContinueTimer ||
-        NS_FAILED(mReflowContinueTimer->
-                    InitWithNamedFuncCallback(sReflowContinueCallback, this, 30,
-                                              nsITimer::TYPE_ONE_SHOT,
-                                              "sReflowContinueCallback"))) {
-      return false;
-    }
+    return NS_SUCCEEDED(rv);
   }
   return true;
 }
 
 bool
 PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
 {
   gfxTextPerfMetrics* tp = mPresContext->GetTextPerfMetrics();
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -631,26 +631,26 @@ void nsCaret::ResetBlinking()
     // If the rate hasn't changed, then there is nothing to do.
     return;
   }
   mBlinkRate = blinkRate;
 
   if (mBlinkTimer) {
     mBlinkTimer->Cancel();
   } else {
-    nsresult  err;
-    mBlinkTimer = do_CreateInstance("@mozilla.org/timer;1", &err);
-    if (NS_FAILED(err)) {
-      return;
+    nsIEventTarget* target = nullptr;
+    if (nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell)) {
+      if (nsCOMPtr<nsIDocument> doc = presShell->GetDocument()) {
+        target = doc->EventTargetFor(TaskCategory::Other);
+      }
     }
 
-    if (nsCOMPtr<nsIPresShell> presShell = do_QueryReferent(mPresShell)) {
-      if (nsCOMPtr<nsIDocument> doc = presShell->GetDocument()) {
-        mBlinkTimer->SetTarget(doc->EventTargetFor(TaskCategory::Other));
-      }
+    mBlinkTimer = NS_NewTimer(target);
+    if (!mBlinkTimer) {
+      return;
     }
   }
 
   if (blinkRate > 0) {
     mBlinkCount = Preferences::GetInt("ui.caretBlinkCount", -1);
     mBlinkTimer->InitWithNamedFuncCallback(CaretBlinkCallback, this, blinkRate,
                                            nsITimer::TYPE_REPEATING_SLACK,
                                            "nsCaret::CaretBlinkCallback_timer");
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2793,28 +2793,23 @@ nsPresContext::HasCachedStyleData()
   return styleSet->HasCachedStyleData();
 }
 
 already_AddRefed<nsITimer>
 nsPresContext::CreateTimer(nsTimerCallbackFunc aCallback,
                            const char* aName,
                            uint32_t aDelay)
 {
-  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
-  timer->SetTarget(Document()->EventTargetFor(TaskCategory::Other));
-  if (timer) {
-    nsresult rv = timer->InitWithNamedFuncCallback(aCallback, this, aDelay,
-                                                   nsITimer::TYPE_ONE_SHOT,
-                                                   aName);
-    if (NS_SUCCEEDED(rv)) {
-      return timer.forget();
-    }
-  }
-
-  return nullptr;
+  nsCOMPtr<nsITimer> timer;
+  NS_NewTimerWithFuncCallback(getter_AddRefs(timer),
+                              aCallback, this, aDelay,
+                              nsITimer::TYPE_ONE_SHOT,
+                              aName,
+                              Document()->EventTargetFor(TaskCategory::Other));
+  return timer.forget();
 }
 
 static bool sGotInterruptEnv = false;
 enum InterruptMode {
   ModeRandom,
   ModeCounter,
   ModeEvent
 };
@@ -3441,31 +3436,30 @@ void
 nsRootPresContext::EnsureEventualDidPaintEvent(uint64_t aTransactionId)
 {
   for (NotifyDidPaintTimer& t : mNotifyDidPaintTimers) {
     if (t.mTransactionId == aTransactionId) {
       return;
     }
   }
 
-  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
-  timer->SetTarget(Document()->EventTargetFor(TaskCategory::Other));
-  if (timer) {
-    RefPtr<nsRootPresContext> self = this;
-    nsresult rv = timer->InitWithCallback(
-      NewNamedTimerCallback([self, aTransactionId](){
-        nsAutoScriptBlocker blockScripts;
-        self->NotifyDidPaintForSubtree(aTransactionId);
-    }, "NotifyDidPaintForSubtree"), 100, nsITimer::TYPE_ONE_SHOT);
-
-    if (NS_SUCCEEDED(rv)) {
-      NotifyDidPaintTimer* t = mNotifyDidPaintTimers.AppendElement();
-      t->mTransactionId = aTransactionId;
-      t->mTimer = timer;
-    }
+  nsCOMPtr<nsITimer> timer;
+  RefPtr<nsRootPresContext> self = this;
+  nsresult rv = NS_NewTimerWithCallback(
+    getter_AddRefs(timer),
+    NewNamedTimerCallback([self, aTransactionId](){
+      nsAutoScriptBlocker blockScripts;
+      self->NotifyDidPaintForSubtree(aTransactionId);
+     }, "NotifyDidPaintForSubtree"), 100, nsITimer::TYPE_ONE_SHOT,
+    Document()->EventTargetFor(TaskCategory::Other));
+
+  if (NS_SUCCEEDED(rv)) {
+    NotifyDidPaintTimer* t = mNotifyDidPaintTimers.AppendElement();
+    t->mTransactionId = aTransactionId;
+    t->mTimer = timer;
   }
 }
 
 void
 nsRootPresContext::CancelDidPaintTimers(uint64_t aTransactionId)
 {
   uint32_t i = 0;
   while (i < mNotifyDidPaintTimers.Length()) {
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -366,17 +366,17 @@ class SimpleTimerBasedRefreshDriverTimer
 {
 public:
   /*
    * aRate -- the delay, in milliseconds, requested between timer firings
    */
   explicit SimpleTimerBasedRefreshDriverTimer(double aRate)
   {
     SetRate(aRate);
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mTimer = NS_NewTimer();
   }
 
   virtual ~SimpleTimerBasedRefreshDriverTimer() override
   {
     StopTimer();
   }
 
   // will take effect at next timer tick
--- a/layout/generic/ScrollbarActivity.cpp
+++ b/layout/generic/ScrollbarActivity.cpp
@@ -423,17 +423,17 @@ ScrollbarActivity::SetIsFading(bool aNew
 
 void
 ScrollbarActivity::StartFadeBeginTimer()
 {
   if (GetForceAlwaysVisiblePref()) {
     return;
   }
   if (!mFadeBeginTimer) {
-    mFadeBeginTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mFadeBeginTimer = NS_NewTimer();
   }
   mFadeBeginTimer->InitWithNamedFuncCallback(
     FadeBeginTimerFired, this, mScrollbarFadeBeginDelay,
     nsITimer::TYPE_ONE_SHOT, "ScrollbarActivity::FadeBeginTimerFired");
 }
 
 void
 ScrollbarActivity::CancelFadeBeginTimer()
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2601,17 +2601,17 @@ void ScrollFrameHelper::TriggerDisplayPo
   }
 
   if (!gfxPrefs::APZDisplayPortExpiryTime()) {
     // a zero time disables the expiry
     return;
   }
 
   if (!mDisplayPortExpiryTimer) {
-    mDisplayPortExpiryTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mDisplayPortExpiryTimer = NS_NewTimer();
   }
   ResetDisplayPortExpiryTimer();
 }
 
 void ScrollFrameHelper::ScrollVisual()
 {
   // Mark this frame as having been scrolled. If this is the root
   // scroll frame of a content document, then IsAlwaysActive()
@@ -2721,23 +2721,21 @@ ScrollFrameHelper::ScrollActivityCallbac
   self->mOuter->PresContext()->PresShell()->SynthesizeMouseMove(true);
 }
 
 
 void
 ScrollFrameHelper::ScheduleSyntheticMouseMove()
 {
   if (!mScrollActivityTimer) {
-    mScrollActivityTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mScrollActivityTimer = NS_NewTimer(
+      mOuter->PresContext()->Document()->EventTargetFor(TaskCategory::Other));
     if (!mScrollActivityTimer) {
       return;
     }
-
-    mScrollActivityTimer->SetTarget(
-      mOuter->PresContext()->Document()->EventTargetFor(TaskCategory::Other));
   }
 
   mScrollActivityTimer->InitWithNamedFuncCallback(
     ScrollActivityCallback,
     this,
     100,
     nsITimer::TYPE_ONE_SHOT,
     "ScrollFrameHelper::ScheduleSyntheticMouseMove");
@@ -3387,28 +3385,30 @@ ScrollFrameHelper::BuildDisplayList(nsDi
     !(mIsRoot && mOuter->PresContext()->PresShell()->GetIsViewportOverridden());
 
   // Whether we might want to build a scrollable layer for this scroll frame
   // at some point in the future. This controls whether we add the information
   // to the layer tree (a scroll info layer if necessary, and add the right
   // area to the dispatch to content layer event regions) necessary to activate
   // a scroll frame so it creates a scrollable layer.
   bool couldBuildLayer = false;
-  if (mWillBuildScrollableLayer) {
-    couldBuildLayer = true;
-  } else {
-    couldBuildLayer =
-      nsLayoutUtils::AsyncPanZoomEnabled(mOuter) &&
-      WantAsyncScroll() &&
-      // If we are using containers for root frames, and we are the root
-      // scroll frame for the display root, then we don't need a scroll
-      // info layer. nsDisplayList::PaintForFrame already calls
-      // ComputeFrameMetrics for us.
-      (!(gfxPrefs::LayoutUseContainersForRootFrames() && mIsRoot) ||
-       (aBuilder->RootReferenceFrame()->PresContext() != mOuter->PresContext()));
+  if (aBuilder->IsPaintingToWindow()) {
+    if (mWillBuildScrollableLayer) {
+      couldBuildLayer = true;
+    } else {
+      couldBuildLayer =
+        nsLayoutUtils::AsyncPanZoomEnabled(mOuter) &&
+        WantAsyncScroll() &&
+        // If we are using containers for root frames, and we are the root
+        // scroll frame for the display root, then we don't need a scroll
+        // info layer. nsDisplayList::PaintForFrame already calls
+        // ComputeFrameMetrics for us.
+        (!(gfxPrefs::LayoutUseContainersForRootFrames() && mIsRoot) ||
+         (aBuilder->RootReferenceFrame()->PresContext() != mOuter->PresContext()));
+    }
   }
 
   // Now display the scrollbars and scrollcorner. These parts are drawn
   // in the border-background layer, on top of our own background and
   // borders and underneath borders and backgrounds of later elements
   // in the tree.
   // Note that this does not apply for overlay scrollbars; those are drawn
   // in the positioned-elements layer on top of everything else by the call
@@ -3500,33 +3500,33 @@ ScrollFrameHelper::BuildDisplayList(nsDi
       if (mClipAllDescendants) {
         contentBoxClipState->ClipContentDescendants(*contentBoxClip);
       } else {
         contentBoxClipState->ClipContainingBlockDescendants(*contentBoxClip);
       }
     }
 
     nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter asrSetter(aBuilder);
-    if (mWillBuildScrollableLayer) {
+    if (mWillBuildScrollableLayer && aBuilder->IsPaintingToWindow()) {
       asrSetter.EnterScrollFrame(sf);
     }
 
     if (mIsScrollableLayerInRootContainer) {
       aBuilder->SetActiveScrolledRootForRootScrollframe(aBuilder->CurrentActiveScrolledRoot());
     }
 
     {
       // Clip our contents to the unsnapped scrolled rect. This makes sure that
       // we don't have display items over the subpixel seam at the edge of the
       // scrolled area.
       DisplayListClipState::AutoSaveRestore scrolledRectClipState(aBuilder);
       nsRect scrolledRectClip =
         GetUnsnappedScrolledRectInternal(mScrolledFrame->GetScrollableOverflowRect(),
                                          mScrollPort.Size()) + mScrolledFrame->GetPosition();
-      if (mWillBuildScrollableLayer) {
+      if (mWillBuildScrollableLayer && aBuilder->IsPaintingToWindow()) {
         // Clip the contents to the display port.
         // The dirty rect already acts kind of like a clip, in that
         // FrameLayerBuilder intersects item bounds and opaque regions with
         // it, but it doesn't have the consistent snapping behavior of a
         // true clip.
         // For a case where this makes a difference, imagine the following
         // scenario: The display port has an edge that falls on a fractional
         // layer pixel, and there's an opaque display item that covers the
@@ -3564,17 +3564,18 @@ ScrollFrameHelper::BuildDisplayList(nsDi
     if (idSetter.ShouldForceLayerForScrollParent() &&
         !gfxPrefs::LayoutUseContainersForRootFrames())
     {
       // Note that forcing layerization of scroll parents follows the scroll
       // handoff chain which is subject to the out-of-flow-frames caveat noted
       // above (where the idSetter variable is created).
       //
       // This is not compatible when using containes for root scrollframes.
-      MOZ_ASSERT(couldBuildLayer && mScrolledFrame->GetContent());
+      MOZ_ASSERT(couldBuildLayer && mScrolledFrame->GetContent() &&
+        aBuilder->IsPaintingToWindow());
       if (!mWillBuildScrollableLayer) {
         // Set a displayport so next paint we don't have to force layerization
         // after the fact.
         nsLayoutUtils::SetDisplayPortMargins(mOuter->GetContent(),
                                              mOuter->PresContext()->PresShell(),
                                              ScreenMargin(),
                                              0,
                                              nsLayoutUtils::RepaintMode::DoNotRepaint);
@@ -3586,17 +3587,17 @@ ScrollFrameHelper::BuildDisplayList(nsDi
                     /* aSetBase = */ false);
         if (mWillBuildScrollableLayer) {
           asrSetter.InsertScrollFrame(sf);
         }
       }
     }
   }
 
-  if (mWillBuildScrollableLayer) {
+  if (mWillBuildScrollableLayer && aBuilder->IsPaintingToWindow()) {
     aBuilder->ForceLayerForScrollParent();
   }
 
   if (couldBuildLayer) {
     // Make sure that APZ will dispatch events back to content so we can create
     // a displayport for this frame. We'll add the item later on.
     nsDisplayLayerEventRegions* inactiveRegionItem = nullptr;
     if (aBuilder->IsPaintingToWindow() &&
@@ -5052,33 +5053,37 @@ ScrollFrameHelper::IsScrollbarOnRight() 
 bool
 ScrollFrameHelper::IsMaybeScrollingActive() const
 {
   const nsStyleDisplay* disp = mOuter->StyleDisplay();
   if (disp && (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_SCROLL)) {
     return true;
   }
 
+  nsIContent* content = mOuter->GetContent();
   return mHasBeenScrolledRecently ||
          IsAlwaysActive() ||
-         mWillBuildScrollableLayer;
+         nsLayoutUtils::HasDisplayPort(content) ||
+         nsContentUtils::HasScrollgrab(content);
 }
 
 bool
 ScrollFrameHelper::IsScrollingActive(nsDisplayListBuilder* aBuilder) const
 {
   const nsStyleDisplay* disp = mOuter->StyleDisplay();
   if (disp && (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_SCROLL) &&
     aBuilder->IsInWillChangeBudget(mOuter, GetScrollPositionClampingScrollPortSize())) {
     return true;
   }
 
+  nsIContent* content = mOuter->GetContent();
   return mHasBeenScrolledRecently ||
          IsAlwaysActive() ||
-         mWillBuildScrollableLayer;
+         nsLayoutUtils::HasDisplayPort(content) ||
+         nsContentUtils::HasScrollgrab(content);
 }
 
 /**
  * Reflow the scroll area if it needs it and return its size. Also determine if the reflow will
  * cause any of the scrollbars to need to be reflowed.
  */
 nsresult
 nsXULScrollFrame::XULLayout(nsBoxLayoutState& aState)
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -399,17 +399,18 @@ nsSubDocumentFrame::BuildDisplayList(nsD
       nsIScrollableFrame* rootScrollableFrame = presShell->GetRootScrollFrameAsScrollable();
       MOZ_ASSERT(rootScrollableFrame);
       // Use a copy, so the rects don't get modified.
       nsRect copyOfDirty = dirty;
       haveDisplayPort = rootScrollableFrame->DecideScrollableLayer(aBuilder,
                           &copyOfDirty,
                           /* aSetBase = */ true);
 
-      if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
+      if (!gfxPrefs::LayoutUseContainersForRootFrames() ||
+          !aBuilder->IsPaintingToWindow()) {
         haveDisplayPort = false;
       }
 
       ignoreViewportScrolling = presShell->IgnoringViewportScrolling();
       if (ignoreViewportScrolling) {
         savedIgnoreScrollFrame = aBuilder->GetIgnoreScrollFrame();
         aBuilder->SetIgnoreScrollFrame(rootScrollFrame);
       }
--- a/layout/generic/test/mochitest.ini
+++ b/layout/generic/test/mochitest.ini
@@ -92,16 +92,17 @@ support-files = bug633762_iframe.html
 [test_bug904810.html]
 [test_bug938772.html]
 [test_bug970363.html]
 [test_bug1062406.html]
 [test_bug1174521.html]
 [test_bug1198135.html]
 [test_bug1307853.html]
 support-files = file_bug1307853.html
+[test_bug1408607.html]
 [test_contained_plugin_transplant.html]
 skip-if = os=='win'
 [test_image_selection.html]
 [test_image_selection_2.html]
 [test_invalidate_during_plugin_paint.html]
 skip-if = toolkit == 'android'
 [test_intrinsic_size_on_loading.html]
 [test_movement_by_characters.html]
@@ -119,17 +120,17 @@ skip-if = e10s
 skip-if = e10s
 [test_plugin_clipping_transformed.xhtml]
 skip-if = e10s
 [test_plugin_clipping_table.xhtml]
 skip-if = e10s
 [test_plugin_focus.html]
 skip-if  = os == 'win' # bug 1207918
 [test_plugin_mouse_coords.html]
-skip-if = toolkit == 'android'
+skip-if = toolkit == 'android' || headless # Headless:Bug 1405871
 [test_plugin_position.xhtml]
 skip-if = e10s
 [test_scroll_behavior.html]
 [test_selection_expanding.html]
 support-files = selection_expanding_xbl.xml
 [test_selection_preventDefault.html]
 [test_selection_splitText-normalize.html]
 [test_selection_touchevents.html]
new file mode 100644
--- /dev/null
+++ b/layout/generic/test/test_bug1408607.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1408607
+-->
+<head>
+  <title>Test for Bug 1408607</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1408607">Mozilla Bug 1408607</a>
+<iframe id="display" src="about:blank"></iframe>
+<div id="content" style="display: none">
+
+</div>
+
+<div style="margin-left: 1%; border: 1px solid black;">
+  <div style="height: 200px; overflow: auto; transform: translateZ(0);">
+    <div style="height: 100px;"></div>
+    <a id="x" href="./">Hello</a>
+    <div style="height: 500px;"></div>
+  </div>
+</div
+
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+window.addEventListener("load", step1);
+
+
+function step1()
+{
+  var rect = document.getElementById("x").getBoundingClientRect();
+  
+  is(document.elementFromPoint(rect.x + rect.width/2, rect.y + rect.height/2), document.getElementById("x"), "Able to hit transformed object");
+  SimpleTest.finish();
+}
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/layout/printing/nsPagePrintTimer.cpp
+++ b/layout/printing/nsPagePrintTimer.cpp
@@ -24,54 +24,42 @@ nsPagePrintTimer::~nsPagePrintTimer()
   if (cv) {
     cv->Destroy();
   }
 }
 
 nsresult
 nsPagePrintTimer::StartTimer(bool aUseDelay)
 {
-  nsresult result;
-  mTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
-  if (NS_FAILED(result)) {
-    NS_WARNING("unable to start the timer");
-  } else {
-    uint32_t delay = 0;
-    if (aUseDelay) {
-      if (mFiringCount < 10) {
-        // Longer delay for the few first pages.
-        delay = mDelay + ((10 - mFiringCount) * 100);
-      } else {
-        delay = mDelay;
-      }
+  uint32_t delay = 0;
+  if (aUseDelay) {
+    if (mFiringCount < 10) {
+      // Longer delay for the few first pages.
+      delay = mDelay + ((10 - mFiringCount) * 100);
+    } else {
+      delay = mDelay;
     }
-    mTimer->SetTarget(mDocument->EventTargetFor(TaskCategory::Other));
-    mTimer->InitWithCallback(this, delay, nsITimer::TYPE_ONE_SHOT);
   }
-  return result;
+  return NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                                 this, delay, nsITimer::TYPE_ONE_SHOT,
+                                 mDocument->EventTargetFor(TaskCategory::Other));
 }
 
 nsresult
 nsPagePrintTimer::StartWatchDogTimer()
 {
-  nsresult result;
   if (mWatchDogTimer) {
     mWatchDogTimer->Cancel();
   }
-  mWatchDogTimer = do_CreateInstance("@mozilla.org/timer;1", &result);
-  if (NS_FAILED(result)) {
-    NS_WARNING("unable to start the timer");
-  } else {
-    // Instead of just doing one timer for a long period do multiple so we
-    // can check if the user cancelled the printing.
-    mWatchDogTimer->SetTarget(mDocument->EventTargetFor(TaskCategory::Other));
-    mWatchDogTimer->InitWithCallback(this, WATCH_DOG_INTERVAL,
-                                     nsITimer::TYPE_ONE_SHOT);
-  }
-  return result;
+  // Instead of just doing one timer for a long period do multiple so we
+  // can check if the user cancelled the printing.
+  return NS_NewTimerWithCallback(getter_AddRefs(mWatchDogTimer),
+                                 this, WATCH_DOG_INTERVAL,
+                                 nsITimer::TYPE_ONE_SHOT,
+                                 mDocument->EventTargetFor(TaskCategory::Other));
 }
 
 void
 nsPagePrintTimer::StopWatchDogTimer()
 {
   if (mWatchDogTimer) {
     mWatchDogTimer->Cancel();
     mWatchDogTimer = nullptr;
@@ -174,21 +162,19 @@ nsPagePrintTimer::Notify(nsITimer *timer
   }
   return NS_OK;
 }
 
 
 void
 nsPagePrintTimer::WaitForRemotePrint()
 {
-  nsresult result;
-  mWaitingForRemotePrint = do_CreateInstance("@mozilla.org/timer;1", &result);
-  if (NS_FAILED(result)) {
+  mWaitingForRemotePrint = NS_NewTimer();
+  if (!mWaitingForRemotePrint) {
     NS_WARNING("Failed to wait for remote print, we might time-out.");
-    mWaitingForRemotePrint = nullptr;
   }
 }
 
 void
 nsPagePrintTimer::RemotePrintFinished()
 {
   if (!mWaitingForRemotePrint) {
     return;
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -84,26 +84,23 @@ nsFontFaceLoader::StartedLoading(nsIStre
   if (fontDisplay == NS_FONT_DISPLAY_AUTO ||
       fontDisplay == NS_FONT_DISPLAY_BLOCK) {
     loadTimeout = GetFallbackDelay();
   } else {
     loadTimeout = GetShortFallbackDelay();
   }
 
   if (loadTimeout > 0) {
-    mLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
-    if (mLoadTimer) {
-      mLoadTimer->SetTarget(
-        mFontFaceSet->Document()->EventTargetFor(TaskCategory::Other));
-      mLoadTimer->InitWithNamedFuncCallback(LoadTimerCallback,
-                                            static_cast<void*>(this),
-                                            loadTimeout,
-                                            nsITimer::TYPE_ONE_SHOT,
-                                            "LoadTimerCallback");
-    }
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mLoadTimer),
+                                LoadTimerCallback,
+                                static_cast<void*>(this),
+                                loadTimeout,
+                                nsITimer::TYPE_ONE_SHOT,
+                                "LoadTimerCallback",
+                                mFontFaceSet->Document()->EventTargetFor(TaskCategory::Other));
   } else {
     mUserFontEntry->mFontDataLoadingState = gfxUserFontEntry::LOADING_SLOWLY;
   }
   mStreamLoader = aStreamLoader;
 }
 
 /* static */ void
 nsFontFaceLoader::LoadTimerCallback(nsITimer* aTimer, void* aClosure)
--- a/layout/style/res/forms.css
+++ b/layout/style/res/forms.css
@@ -1122,16 +1122,17 @@ input[type=number]::-moz-number-spin-dow
 input[type="number"] > div > div > div:hover {
   /* give some indication of hover state for the up/down buttons */
   background-color: lightblue;
 }
 
 input[type="date"],
 input[type="time"] {
   overflow: hidden !important;
+  font-family: -moz-fixed;
 }
 
 :-moz-autofill, :-moz-autofill-preview {
   filter: grayscale(21%) brightness(88%) contrast(161%) invert(10%) sepia(40%) saturate(206%);
 }
 :-moz-autofill-preview {
   color: GrayText;
 }
--- a/layout/xul/nsListBoxBodyFrame.cpp
+++ b/layout/xul/nsListBoxBodyFrame.cpp
@@ -117,30 +117,29 @@ nsListScrollSmoother::Start()
     NS_ASSERTION(self->mOuter, "mOuter is null, see bug #68365");
     if (self->mOuter) {
       // actually do some work.
       self->mOuter->InternalPositionChangedCallback();
     }
   };
 
   Stop();
-  mRepeatTimer = do_CreateInstance("@mozilla.org/timer;1");
-  nsIContent* content = nullptr;
+  nsIEventTarget* target = nullptr;
   if (mOuter) {
-    content = mOuter->GetContent();
+    if (nsIContent* content = mOuter->GetContent()) {
+      target = content->OwnerDoc()->EventTargetFor(TaskCategory::Other);
+    }
   }
-  if (content) {
-    mRepeatTimer->SetTarget(
-        content->OwnerDoc()->EventTargetFor(TaskCategory::Other));
-  }
-  mRepeatTimer->InitWithNamedFuncCallback(scrollSmootherCallback,
-                                          this,
-                                          SMOOTH_INTERVAL,
-                                          nsITimer::TYPE_ONE_SHOT,
-                                          "scrollSmootherCallback");
+  NS_NewTimerWithFuncCallback(getter_AddRefs(mRepeatTimer),
+                              scrollSmootherCallback,
+                              this,
+                              SMOOTH_INTERVAL,
+                              nsITimer::TYPE_ONE_SHOT,
+                              "scrollSmootherCallback",
+                              target);
 }
 
 void
 nsListScrollSmoother::Stop()
 {
   if ( mRepeatTimer ) {
     mRepeatTimer->Cancel();
     mRepeatTimer = nullptr;
--- a/layout/xul/nsMenuFrame.cpp
+++ b/layout/xul/nsMenuFrame.cpp
@@ -523,20 +523,19 @@ nsMenuFrame::HandleEvent(nsPresContext* 
     // A timer is used so that it doesn't open if the user moves the mouse quickly
     // past the menu. This conditional check ensures that only menus have this
     // behaviour
     if (!IsDisabled() && IsMenu() && !IsOpen() && !mOpenTimer && !menuParent->IsMenuBar()) {
       int32_t menuDelay =
         LookAndFeel::GetInt(LookAndFeel::eIntID_SubmenuDelay, 300); // ms
 
       // We're a menu, we're built, we're closed, and no timer has been kicked off.
-      mOpenTimer = do_CreateInstance("@mozilla.org/timer;1");
-      mOpenTimer->SetTarget(
-          mContent->OwnerDoc()->EventTargetFor(TaskCategory::Other));
-      mOpenTimer->InitWithCallback(mTimerMediator, menuDelay, nsITimer::TYPE_ONE_SHOT);
+      NS_NewTimerWithCallback(getter_AddRefs(mOpenTimer),
+                              mTimerMediator, menuDelay, nsITimer::TYPE_ONE_SHOT,
+                              mContent->OwnerDoc()->EventTargetFor(TaskCategory::Other));
     }
   }
 
   return NS_OK;
 }
 
 void
 nsMenuFrame::ToggleMenuState()
@@ -1237,20 +1236,19 @@ nsMenuFrame::StartBlinking(WidgetGUIEven
 
   nsMenuParent* menuParent = GetMenuParent();
   if (menuParent) {
     // Make this menu ignore events from now on.
     menuParent->LockMenuUntilClosed(true);
   }
 
   // Set up a timer to blink back on.
-  mBlinkTimer = do_CreateInstance("@mozilla.org/timer;1");
-  mBlinkTimer->SetTarget(
-      mContent->OwnerDoc()->EventTargetFor(TaskCategory::Other));
-  mBlinkTimer->InitWithCallback(mTimerMediator, kBlinkDelay, nsITimer::TYPE_ONE_SHOT);
+  NS_NewTimerWithCallback(getter_AddRefs(mBlinkTimer),
+                          mTimerMediator, kBlinkDelay, nsITimer::TYPE_ONE_SHOT,
+                          mContent->OwnerDoc()->EventTargetFor(TaskCategory::Other));
   mBlinkState = 1;
 }
 
 void
 nsMenuFrame::StopBlinking()
 {
   mBlinkState = 0;
   if (mBlinkTimer) {
--- a/layout/xul/nsRepeatService.cpp
+++ b/layout/xul/nsRepeatService.cpp
@@ -50,21 +50,20 @@ nsRepeatService::Start(Callback aCallbac
                        uint32_t aInitialDelay)
 {
   NS_PRECONDITION(aCallback != nullptr, "null ptr");
 
   mCallback = aCallback;
   mCallbackData = aCallbackData;
   mCallbackName = aCallbackName;
 
-  nsresult rv;
-  mRepeatTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
+  mRepeatTimer = NS_NewTimer(
+    aDocument->EventTargetFor(TaskCategory::Other));
 
-  if (NS_SUCCEEDED(rv))  {
-    mRepeatTimer->SetTarget(aDocument->EventTargetFor(TaskCategory::Other));
+  if (mRepeatTimer)  {
     InitTimerCallback(aInitialDelay);
   }
 }
 
 void nsRepeatService::Stop(Callback aCallback, void* aCallbackData)
 {
   if (mCallback != aCallback || mCallbackData != aCallbackData)
     return;
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -10,16 +10,18 @@
 #include "nsMenuBarFrame.h"
 #include "nsMenuBarListener.h"
 #include "nsContentUtils.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMEvent.h"
 #include "nsXULElement.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIXULDocument.h"
+#include "nsIDOMXULDocument.h"
+#include "nsIDOMXULCommandDispatcher.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsCSSFrameConstructor.h"
 #include "nsGlobalWindow.h"
 #include "nsLayoutUtils.h"
 #include "nsViewManager.h"
 #include "nsIComponentManager.h"
 #include "nsITimer.h"
 #include "nsFocusManager.h"
@@ -1238,28 +1240,29 @@ nsXULPopupManager::HidePopupAfterDelay(n
   // Don't close up immediately.
   // Kick off a close timer.
   KillMenuTimer();
 
   int32_t menuDelay =
     LookAndFeel::GetInt(LookAndFeel::eIntID_SubmenuDelay, 300); // ms
 
   // Kick off the timer.
-  mCloseTimer = do_CreateInstance("@mozilla.org/timer;1");
-  nsIContent* content = aPopup->GetContent();
-  if (content) {
-    mCloseTimer->SetTarget(
-        content->OwnerDoc()->EventTargetFor(TaskCategory::Other));
+  nsIEventTarget* target = nullptr;
+  if (nsIContent* content = aPopup->GetContent()) {
+    target = content->OwnerDoc()->EventTargetFor(TaskCategory::Other);
   }
-  mCloseTimer->InitWithNamedFuncCallback([](nsITimer* aTimer, void* aClosure) {
-    nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
-    if (pm) {
-      pm->KillMenuTimer();
-    }
-  }, nullptr, menuDelay, nsITimer::TYPE_ONE_SHOT, "KillMenuTimer");
+  NS_NewTimerWithFuncCallback(
+    getter_AddRefs(mCloseTimer),
+    [](nsITimer* aTimer, void* aClosure) {
+      nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+      if (pm) {
+        pm->KillMenuTimer();
+      }
+    }, nullptr, menuDelay, nsITimer::TYPE_ONE_SHOT, "KillMenuTimer",
+    target);
 
   // the popup will call PopupDestroyed if it is destroyed, which checks if it
   // is set to mTimerMenu, so it should be safe to keep a reference to it
   mTimerMenu = aPopup;
 }
 
 void
 nsXULPopupManager::HidePopupsInList(const nsTArray<nsMenuPopupFrame *> &aFrames)
@@ -1969,16 +1972,26 @@ nsXULPopupManager::UpdateMenuItems(nsICo
   // Walk all of the menu's children, checking to see if any of them has a
   // command attribute. If so, then several attributes must potentially be updated.
 
   nsCOMPtr<nsIDocument> document = aPopup->GetUncomposedDoc();
   if (!document) {
     return;
   }
 
+  // When a menu is opened, make sure that command updating is unlocked first.
+  nsCOMPtr<nsIDOMXULDocument> xulDoc = do_QueryInterface(document);
+  if (xulDoc) {
+    nsCOMPtr<nsIDOMXULCommandDispatcher> xulCommandDispatcher;
+    xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher));
+    if (xulCommandDispatcher) {
+      xulCommandDispatcher->Unlock();
+    }
+  }
+
   for (nsCOMPtr<nsIContent> grandChild = aPopup->GetFirstChild();
        grandChild;
        grandChild = grandChild->GetNextSibling()) {
     if (grandChild->IsXULElement(nsGkAtoms::menugroup)) {
       if (grandChild->GetChildCount() == 0) {
         continue;
       }
       grandChild = grandChild->GetFirstChild();
--- a/layout/xul/nsXULTooltipListener.cpp
+++ b/layout/xul/nsXULTooltipListener.cpp
@@ -190,31 +190,28 @@ nsXULTooltipListener::MouseMove(nsIDOMEv
           mSourceNode = nullptr;
           return;
         }
 
         targetContent = targetContent->GetParent();
       }
     }
 
-    mTooltipTimer = do_CreateInstance("@mozilla.org/timer;1");
-    mTooltipTimer->SetTarget(
+    mTargetNode = do_GetWeakReference(eventTarget);
+    if (mTargetNode) {
+      nsresult rv = NS_NewTimerWithFuncCallback(
+        getter_AddRefs(mTooltipTimer),
+        sTooltipCallback, this,
+        LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
+        nsITimer::TYPE_ONE_SHOT,
+        "sTooltipCallback",
         sourceContent->OwnerDoc()->EventTargetFor(TaskCategory::Other));
-    if (mTooltipTimer) {
-      mTargetNode = do_GetWeakReference(eventTarget);
-      if (mTargetNode) {
-        nsresult rv =
-          mTooltipTimer->InitWithNamedFuncCallback(sTooltipCallback, this,
-            LookAndFeel::GetInt(LookAndFeel::eIntID_TooltipDelay, 500),
-            nsITimer::TYPE_ONE_SHOT,
-            "sTooltipCallback");
-        if (NS_FAILED(rv)) {
-          mTargetNode = nullptr;
-          mSourceNode = nullptr;
-        }
+      if (NS_FAILED(rv)) {
+        mTargetNode = nullptr;
+        mSourceNode = nullptr;
       }
     }
     return;
   }
 
 #ifdef MOZ_XUL
   if (mIsSourceTree)
     return;
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/ContentEvents.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/MouseEvents.h"
+#include "mozilla/ResultExtensions.h"
 #include "mozilla/TextEditRules.h"
 
 #include "gfxUtils.h"
 #include "nsAlgorithm.h"
 #include "nsCOMPtr.h"
 #include "nsFontMetrics.h"
 #include "nsPresContext.h"
 #include "nsNameSpaceManager.h"
@@ -1805,26 +1806,22 @@ nsTreeBodyFrame::CreateTimer(const LookA
   // Get the delay from the look and feel service.
   int32_t delay = LookAndFeel::GetInt(aID, 0);
 
   nsCOMPtr<nsITimer> timer;
 
   // Create a new timer only if the delay is greater than zero.
   // Zero value means that this feature is completely disabled.
   if (delay > 0) {
-    timer = do_CreateInstance("@mozilla.org/timer;1");
-    if (timer) {
-      timer->SetTarget(
-          mContent->OwnerDoc()->EventTargetFor(TaskCategory::Other));
-      timer->InitWithNamedFuncCallback(aFunc, this, delay, aType, aName);
-    }
+    MOZ_TRY_VAR(timer, NS_NewTimerWithFuncCallback(
+        aFunc, this, delay, aType, aName,
+        mContent->OwnerDoc()->EventTargetFor(TaskCategory::Other)));
   }
 
-  NS_IF_ADDREF(*aTimer = timer);
-
+  timer.forget(aTimer);
   return NS_OK;
 }
 
 nsresult
 nsTreeBodyFrame::RowCountChanged(int32_t aIndex, int32_t aCount)
 {
   if (aCount == 0 || !mView)
     return NS_OK; // Nothing to do.
--- a/layout/xul/tree/nsTreeSelection.cpp
+++ b/layout/xul/tree/nsTreeSelection.cpp
@@ -325,25 +325,25 @@ NS_IMETHODIMP nsTreeSelection::TimedSele
     return rv;
 
   if (aMsec != -1) {
     mSuppressed = suppressSelect;
     if (!mSuppressed) {
       if (mSelectTimer)
         mSelectTimer->Cancel();
 
-      mSelectTimer = do_CreateInstance("@mozilla.org/timer;1");
-      nsCOMPtr<nsIContent> content = GetContent();
-      if (content) {
-        mSelectTimer->SetTarget(
-            content->OwnerDoc()->EventTargetFor(TaskCategory::Other));
+      nsIEventTarget* target = nullptr;
+      if (nsCOMPtr<nsIContent> content = GetContent()) {
+        target = content->OwnerDoc()->EventTargetFor(TaskCategory::Other);
       }
-      mSelectTimer->InitWithNamedFuncCallback(SelectCallback, this, aMsec,
-                                              nsITimer::TYPE_ONE_SHOT,
-                                              "nsTreeSelection::SelectCallback");
+      NS_NewTimerWithFuncCallback(getter_AddRefs(mSelectTimer),
+                                  SelectCallback, this, aMsec,
+                                  nsITimer::TYPE_ONE_SHOT,
+                                  "nsTreeSelection::SelectCallback",
+                                  target);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsTreeSelection::Select(int32_t aIndex)
 {
--- a/media/mtransport/nr_timer.cpp
+++ b/media/mtransport/nr_timer.cpp
@@ -202,24 +202,22 @@ static int nr_async_timer_set_zero(NR_as
 }
 
 static int nr_async_timer_set_nonzero(int timeout, NR_async_cb cb, void *arg,
                                       char *func, int l,
                                       nrappkitCallback **handle) {
   nsresult rv;
   CheckSTSThread();
 
-  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  if (NS_FAILED(rv)) {
-    return(R_FAILED);
-  }
-
   nrappkitTimerCallback* callback =
       new nrappkitTimerCallback(cb, arg, func, l);
-  rv = timer->InitWithCallback(callback, timeout, nsITimer::TYPE_ONE_SHOT);
+
+  nsCOMPtr<nsITimer> timer;
+  rv = NS_NewTimerWithCallback(getter_AddRefs(timer),
+                               callback, timeout, nsITimer::TYPE_ONE_SHOT);
   if (NS_FAILED(rv)) {
     return R_FAILED;
   }
 
   // Move the ownership of the timer to the callback object, which holds the
   // timer alive per spec.
   callback->SetTimer(timer.forget());
 
--- a/media/mtransport/test/sctp_unittest.cpp
+++ b/media/mtransport/test/sctp_unittest.cpp
@@ -63,17 +63,17 @@ class TransportTestPeer : public sigslot
  public:
   TransportTestPeer(std::string name, int local_port, int remote_port,
                     MtransportTestUtils* utils)
       : name_(name), connected_(false),
         sent_(0), received_(0),
         flow_(new TransportFlow()),
         loopback_(new TransportLayerLoopback()),
         sctp_(usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, receive_cb, nullptr, 0, nullptr)),
-        timer_(do_CreateInstance(NS_TIMER_CONTRACTID)),
+        timer_(NS_NewTimer()),
         periodic_(nullptr),
         test_utils_(utils) {
     std::cerr << "Creating TransportTestPeer; flow=" <<
         static_cast<void *>(flow_.get()) <<
         " local=" << local_port <<
         " remote=" << remote_port << std::endl;
 
     usrsctp_register_address(static_cast<void *>(this));
--- a/media/mtransport/transportlayerdtls.cpp
+++ b/media/mtransport/transportlayerdtls.cpp
@@ -384,18 +384,18 @@ nsresult TransportLayerDtls::InitInterna
   nsresult rv;
   target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
 
   if (NS_FAILED(rv)) {
     MOZ_MTLOG(ML_ERROR, "Couldn't get socket transport service");
     return rv;
   }
 
-  timer_ = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  if (NS_FAILED(rv)) {
+  timer_ = NS_NewTimer();
+  if (!timer_) {
     MOZ_MTLOG(ML_ERROR, "Couldn't get timer");
     return rv;
   }
 
   return NS_OK;
 }
 
 
--- a/media/mtransport/transportlayerloopback.cpp
+++ b/media/mtransport/transportlayerloopback.cpp
@@ -24,28 +24,26 @@
 #include "transportflow.h"
 #include "transportlayerloopback.h"
 
 namespace mozilla {
 
 MOZ_MTLOG_MODULE("mtransport")
 
 nsresult TransportLayerLoopback::Init() {
-  timer_ = do_CreateInstance(NS_TIMER_CONTRACTID);
-  MOZ_ASSERT(timer_);
-  if (!timer_)
-    return NS_ERROR_FAILURE;
-
   nsresult rv;
   target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
   if (!NS_SUCCEEDED(rv))
     return rv;
 
-  timer_->SetTarget(target_);
+  timer_ = NS_NewTimer(target_);
+  MOZ_ASSERT(timer_);
+  if (!timer_)
+    return NS_ERROR_FAILURE;
 
   packets_lock_ = PR_NewLock();
   MOZ_ASSERT(packets_lock_);
   if (!packets_lock_)
     return NS_ERROR_FAILURE;
 
   deliverer_ = new Deliverer(this);
 
--- a/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp
+++ b/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp
@@ -84,21 +84,21 @@ public:
 
   FakeAudioStreamTrack()
     : AudioStreamTrack(new DOMMediaStream(nullptr, nullptr), 0, 1,
                        new FakeMediaStreamTrackSource())
     , mMutex("Fake AudioStreamTrack")
     , mStop(false)
     , mCount(0)
   {
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    mTimer->SetTarget(test_utils->sts_target());
-    mTimer->InitWithNamedFuncCallback(FakeAudioStreamTrackGenerateData, this, 20,
-                                      nsITimer::TYPE_REPEATING_SLACK,
-                                      "FakeAudioStreamTrack::FakeAudioStreamTrackGenerateData");
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+                                FakeAudioStreamTrackGenerateData, this, 20,
+                                nsITimer::TYPE_REPEATING_SLACK,
+                                "FakeAudioStreamTrack::FakeAudioStreamTrackGenerateData",
+                                test_utils->sts_target());
 
   }
 
   void Stop()
   {
     mozilla::MutexAutoLock lock(mMutex);
     mStop = true;
     mTimer->Cancel();
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -269,17 +269,17 @@ WebrtcVideoConduit::WebrtcVideoConduit(R
   , mCodecMode(webrtc::kRealtimeVideo)
   , mCall(aCall) // refcounted store of the call object
   , mSendStreamConfig(this) // 'this' is stored but not  dereferenced in the constructor.
   , mRecvStreamConfig(this) // 'this' is stored but not  dereferenced in the constructor.
   , mRecvSSRC(0)
   , mRecvSSRCSetInProgress(false)
   , mSendCodecPlugin(nullptr)
   , mRecvCodecPlugin(nullptr)
-  , mVideoStatsTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
+  , mVideoStatsTimer(NS_NewTimer())
 {
   mRecvStreamConfig.renderer = this;
 
   // Video Stats Callback
   nsTimerCallbackFunc callback = [](nsITimer* aTimer, void* aClosure) {
     CSFLogDebug(LOGTAG, "StreamStats polling scheduled for VideoConduit: %p", aClosure);
     auto self = static_cast<WebrtcVideoConduit*>(aClosure);
     MutexAutoLock lock(self->mCodecMutex);
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
@@ -365,23 +365,22 @@ PeerConnectionCtx::UpdateNetworkState(bo
   for (auto pc : ctx->mPeerConnections) {
     pc.second->UpdateNetworkState(online);
   }
 }
 
 nsresult PeerConnectionCtx::Initialize() {
   initGMP();
 
-  mTelemetryTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  MOZ_ASSERT(mTelemetryTimer);
-  nsresult rv = mTelemetryTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::Other));
+  nsresult rv = NS_NewTimerWithFuncCallback(getter_AddRefs(mTelemetryTimer),
+                                            EverySecondTelemetryCallback_m, this, 1000,
+                                            nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP,
+                                            "EverySecondTelemetryCallback_m",
+                                            SystemGroup::EventTargetFor(TaskCategory::Other));
   NS_ENSURE_SUCCESS(rv, rv);
-  mTelemetryTimer->InitWithNamedFuncCallback(EverySecondTelemetryCallback_m, this, 1000,
-                                             nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP,
-                                             "EverySecondTelemetryCallback_m");
 
   if (XRE_IsContentProcess()) {
     WebrtcGlobalChild::Create();
   }
 
   return NS_OK;
 }
 
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -2631,18 +2631,17 @@ PeerConnectionImpl::InsertDTMF(mozilla::
     }
   }
 
   // No state yet, create a new one
   if (!state) {
     state = mDTMFStates.AppendElement();
     state->mPeerConnectionImpl = this;
     state->mTrackId = senderTrackId;
-    state->mSendTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    MOZ_ASSERT(state->mSendTimer);
+    state->mSendTimer = NS_NewTimer();
   }
   MOZ_ASSERT(state);
 
   auto trackPairs = mJsepSession->GetNegotiatedTrackPairs();
   state->mLevel = -1;
   for (auto& trackPair : trackPairs) {
     if (state->mTrackId.EqualsASCII(trackPair.mSending->GetTrackId().c_str())) {
       if (trackPair.HasBundleLevel()) {
--- a/media/webrtc/signaling/test/FakeMediaStreamsImpl.h
+++ b/media/webrtc/signaling/test/FakeMediaStreamsImpl.h
@@ -32,24 +32,18 @@ mozilla::TrackTicks Fake_MediaStream::Ti
 mozilla::StreamTime
 Fake_MediaStream::TicksToTimeRoundDown(mozilla::TrackRate aRate,
                                        mozilla::TrackTicks aTicks) {
   return aTicks * GRAPH_RATE / aRate;
 }
 
 // Fake_SourceMediaStream
 nsresult Fake_SourceMediaStream::Start() {
-  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  if (!mTimer) {
-    return NS_ERROR_FAILURE;
-  }
-
-  mTimer->InitWithCallback(mPeriodic, 100, nsITimer::TYPE_REPEATING_SLACK);
-
-  return NS_OK;
+  return NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                                 mPeriodic, 100, nsITimer::TYPE_REPEATING_SLACK);
 }
 
 nsresult Fake_SourceMediaStream::Stop() {
   mozilla::MutexAutoLock lock(mMutex);
   if (mTimer)
     mTimer->Cancel();
   mPeriodic->Detach();
   return NS_OK;
@@ -78,24 +72,18 @@ void Fake_MediaStreamTrack::AddListener(
 }
 void Fake_MediaStreamTrack::RemoveListener(Fake_MediaStreamTrackListener *aListener)
 {
   mOwningStream->GetInputStream()->RemoveTrackListener(aListener, mTrackID);
 }
 
 // Fake_MediaStreamBase
 nsresult Fake_MediaStreamBase::Start() {
-  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  if (!mTimer) {
-    return NS_ERROR_FAILURE;
-  }
-
-  mTimer->InitWithCallback(mPeriodic, 100, nsITimer::TYPE_REPEATING_SLACK);
-
-  return NS_OK;
+  return NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                                 mPeriodic, 100, nsITimer::TYPE_REPEATING_SLACK);
 }
 
 nsresult Fake_MediaStreamBase::Stop() {
   // Lock the mutex so that we know that after this
   // has returned, periodic will not be firing again
   // and so it's safe to destruct.
   mozilla::MutexAutoLock lock(mMutex);
   mTimer->Cancel();
--- a/mobile/android/components/build/nsAndroidHistory.cpp
+++ b/mobile/android/components/build/nsAndroidHistory.cpp
@@ -42,17 +42,17 @@ nsAndroidHistory::GetSingleton()
   return sHistory;
 }
 
 nsAndroidHistory::nsAndroidHistory()
   : mHistoryEnabled(true)
 {
   LoadPrefs();
 
-  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mTimer = NS_NewTimer();
 }
 
 NS_IMETHODIMP
 nsAndroidHistory::RegisterVisitedCallback(nsIURI *aURI, Link *aContent)
 {
   if (!aContent || !aURI)
     return NS_OK;
 
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -1170,16 +1170,29 @@ nsJARChannel::RetargetDeliveryTo(nsIEven
   if (!request) {
     return NS_ERROR_NO_INTERFACE;
   }
 
   return request->RetargetDeliveryTo(aEventTarget);
 }
 
 NS_IMETHODIMP
+nsJARChannel::GetDeliveryTarget(nsIEventTarget** aEventTarget)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIThreadRetargetableRequest> request = do_QueryInterface(mRequest);
+  if (!request) {
+    return NS_ERROR_NO_INTERFACE;
+  }
+
+  return request->GetDeliveryTarget(aEventTarget);
+}
+
+NS_IMETHODIMP
 nsJARChannel::CheckListenerChain()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
     do_QueryInterface(mListener);
   if (!listener) {
     return NS_ERROR_NO_INTERFACE;
--- a/netwerk/base/CaptivePortalService.cpp
+++ b/netwerk/base/CaptivePortalService.cpp
@@ -88,17 +88,17 @@ CaptivePortalService::RearmTimer()
   // If we have successfully determined the state, and we have never detected
   // a captive portal, we don't need to keep polling, but will rely on events
   // to trigger detection.
   if (mState == NOT_CAPTIVE) {
     return NS_OK;
   }
 
   if (!mTimer) {
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mTimer = NS_NewTimer();
   }
 
   if (mTimer && mDelay > 0) {
     LOG(("CaptivePortalService - Reloading timer with delay %u\n", mDelay));
     return mTimer->InitWithCallback(this, mDelay, nsITimer::TYPE_ONE_SHOT);
   }
 
   return NS_OK;
--- a/netwerk/base/Dashboard.cpp
+++ b/netwerk/base/Dashboard.cpp
@@ -238,17 +238,17 @@ ConnectionData::Notify(nsITimer *aTimer)
 
     return NS_OK;
 }
 
 void
 ConnectionData::StartTimer(uint32_t aTimeout)
 {
     if (!mTimer) {
-        mTimer = do_CreateInstance("@mozilla.org/timer;1");
+        mTimer = NS_NewTimer();
     }
 
     mTimer->InitWithCallback(this, aTimeout * 1000,
         nsITimer::TYPE_ONE_SHOT);
 }
 
 void
 ConnectionData::StopTimer()
--- a/netwerk/base/EventTokenBucket.cpp
+++ b/netwerk/base/EventTokenBucket.cpp
@@ -95,19 +95,17 @@ EventTokenBucket::EventTokenBucket(uint3
   MOZ_ASSERT(NS_IsMainThread());
 
   nsresult rv;
   nsCOMPtr<nsIEventTarget> sts;
   nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
   if (NS_SUCCEEDED(rv))
     sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
   if (NS_SUCCEEDED(rv))
-    mTimer = do_CreateInstance("@mozilla.org/timer;1");
-  if (mTimer)
-    mTimer->SetTarget(sts);
+    mTimer = NS_NewTimer(sts);
   SetRate(eventsPerSecond, burstSize);
 }
 
 EventTokenBucket::~EventTokenBucket()
 {
   SOCKET_LOG(("EventTokenBucket::dtor %p events=%zu\n",
               this, mEvents.GetSize()));
 
@@ -425,17 +423,17 @@ EventTokenBucket::WantNormalTimers()
     static const TimeDuration fiveSeconds = TimeDuration::FromSeconds(5);
 
     if (elapsed >= fiveSeconds) {
       NormalTimers();
       return;
     }
 
     if (!mFineGrainResetTimer)
-      mFineGrainResetTimer = do_CreateInstance("@mozilla.org/timer;1");
+      mFineGrainResetTimer = NS_NewTimer();
 
     // if we can't delay the reset, just do it now
     if (!mFineGrainResetTimer) {
       NormalTimers();
       return;
     }
 
     // pad the callback out 100ms to avoid having to round trip this again if the
--- a/netwerk/base/Predictor.cpp
+++ b/netwerk/base/Predictor.cpp
@@ -446,18 +446,18 @@ Predictor::InstallObserver()
   Preferences::AddBoolVarCache(&mCleanedUp, PREDICTOR_CLEANED_UP_PREF, false);
 
   Preferences::AddUintVarCache(&mMaxURILength, PREDICTOR_MAX_URI_LENGTH_PREF,
                                PREDICTOR_MAX_URI_LENGTH_DEFAULT);
 
   Preferences::AddBoolVarCache(&mDoingTests, PREDICTOR_DOING_TESTS_PREF, false);
 
   if (!mCleanedUp) {
-    mCleanupTimer = do_CreateInstance("@mozilla.org/timer;1");
-    mCleanupTimer->Init(this, 60 * 1000, nsITimer::TYPE_ONE_SHOT);
+    NS_NewTimerWithObserver(getter_AddRefs(mCleanupTimer),
+                            this, 60 * 1000, nsITimer::TYPE_ONE_SHOT);
   }
 
   return rv;
 }
 
 void
 Predictor::RemoveObserver()
 {
--- a/netwerk/base/ProxyAutoConfig.cpp
+++ b/netwerk/base/ProxyAutoConfig.cpp
@@ -435,17 +435,17 @@ ProxyAutoConfig::ResolveAddress(const ns
                                         helper,
                                         GetCurrentThreadEventTarget(),
                                         attrs,
                                         getter_AddRefs(helper->mRequest))))
     return false;
 
   if (aTimeout && helper->mRequest) {
     if (!mTimer)
-      mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+      mTimer = NS_NewTimer();
     if (mTimer) {
       mTimer->SetTarget(mMainThreadEventTarget);
       mTimer->InitWithCallback(helper, aTimeout, nsITimer::TYPE_ONE_SHOT);
       helper->mTimer = mTimer;
     }
   }
 
   // Spin the event loop of the pac thread until lookup is complete.
--- a/netwerk/base/ThrottleQueue.cpp
+++ b/netwerk/base/ThrottleQueue.cpp
@@ -244,19 +244,17 @@ ThrottleQueue::ThrottleQueue()
   , mTimerArmed(false)
 {
   nsresult rv;
   nsCOMPtr<nsIEventTarget> sts;
   nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
   if (NS_SUCCEEDED(rv))
     sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
   if (NS_SUCCEEDED(rv))
-    mTimer = do_CreateInstance("@mozilla.org/timer;1");
-  if (mTimer)
-    mTimer->SetTarget(sts);
+    mTimer = NS_NewTimer(sts);
 }
 
 ThrottleQueue::~ThrottleQueue()
 {
   if (mTimer && mTimerArmed) {
     mTimer->Cancel();
   }
   mTimer = nullptr;
--- a/netwerk/base/Tickler.cpp
+++ b/netwerk/base/Tickler.cpp
@@ -75,23 +75,19 @@ Tickler::Init()
   opt.value.ip_ttl = 1;
   PR_SetSocketOption(mFD, &opt);
 
   nsresult rv = NS_NewNamedThread("wifi tickler",
                                   getter_AddRefs(mThread));
   if (NS_FAILED(rv))
     return rv;
 
-  nsCOMPtr<nsITimer> tmpTimer(do_CreateInstance(NS_TIMER_CONTRACTID, &rv));
-  if (NS_FAILED(rv))
-    return rv;
-
-  rv = tmpTimer->SetTarget(mThread);
-  if (NS_FAILED(rv))
-    return rv;
+  nsCOMPtr<nsITimer> tmpTimer = NS_NewTimer(mThread);
+  if (!tmpTimer)
+    return NS_ERROR_OUT_OF_MEMORY;
 
   mTimer.swap(tmpTimer);
 
   mAddr.inet.family = PR_AF_INET;
   mAddr.inet.port = PR_htons (4886);
   mAddr.inet.ip = 0;
 
   return NS_OK;
--- a/netwerk/base/nsBaseChannel.cpp
+++ b/netwerk/base/nsBaseChannel.cpp
@@ -970,16 +970,30 @@ nsBaseChannel::RetargetDeliveryTo(nsIEve
   }
 
   NS_ENSURE_TRUE(req, NS_ERROR_NOT_IMPLEMENTED);
 
   return req->RetargetDeliveryTo(aEventTarget);
 }
 
 NS_IMETHODIMP
+nsBaseChannel::GetDeliveryTarget(nsIEventTarget** aEventTarget)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  NS_ENSURE_TRUE(mRequest, NS_ERROR_NOT_INITIALIZED);
+
+  nsCOMPtr<nsIThreadRetargetableRequest> req;
+    req = do_QueryInterface(mRequest);
+
+  NS_ENSURE_TRUE(req, NS_ERROR_NOT_IMPLEMENTED);
+  return req->GetDeliveryTarget(aEventTarget);
+}
+
+NS_IMETHODIMP
 nsBaseChannel::CheckListenerChain()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mAllowThreadRetargeting) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
--- a/netwerk/base/nsIThreadRetargetableRequest.idl
+++ b/netwerk/base/nsIThreadRetargetableRequest.idl
@@ -27,9 +27,17 @@ interface nsIThreadRetargetableRequest :
    * @param aNewTarget New event target, e.g. thread or threadpool.
    *
    * Note: no return value is given. If the retargeting cannot be handled,
    * normal delivery to the main thread will continue. As such, listeners
    * should be ready to deal with OnDataAvailable on either the main thread or
    * the new target thread.
    */
   void retargetDeliveryTo(in nsIEventTarget aNewTarget);
+
+  /**
+   * Returns the event target where OnDataAvailable events will be dispatched.
+   *
+   * This is only valid after OnStartRequest has been called. Any time before
+   * that point, the value may be changed by `retargetDeliveryTo` calls.
+   */
+  readonly attribute nsIEventTarget deliveryTarget;
 };
--- a/netwerk/base/nsIncrementalDownload.cpp
+++ b/netwerk/base/nsIncrementalDownload.cpp
@@ -221,22 +221,19 @@ nsIncrementalDownload::CallOnStopRequest
   mObserver->OnStopRequest(this, mObserverContext, mStatus);
   mObserver = nullptr;
   mObserverContext = nullptr;
 }
 
 nsresult
 nsIncrementalDownload::StartTimer(int32_t interval)
 {
-  nsresult rv;
-  mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  if (NS_FAILED(rv))
-    return rv;
-
-  return mTimer->Init(this, interval * 1000, nsITimer::TYPE_ONE_SHOT);
+  return NS_NewTimerWithObserver(getter_AddRefs(mTimer),
+                                 this, interval * 1000,
+                                 nsITimer::TYPE_ONE_SHOT);
 }
 
 nsresult
 nsIncrementalDownload::ProcessTimeout()
 {
   NS_ASSERTION(!mChannel, "how can we have a channel?");
 
   // Handle existing error conditions
--- a/netwerk/base/nsInputStreamPump.cpp
+++ b/netwerk/base/nsInputStreamPump.cpp
@@ -770,8 +770,18 @@ nsInputStreamPump::RetargetDeliveryTo(ns
         }
     }
     LOG(("nsInputStreamPump::RetargetDeliveryTo [this=%p aNewTarget=%p] "
          "%s listener [%p] rv[%" PRIx32 "]",
          this, aNewTarget, (mTargetThread == aNewTarget ? "success" : "failure"),
          (nsIStreamListener*)mListener, static_cast<uint32_t>(rv)));
     return rv;
 }
+
+NS_IMETHODIMP
+nsInputStreamPump::GetDeliveryTarget(nsIEventTarget** aNewTarget)
+{
+    RecursiveMutexAutoLock lock(mMutex);
+
+    nsCOMPtr<nsIEventTarget> target = mTargetThread;
+    target.forget(aNewTarget);
+    return NS_OK;
+}
--- a/netwerk/base/nsSerializationHelper.cpp
+++ b/netwerk/base/nsSerializationHelper.cpp
@@ -20,21 +20,17 @@ using namespace mozilla;
 nsresult
 NS_SerializeToString(nsISerializable* obj, nsACString& str)
 {
   RefPtr<nsBase64Encoder> stream(new nsBase64Encoder());
   if (!stream)
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsCOMPtr<nsIObjectOutputStream> objstream =
-      do_CreateInstance("@mozilla.org/binaryoutputstream;1");
-  if (!objstream)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  objstream->SetOutputStream(stream);
+    NS_NewObjectOutputStream(stream);
   nsresult rv =
       objstream->WriteCompoundObject(obj, NS_GET_IID(nsISupports), true);
   NS_ENSURE_SUCCESS(rv, rv);
   return stream->Finish(str);
 }
 
 nsresult
 NS_DeserializeObject(const nsACString& str, nsISupports** obj)
@@ -43,21 +39,17 @@ NS_DeserializeObject(const nsACString& s
   nsresult rv = Base64Decode(str, decodedData);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIInputStream> stream;
   rv = NS_NewCStringInputStream(getter_AddRefs(stream), decodedData);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIObjectInputStream> objstream =
-      do_CreateInstance("@mozilla.org/binaryinputstream;1");
-  if (!objstream)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  objstream->SetInputStream(stream);
+    NS_NewObjectInputStream(stream);
   return objstream->ReadObject(true, obj);
 }
 
 NS_IMPL_ISUPPORTS(nsSerializationHelper, nsISerializationHelper)
 
 NS_IMETHODIMP
 nsSerializationHelper::SerializeToString(nsISerializable *serializable,
                                          nsACString & _retval)
--- a/netwerk/base/nsSocketTransportService2.cpp
+++ b/netwerk/base/nsSocketTransportService2.cpp
@@ -1428,20 +1428,18 @@ nsSocketTransportService::Observe(nsISup
     } else if (!strcmp(topic, NS_WIDGET_SLEEP_OBSERVER_TOPIC)) {
         mSleepPhase = true;
         if (mAfterWakeUpTimer) {
             mAfterWakeUpTimer->Cancel();
             mAfterWakeUpTimer = nullptr;
         }
     } else if (!strcmp(topic, NS_WIDGET_WAKE_OBSERVER_TOPIC)) {
         if (mSleepPhase && !mAfterWakeUpTimer) {
-            mAfterWakeUpTimer = do_CreateInstance("@mozilla.org/timer;1");
-            if (mAfterWakeUpTimer) {
-                mAfterWakeUpTimer->Init(this, 2000, nsITimer::TYPE_ONE_SHOT);
-            }
+            NS_NewTimerWithObserver(getter_AddRefs(mAfterWakeUpTimer),
+                                    this, 2000, nsITimer::TYPE_ONE_SHOT);
         }
     } else if (!strcmp(topic, "xpcom-shutdown-threads")) {
         ShutdownThread();
     }
 
     return NS_OK;
 }
 
@@ -1660,19 +1658,19 @@ nsSocketTransportService::StartPollWatch
                                                    [self] {
          MutexAutoLock lock(self->mLock);
 
          // Poll can hang sometimes. If we are in shutdown, we are going to start a
          // watchdog. If we do not exit poll within REPAIR_POLLABLE_EVENT_TIME
          // signal a pollable event again.
          MOZ_ASSERT(gIOService->IsNetTearingDown());
          if (self->mPolling && !self->mPollRepairTimer) {
-             self->mPollRepairTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-             self->mPollRepairTimer->Init(self, REPAIR_POLLABLE_EVENT_TIME,
-                                          nsITimer::TYPE_REPEATING_SLACK);
+             NS_NewTimerWithObserver(getter_AddRefs(self->mPollRepairTimer),
+                                     self, REPAIR_POLLABLE_EVENT_TIME,
+                                     nsITimer::TYPE_REPEATING_SLACK);
          }
     }));
 }
 
 void
 nsSocketTransportService::DoPollRepair()
 {
     MutexAutoLock lock(mLock);
--- a/netwerk/cache/nsCacheService.cpp
+++ b/netwerk/cache/nsCacheService.cpp
@@ -1627,27 +1627,22 @@ nsCacheService::CreateDiskDevice()
         return rv;
     }
 
     NS_ASSERTION(!mSmartSizeTimer, "Smartsize timer was already fired!");
 
     // Disk device is usually created during the startup. Delay smart size
     // calculation to avoid possible massive IO caused by eviction of entries
     // in case the new smart size is smaller than current cache usage.
-    mSmartSizeTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    if (NS_SUCCEEDED(rv)) {
-        rv = mSmartSizeTimer->InitWithCallback(new nsSetDiskSmartSizeCallback(),
-                                               1000*60*3,
-                                               nsITimer::TYPE_ONE_SHOT);
-        if (NS_FAILED(rv)) {
-            NS_WARNING("Failed to post smart size timer");
-            mSmartSizeTimer = nullptr;
-        }
-    } else {
-        NS_WARNING("Can't create smart size timer");
+    rv = NS_NewTimerWithCallback(getter_AddRefs(mSmartSizeTimer),
+                                 new nsSetDiskSmartSizeCallback(),
+                                 1000*60*3,
+                                 nsITimer::TYPE_ONE_SHOT);
+    if (NS_FAILED(rv)) {
+        NS_WARNING("Failed to post smart size timer");
     }
     // Ignore state of the timer and return success since the purpose of the
     // method (create the disk-device) has been fulfilled
 
     return NS_OK;
 }
 
 // Runnable sent from cache thread to main thread
--- a/netwerk/cache/nsDeleteDir.cpp
+++ b/netwerk/cache/nsDeleteDir.cpp
@@ -374,35 +374,30 @@ nsDeleteDir::RemoveOldTrashes(nsIFile *c
   return NS_OK;
 }
 
 nsresult
 nsDeleteDir::PostTimer(void *arg, uint32_t delay)
 {
   nsresult rv;
 
-  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  if (NS_FAILED(rv))
-    return NS_ERROR_UNEXPECTED;
-
   MutexAutoLock lock(mLock);
 
   rv = InitThread();
   if (NS_FAILED(rv))
     return rv;
 
-  rv = timer->SetTarget(mThread);
-  if (NS_FAILED(rv))
-    return rv;
-
-  rv = timer->InitWithNamedFuncCallback(TimerCallback,
-                                        arg,
-                                        delay,
-                                        nsITimer::TYPE_ONE_SHOT,
-                                        "nsDeleteDir::PostTimer");
+  nsCOMPtr<nsITimer> timer;
+  rv = NS_NewTimerWithFuncCallback(getter_AddRefs(timer),
+                                   TimerCallback,
+                                   arg,
+                                   delay,
+                                   nsITimer::TYPE_ONE_SHOT,
+                                   "nsDeleteDir::PostTimer",
+                                   mThread);
   if (NS_FAILED(rv))
     return rv;
 
   mTimers.AppendObject(timer);
   return NS_OK;
 }
 
 nsresult
--- a/netwerk/cache/nsDiskCacheMap.cpp
+++ b/netwerk/cache/nsDiskCacheMap.cpp
@@ -1274,21 +1274,18 @@ nsDiskCacheMap::InitCacheClean(nsIFile *
         int32_t bytesRead = PR_Read(mCleanFD, &clean, 1);
         if (bytesRead != 1) {
             NS_WARNING("Could not read _CACHE_CLEAN_ file contents");
         }
     }
 
     // Create a timer that will be used to validate the cache
     // as long as an activity threshold was met
-    mCleanCacheTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    if (NS_SUCCEEDED(rv)) {
-        mCleanCacheTimer->SetTarget(nsCacheService::GlobalInstance()->mCacheIOThread);
-        rv = ResetCacheTimer();
-    }
+    mCleanCacheTimer = NS_NewTimer(nsCacheService::GlobalInstance()->mCacheIOThread);
+    rv = mCleanCacheTimer ? ResetCacheTimer() : NS_ERROR_OUT_OF_MEMORY;
 
     if (NS_FAILED(rv)) {
         NS_WARNING("Could not create cache clean timer");
         mCleanCacheTimer = nullptr;
         *corruptInfo = nsDiskCache::kCacheCleanTimerError;
         return rv;
     }
 
--- a/netwerk/cache2/CacheFileIOManager.cpp
+++ b/netwerk/cache2/CacheFileIOManager.cpp
@@ -1519,21 +1519,19 @@ CacheFileIOManager::ScheduleMetadataWrit
 nsresult
 CacheFileIOManager::ScheduleMetadataWriteInternal(CacheFile * aFile)
 {
   MOZ_ASSERT(IsOnIOThreadOrCeased());
 
   nsresult rv;
 
   if (!mMetadataWritesTimer) {
-    mMetadataWritesTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mMetadataWritesTimer->InitWithCallback(
-      this, kMetadataWriteDelay, nsITimer::TYPE_ONE_SHOT);
+    rv = NS_NewTimerWithCallback(getter_AddRefs(mMetadataWritesTimer),
+                                 this, kMetadataWriteDelay,
+                                 nsITimer::TYPE_ONE_SHOT);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (mScheduledMetadataWrites.IndexOf(aFile) !=
       mScheduledMetadataWrites.NoIndex) {
     return NS_OK;
   }
 
@@ -3434,35 +3432,27 @@ CacheFileIOManager::StartRemovingTrash()
   if (mRemovingTrashDirs) {
     LOG(("CacheFileIOManager::StartRemovingTrash() - Trash removing in "
          "progress."));
     return NS_OK;
   }
 
   uint32_t elapsed = (TimeStamp::NowLoRes() - mStartTime).ToMilliseconds();
   if (elapsed < kRemoveTrashStartDelay) {
-    nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
     nsCOMPtr<nsIEventTarget> ioTarget = IOTarget();
     MOZ_ASSERT(ioTarget);
 
-    rv = timer->SetTarget(ioTarget);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = timer->InitWithNamedFuncCallback(
+    return NS_NewTimerWithFuncCallback(
+      getter_AddRefs(mTrashTimer),
       CacheFileIOManager::OnTrashTimer,
       nullptr,
       kRemoveTrashStartDelay - elapsed,
       nsITimer::TYPE_ONE_SHOT,
-      "net::CacheFileIOManager::StartRemovingTrash");
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    mTrashTimer.swap(timer);
-    return NS_OK;
+      "net::CacheFileIOManager::StartRemovingTrash",
+      ioTarget);
   }
 
   nsCOMPtr<nsIRunnable> ev;
   ev = NewRunnableMethod("net::CacheFileIOManager::RemoveTrashInternal",
                          this,
                          &CacheFileIOManager::RemoveTrashInternal);
 
   rv = mIOThread->Dispatch(ev, CacheIOThread::EVICT);
--- a/netwerk/cache2/CacheIndex.cpp
+++ b/netwerk/cache2/CacheIndex.cpp
@@ -2646,36 +2646,26 @@ CacheIndex::DelayedUpdateLocked()
 
 nsresult
 CacheIndex::ScheduleUpdateTimer(uint32_t aDelay)
 {
   LOG(("CacheIndex::ScheduleUpdateTimer() [delay=%u]", aDelay));
 
   MOZ_ASSERT(!mUpdateTimer);
 
-  nsresult rv;
-
-  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   nsCOMPtr<nsIEventTarget> ioTarget = CacheFileIOManager::IOTarget();
   MOZ_ASSERT(ioTarget);
 
-  rv = timer->SetTarget(ioTarget);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = timer->InitWithNamedFuncCallback(CacheIndex::DelayedUpdate,
-                                        nullptr,
-                                        aDelay,
-                                        nsITimer::TYPE_ONE_SHOT,
-                                        "net::CacheIndex::ScheduleUpdateTimer");
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mUpdateTimer.swap(timer);
-  return NS_OK;
+  return NS_NewTimerWithFuncCallback(getter_AddRefs(mUpdateTimer),
+                                     CacheIndex::DelayedUpdate,
+                                     nullptr,
+                                     aDelay,
+                                     nsITimer::TYPE_ONE_SHOT,
+                                     "net::CacheIndex::ScheduleUpdateTimer",
+                                     ioTarget);
 }
 
 nsresult
 CacheIndex::SetupDirectoryEnumerator()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(!mDirEnumerator);
 
--- a/netwerk/cache2/CacheStorageService.cpp
+++ b/netwerk/cache2/CacheStorageService.cpp
@@ -1230,17 +1230,17 @@ CacheStorageService::SchedulePurgeOverMe
     return;
   }
 
   if (mPurgeTimer) {
     LOG(("  timer already up"));
     return;
   }
 
-  mPurgeTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mPurgeTimer = NS_NewTimer();
   if (mPurgeTimer) {
     nsresult rv;
     rv = mPurgeTimer->InitWithCallback(this, 1000, nsITimer::TYPE_ONE_SHOT);
     LOG(("  timer init rv=0x%08" PRIx32, static_cast<uint32_t>(rv)));
   }
 }
 
 NS_IMETHODIMP
--- a/netwerk/dns/nsIDNService.cpp
+++ b/netwerk/dns/nsIDNService.cpp
@@ -745,16 +745,17 @@ bool nsIDNService::isLabelSafe(const nsA
   }
 
   nsAString::const_iterator current, end;
   label.BeginReading(current);
   label.EndReading(end);
 
   Script lastScript = Script::INVALID;
   uint32_t previousChar = 0;
+  uint32_t baseChar = 0; // last non-diacritic seen (base char for marks)
   uint32_t savedNumberingSystem = 0;
 // Simplified/Traditional Chinese check temporarily disabled -- bug 857481
 #if 0
   HanVariantType savedHanVariant = HVT_NotHan;
 #endif
 
   int32_t savedScript = -1;
 
@@ -825,16 +826,24 @@ bool nsIDNService::isLabelSafe(const nsA
               break;
             }
           }
           if (nScripts == -1) {
             return false;
           }
         }
       }
+      // Check for diacritics on dotless-i, which would be indistinguishable
+      // from normal accented letter i.
+      if (baseChar == 0x0131 &&
+          ((ch >= 0x0300 && ch <= 0x0314) || ch == 0x031a)) {
+        return false;
+      }
+    } else {
+      baseChar = ch;
     }
 
     if (script != Script::COMMON && script != Script::INHERITED) {
       lastScript = script;
     }
 
     // Simplified/Traditional Chinese check temporarily disabled -- bug 857481
 #if 0
--- a/netwerk/protocol/ftp/nsFtpProtocolHandler.cpp
+++ b/netwerk/protocol/ftp/nsFtpProtocolHandler.cpp
@@ -304,30 +304,27 @@ nsFtpProtocolHandler::InsertConnection(n
     if (aConn->mSessionId != mSessionId)
         return NS_ERROR_FAILURE;
 
     nsAutoCString spec;
     aKey->GetPrePath(spec);
 
     LOG(("FTP:inserting connection for %s\n", spec.get()));
 
-    nsresult rv;
-    nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    if (NS_FAILED(rv)) return rv;
-
     timerStruct* ts = new timerStruct();
     if (!ts)
         return NS_ERROR_OUT_OF_MEMORY;
 
-    rv = timer->InitWithNamedFuncCallback(
-      nsFtpProtocolHandler::Timeout,
-      ts,
-      mIdleTimeout * 1000,
-      nsITimer::TYPE_REPEATING_SLACK,
-      "nsFtpProtocolHandler::InsertConnection");
+    nsCOMPtr<nsITimer> timer;
+    nsresult rv = NS_NewTimerWithFuncCallback(getter_AddRefs(timer),
+                                              nsFtpProtocolHandler::Timeout,
+                                              ts,
+                                              mIdleTimeout * 1000,
+                                              nsITimer::TYPE_REPEATING_SLACK,
+                                              "nsFtpProtocolHandler::InsertConnection");
     if (NS_FAILED(rv)) {
         delete ts;
         return rv;
     }
 
     ts->key = ToNewCString(spec);
     if (!ts->key) {
         delete ts;
--- a/netwerk/protocol/http/HSTSPrimerListener.cpp
+++ b/netwerk/protocol/http/HSTSPrimerListener.cpp
@@ -370,20 +370,19 @@ HSTSPrimingListener::StartHSTSPriming(ns
 
   // Set up listener which will start the original channel
   HSTSPrimingListener* listener = new HSTSPrimingListener(aCallback);
   // Start priming
   rv = primingChannel->AsyncOpen2(listener);
   NS_ENSURE_SUCCESS(rv, rv);
   listener->mPrimingChannel.swap(primingChannel);
 
-  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  NS_ENSURE_STATE(timer);
-
-  rv = timer->InitWithCallback(listener,
+  nsCOMPtr<nsITimer> timer;
+  rv = NS_NewTimerWithCallback(getter_AddRefs(timer),
+                               listener,
                                sHSTSPrimingTimeout,
                                nsITimer::TYPE_ONE_SHOT);
   if (NS_FAILED(rv)) {
     NS_ERROR("HSTS Priming failed to initialize channel cancellation timer");
   }
 
   listener->mHSTSPrimingTimer.swap(timer);
 
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -3381,16 +3381,29 @@ HttpChannelChild::RetargetDeliveryTo(nsI
     MutexAutoLock lock(mEventTargetMutex);
     mODATarget = aNewTarget;
   }
 
   mOMTResult = LABELS_HTTP_CHILD_OMT_STATS::success;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+HttpChannelChild::GetDeliveryTarget(nsIEventTarget** aEventTarget)
+{
+  MutexAutoLock lock(mEventTargetMutex);
+
+  nsCOMPtr<nsIEventTarget> target = mODATarget;
+  if (!mODATarget) {
+    target = GetCurrentThreadEventTarget();
+  }
+  target.forget(aEventTarget);
+  return NS_OK;
+}
+
 void
 HttpChannelChild::ResetInterception()
 {
   NS_ENSURE_TRUE_VOID(gNeckoChild != nullptr);
 
   if (mInterceptListener) {
     mInterceptListener->Cleanup();
   }
--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp
+++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp
@@ -1074,16 +1074,25 @@ InterceptedHttpChannel::RetargetDelivery
   if (!mPump) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mPump->RetargetDeliveryTo(aNewTarget);
 }
 
 NS_IMETHODIMP
+InterceptedHttpChannel::GetDeliveryTarget(nsIEventTarget** aEventTarget)
+{
+  if (!mPump) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+  return mPump->GetDeliveryTarget(aEventTarget);
+}
+
+NS_IMETHODIMP
 InterceptedHttpChannel::CheckListenerChain()
 {
   MOZ_ASSERT(NS_IsMainThread());
   nsresult rv = NS_OK;
   nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
   do_QueryInterface(mListener, &rv);
   if (retargetableListener) {
     rv = retargetableListener->CheckListenerChain();
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -419,17 +419,17 @@ TLSFilterTransaction::NudgeTunnel(NudgeT
     delay = 6;
   } else if (counter < 34) { // up to 499 ms at 17ms
     delay = 17;
   } else { // after that at 51ms (3 old windows ticks)
     delay = 51;
   }
 
   if(!mTimer) {
-    mTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mTimer = NS_NewTimer();
   }
 
   mNudgeCallback = aCallback;
   if (!mTimer ||
       NS_FAILED(mTimer->InitWithCallback(this, delay, nsITimer::TYPE_ONE_SHOT))) {
     return StartTimerCallback();
   }
 
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -3928,19 +3928,20 @@ nsHttpChannel::OpenCacheEntry(bool isHtt
         mCacheOpenFunc = [openURI, extension, cacheEntryOpenFlags, cacheStorage] (nsHttpChannel* self) -> void {
             MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread");
             if (self->mNetworkTriggered) {
                 self->mRaceCacheWithNetwork = true;
             }
             cacheStorage->AsyncOpenURI(openURI, extension, cacheEntryOpenFlags, self);
         };
 
-        mCacheOpenTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
         // calls nsHttpChannel::Notify after `mCacheOpenDelay` milliseconds
-        mCacheOpenTimer->InitWithCallback(this, mCacheOpenDelay, nsITimer::TYPE_ONE_SHOT);
+        NS_NewTimerWithCallback(getter_AddRefs(mCacheOpenTimer),
+                                this, mCacheOpenDelay,
+                                nsITimer::TYPE_ONE_SHOT);
 
     }
     NS_ENSURE_SUCCESS(rv, rv);
 
     waitFlags.Keep(WAIT_FOR_CACHE_ENTRY);
 
 bypassCacheEntryOpen:
     if (!mApplicationCacheForWrite)
@@ -7745,16 +7746,29 @@ nsHttpChannel::RetargetDeliveryTo(nsIEve
             nsCOMPtr<nsIEventTarget> main = GetMainThreadEventTarget();
             NS_ENSURE_TRUE(main, NS_ERROR_UNEXPECTED);
             rv = retargetableCachePump->RetargetDeliveryTo(main);
         }
     }
     return rv;
 }
 
+
+NS_IMETHODIMP
+nsHttpChannel::GetDeliveryTarget(nsIEventTarget** aEventTarget)
+{
+    if (mCachePump) {
+        return mCachePump->GetDeliveryTarget(aEventTarget);
+    }
+    if (mTransactionPump) {
+        return mTransactionPump->GetDeliveryTarget(aEventTarget);
+    }
+    return NS_ERROR_NOT_AVAILABLE;
+}
+
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsThreadRetargetableStreamListener
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::CheckListenerChain()
 {
     NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!");
@@ -9262,17 +9276,17 @@ nsHttpChannel::TriggerNetworkWithDelay(u
         // cause performance regression in tp6 tests, see bug 1398847.
         return NS_DispatchToMainThread(
             NewRunnableMethod("net::nsHttpChannel::TriggerNetworkWithDelay",
                               this, &nsHttpChannel::TriggerNetwork),
             NS_DISPATCH_NORMAL);
     }
 
     if (!mNetworkTriggerTimer) {
-        mNetworkTriggerTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+        mNetworkTriggerTimer = NS_NewTimer();
     }
     mNetworkTriggerTimer->InitWithCallback(this, aDelay, nsITimer::TYPE_ONE_SHOT);
     return NS_OK;
 }
 
 nsresult
 nsHttpChannel::TriggerNetwork()
 {
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -1542,23 +1542,23 @@ nsHttpConnection::MaybeForceSendIO()
     // tick interval (kForceDelay) as a backup for those circumstances.
     static const uint32_t kForceDelay = 17; //ms
 
     if (mForceSendPending) {
         return NS_OK;
     }
     MOZ_ASSERT(!mForceSendTimer);
     mForceSendPending = true;
-    mForceSendTimer = do_CreateInstance("@mozilla.org/timer;1");
-    return mForceSendTimer->InitWithNamedFuncCallback(
-      nsHttpConnection::ForceSendIO,
-      this,
-      kForceDelay,
-      nsITimer::TYPE_ONE_SHOT,
-      "net::nsHttpConnection::MaybeForceSendIO");
+    return NS_NewTimerWithFuncCallback(
+        getter_AddRefs(mForceSendTimer),
+        nsHttpConnection::ForceSendIO,
+        this,
+        kForceDelay,
+        nsITimer::TYPE_ONE_SHOT,
+        "net::nsHttpConnection::MaybeForceSendIO");
 }
 
 // trigger an asynchronous read
 nsresult
 nsHttpConnection::ForceRecv()
 {
     LOG(("nsHttpConnection::ForceRecv [this=%p]\n", this));
     MOZ_ASSERT(OnSocketThread(), "not on socket thread");
@@ -2079,17 +2079,17 @@ nsHttpConnection::StartShortLivedTCPKeep
     }
     if (NS_FAILED(rv)) {
         return rv;
     }
 
     // Start a timer to move to long-lived keepalive config.
     if(!mTCPKeepaliveTransitionTimer) {
         mTCPKeepaliveTransitionTimer =
-            do_CreateInstance("@mozilla.org/timer;1");
+            NS_NewTimer();
     }
 
     if (mTCPKeepaliveTransitionTimer) {
         int32_t time = gHttpHandler->GetTCPKeepaliveShortLivedTime();
 
         // Adjust |time| to ensure a full set of keepalive probes can be sent
         // at the end of the short-lived phase.
         if (gHttpHandler->TCPKeepaliveEnabledForShortLivedConns()) {
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -300,17 +300,17 @@ nsHttpConnectionMgr::PostEvent(nsConnEve
 }
 
 void
 nsHttpConnectionMgr::PruneDeadConnectionsAfter(uint32_t timeInSeconds)
 {
     LOG(("nsHttpConnectionMgr::PruneDeadConnectionsAfter\n"));
 
     if(!mTimer)
-        mTimer = do_CreateInstance("@mozilla.org/timer;1");
+        mTimer = NS_NewTimer();
 
     // failure to create a timer is not a fatal error, but idle connections
     // will not be cleaned up until we try to use them.
     if (mTimer) {
         mTimeOfNextWakeUp = timeInSeconds + NowInSeconds();
         mTimer->Init(this, timeInSeconds*1000, nsITimer::TYPE_ONE_SHOT);
     } else {
         NS_WARNING("failed to create: timer for pruning the dead connections!");
@@ -2641,17 +2641,17 @@ nsHttpConnectionMgr::OnMsgVerifyTraffic(
         // Iterate the idle connections and unmark them for traffic checks.
         for (uint32_t index = 0; index < ent->mIdleConns.Length(); ++index) {
             ent->mIdleConns[index]->CheckForTraffic(false);
         }
     }
 
     // If the timer is already there. we just re-init it
     if(!mTrafficTimer) {
-        mTrafficTimer = do_CreateInstance("@mozilla.org/timer;1");
+        mTrafficTimer = NS_NewTimer();
     }
 
     // failure to create a timer is not a fatal error, but dead
     // connections will not be cleaned up as nicely
     if (mTrafficTimer) {
         // Give active connections time to get more traffic before killing
         // them off. Default: 5000 milliseconds
         mTrafficTimer->Init(this, gHttpHandler->NetworkChangedTimeout(),
@@ -2877,17 +2877,17 @@ nsHttpConnectionMgr::ActivateTimeoutTick
         if (mTimeoutTickNext > 1) {
             mTimeoutTickNext = 1;
             mTimeoutTick->SetDelay(1000);
         }
         return;
     }
 
     if (!mTimeoutTick) {
-        mTimeoutTick = do_CreateInstance(NS_TIMER_CONTRACTID);
+        mTimeoutTick = NS_NewTimer();
         if (!mTimeoutTick) {
             NS_WARNING("failed to create timer for http timeout management");
             return;
         }
         mTimeoutTick->SetTarget(mSocketThreadTarget);
     }
 
     MOZ_ASSERT(!mTimeoutTickArmed, "timer tick armed");
@@ -3273,17 +3273,17 @@ nsHttpConnectionMgr::EnsureThrottleTicke
     CancelDelayedResumeBackgroundThrottledTransactions();
 
     if (mThrottleTicker) {
         return;
     }
 
     MOZ_ASSERT(!mThrottlingInhibitsReading);
 
-    mThrottleTicker = do_CreateInstance("@mozilla.org/timer;1");
+    mThrottleTicker = NS_NewTimer();
     if (mThrottleTicker) {
         mThrottleTicker->Init(this, mThrottleSuspendFor, nsITimer::TYPE_ONE_SHOT);
         mThrottlingInhibitsReading = true;
     }
 
     LogActiveTransactions('^');
 }
 
@@ -3344,23 +3344,19 @@ nsHttpConnectionMgr::ThrottlerTick()
 
 void
 nsHttpConnectionMgr::DelayedResumeBackgroundThrottledTransactions()
 {
     if (mDelayedResumeReadTimer) {
         return;
     }
 
-    mDelayedResumeReadTimer = do_CreateInstance("@mozilla.org/timer;1");
-    if (!mDelayedResumeReadTimer) {
-        return;
-    }
-
     LOG(("nsHttpConnectionMgr::DelayedResumeBackgroundThrottledTransactions"));
-    mDelayedResumeReadTimer->Init(this, mThrottleResumeIn, nsITimer::TYPE_ONE_SHOT);
+    NS_NewTimerWithObserver(getter_AddRefs(mDelayedResumeReadTimer),
+                            this, mThrottleResumeIn, nsITimer::TYPE_ONE_SHOT);
 }
 
 void
 nsHttpConnectionMgr::CancelDelayedResumeBackgroundThrottledTransactions()
 {
     if (!mDelayedResumeReadTimer) {
         return;
     }
@@ -4009,22 +4005,19 @@ nsHttpConnectionMgr::nsHalfOpenSocket::S
         (timeout && !mSpeculative)) {
         // Setup the timer that will establish a backup socket
         // if we do not get a writable event on the main one.
         // We do this because a lost SYN takes a very long time
         // to repair at the TCP level.
         //
         // Failure to setup the timer is something we can live with,
         // so don't return an error in that case.
-        nsresult rv;
-        mSynTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-        if (NS_SUCCEEDED(rv)) {
-            mSynTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
-            LOG(("nsHalfOpenSocket::SetupBackupTimer() [this=%p]", this));
-        }
+        NS_NewTimerWithCallback(getter_AddRefs(mSynTimer),
+                                this, timeout, nsITimer::TYPE_ONE_SHOT);
+        LOG(("nsHalfOpenSocket::SetupBackupTimer() [this=%p]", this));
     } else if (timeout) {
         LOG(("nsHalfOpenSocket::SetupBackupTimer() [this=%p], did not arm\n", this));
     }
 }
 
 void
 nsHttpConnectionMgr::nsHalfOpenSocket::CancelBackupTimer()
 {
--- a/netwerk/protocol/websocket/BaseWebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/BaseWebSocketChannel.cpp
@@ -354,16 +354,29 @@ BaseWebSocketChannel::RetargetDeliveryTo
   MOZ_ASSERT(!mTargetThread, "Delivery target should be set once, before AsyncOpen");
   MOZ_ASSERT(!mWasOpened, "Should not be called after AsyncOpen!");
 
   mTargetThread = do_QueryInterface(aTargetThread);
   MOZ_ASSERT(mTargetThread);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+BaseWebSocketChannel::GetDeliveryTarget(nsIEventTarget** aTargetThread)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIEventTarget> target = mTargetThread;
+  if (!target) {
+    target = GetCurrentThreadEventTarget();
+  }
+  target.forget(aTargetThread);
+  return NS_OK;
+}
+
 BaseWebSocketChannel::ListenerAndContextContainer::ListenerAndContextContainer(
                                                nsIWebSocketListener* aListener,
                                                nsISupports* aContext)
   : mListener(aListener)
   , mContext(aContext)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mListener);
--- a/netwerk/protocol/websocket/WebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannel.cpp
@@ -260,28 +260,24 @@ public:
 
       if (fail) {
         TimeStamp rightNow = TimeStamp::Now();
 
         uint32_t remainingDelay = fail->RemainingDelay(rightNow);
         if (remainingDelay) {
           // reconnecting within delay interval: delay by remaining time
           nsresult rv;
-          ws->mReconnectDelayTimer =
-            do_CreateInstance("@mozilla.org/timer;1", &rv);
+          rv = NS_NewTimerWithCallback(getter_AddRefs(ws->mReconnectDelayTimer),
+                                       ws, remainingDelay, nsITimer::TYPE_ONE_SHOT);
           if (NS_SUCCEEDED(rv)) {
-            rv = ws->mReconnectDelayTimer->InitWithCallback(
-                          ws, remainingDelay, nsITimer::TYPE_ONE_SHOT);
-            if (NS_SUCCEEDED(rv)) {
-              LOG(("WebSocket: delaying websocket [this=%p] by %lu ms, changing"
-                   " state to CONNECTING_DELAYED", ws,
-                   (unsigned long)remainingDelay));
-              ws->mConnecting = CONNECTING_DELAYED;
-              return;
-            }
+            LOG(("WebSocket: delaying websocket [this=%p] by %lu ms, changing"
+                 " state to CONNECTING_DELAYED", ws,
+                 (unsigned long)remainingDelay));
+            ws->mConnecting = CONNECTING_DELAYED;
+            return;
           }
           // if timer fails (which is very unlikely), drop down to BeginOpen call
         } else if (fail->IsExpired(rightNow)) {
           mEntries.RemoveElementAt(failIndex);
           delete fail;
         }
       }
     }
@@ -1323,22 +1319,21 @@ WebSocketChannel::OnNetworkChanged()
     return NS_OK;
   }
 
   LOG(("nsWebSocketChannel:: Generating Ping as network changed\n"));
 
   if (!mPingTimer) {
     // The ping timer is only conditionally running already. If it wasn't
     // already created do it here.
-    nsresult rv;
-    mPingTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    if (NS_FAILED(rv)) {
+    mPingTimer = NS_NewTimer();
+    if (!mPingTimer) {
       LOG(("WebSocket: unable to create ping timer!"));
       NS_WARNING("unable to create ping timer!");
-      return rv;
+      return NS_ERROR_OUT_OF_MEMORY;
     }
   }
   // Trigger the ping timeout asap to fire off a new ping. Wait just
   // a little bit to better avoid multi-triggers.
   mPingForced = 1;
   mPingTimer->InitWithCallback(this, 200, nsITimer::TYPE_ONE_SHOT);
 
   return NS_OK;
@@ -1423,25 +1418,19 @@ WebSocketChannel::BeginOpenInternal()
 
   if (NS_FAILED(rv)) {
     LOG(("WebSocketChannel::BeginOpenInternal: cannot async open\n"));
     AbortSession(NS_ERROR_CONNECTION_REFUSED);
     return;
   }
   mOpenedHttpChannel = 1;
 
-  mOpenTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  if (NS_FAILED(rv)) {
-    LOG(("WebSocketChannel::BeginOpenInternal: cannot create open timer\n"));
-    AbortSession(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  rv = mOpenTimer->InitWithCallback(this, mOpenTimeout,
-                                    nsITimer::TYPE_ONE_SHOT);
+  rv = NS_NewTimerWithCallback(getter_AddRefs(mOpenTimer),
+                               this, mOpenTimeout,
+                               nsITimer::TYPE_ONE_SHOT);
   if (NS_FAILED(rv)) {
     LOG(("WebSocketChannel::BeginOpenInternal: cannot initialize open "
          "timer\n"));
     AbortSession(NS_ERROR_UNEXPECTED);
     return;
   }
 }
 
@@ -2130,21 +2119,20 @@ WebSocketChannel::PrimeNewOutgoingMessag
     if (mServerClosed) {
       /* bidi close complete */
       mReleaseOnTransmit = 1;
     } else if (NS_FAILED(mStopOnClose)) {
       /* result of abort session - give up */
       StopSession(mStopOnClose);
     } else {
       /* wait for reciprocal close from server */
-      mCloseTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-      if (NS_SUCCEEDED(rv)) {
-        mCloseTimer->InitWithCallback(this, mCloseTimeout,
-                                      nsITimer::TYPE_ONE_SHOT);
-      } else {
+      rv = NS_NewTimerWithCallback(getter_AddRefs(mCloseTimer),
+                                   this, mCloseTimeout,
+                                   nsITimer::TYPE_ONE_SHOT);
+      if (NS_FAILED(rv)) {
         StopSession(rv);
       }
     }
   } else {
     switch (msgType) {
     case kMsgTypePong:
       mOutHeader[0] = kFinalFragBit | nsIWebSocketFrame::OPCODE_PONG;
       break;
@@ -2445,21 +2433,20 @@ WebSocketChannel::StopSession(nsresult r
     //
     // Normally this will be taken care of in AbortSession() after mTCPClosed
     // is set when the server close arrives without waiting for the timeout to
     // expire.
 
     LOG(("WebSocketChannel::StopSession: Wait for Server TCP close"));
 
     nsresult rv;
-    mLingeringCloseTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    if (NS_SUCCEEDED(rv))
-      mLingeringCloseTimer->InitWithCallback(this, kLingeringCloseTimeout,
-                                             nsITimer::TYPE_ONE_SHOT);
-    else
+    rv = NS_NewTimerWithCallback(getter_AddRefs(mLingeringCloseTimer),
+                                 this, kLingeringCloseTimeout,
+                                 nsITimer::TYPE_ONE_SHOT);
+    if (NS_FAILED(rv))
       CleanupConnection();
   } else {
     CleanupConnection();
   }
 
   if (mCancelable) {
     mCancelable->Cancel(NS_ERROR_UNEXPECTED);
     mCancelable = nullptr;
@@ -3012,23 +2999,24 @@ nsresult
 WebSocketChannel::StartPinging()
 {
   LOG(("WebSocketChannel::StartPinging() %p", this));
   MOZ_ASSERT(OnSocketThread(), "not on socket thread");
   MOZ_ASSERT(mPingInterval);
   MOZ_ASSERT(!mPingTimer);
 
   nsresult rv;
-  mPingTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  if (NS_FAILED(rv)) {
-    NS_WARNING("unable to create ping timer. Carrying on.");
-  } else {
+  rv = NS_NewTimerWithCallback(getter_AddRefs(mPingTimer),
+                               this, mPingInterval,
+                               nsITimer::TYPE_ONE_SHOT);
+  if (NS_SUCCEEDED(rv)) {
     LOG(("WebSocketChannel will generate ping after %d ms of receive silence\n",
          mPingInterval));
-    mPingTimer->InitWithCallback(this, mPingInterval, nsITimer::TYPE_ONE_SHOT);
+  } else {
+    NS_WARNING("unable to create ping timer. Carrying on.");
   }
 
   return NS_OK;
 }
 
 
 void
 WebSocketChannel::ReportConnectionTelemetry()
--- a/netwerk/test/TestUDPSocket.cpp
+++ b/netwerk/test/TestUDPSocket.cpp
@@ -304,17 +304,17 @@ TEST(TestUDPSocket, TestUDPSocketMain)
   // Wait for server
   waiter->Wait(1);
   ASSERT_TRUE(NS_SUCCEEDED(serverListener->mResult));
 
   // Read response from server
   ASSERT_TRUE(NS_SUCCEEDED(clientListener->mResult));
 
   // Setup timer to detect multicast failure
-  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
+  nsCOMPtr<nsITimer> timer = NS_NewTimer();
   ASSERT_TRUE(timer);
   RefPtr<MulticastTimerCallback> timerCb = new MulticastTimerCallback(waiter);
 
   // Join multicast group
   printf("Joining multicast group\n");
   phase = TEST_MULTICAST;
   mozilla::net::NetAddr multicastAddr;
   multicastAddr.inet.family = AF_INET;
--- a/netwerk/test/unit/test_idn_urls.js
+++ b/netwerk/test/unit/test_idn_urls.js
@@ -298,16 +298,23 @@ const testcases = [
 
     // Arabic diacritic not allowed in Latin text (bug 1370497)
     ["goo\u0650gle", "xn--google-yri", false, false, false],
     // ...but Arabic diacritics are allowed on Arabic text
     ["العَرَبِي", "xn--mgbc0a5a6cxbzabt", false, true, true],
 
     // Hebrew diacritic also not allowed in Latin text (bug 1404349)
     ["goo\u05b4gle", "xn--google-rvh", false, false, false],
+
+    // Accents above dotless-i are not allowed
+    ["na\u0131\u0308ve", "xn--nave-mza04z", false, false, false],
+    ["d\u0131\u0302ner", "xn--dner-lza40z", false, false, false],
+    // but the corresponding accented-i (based on dotted i) is OK
+    ["na\u00efve.com", "xn--nave-6pa.com", false, true, true],
+    ["d\u00eener.com", "xn--dner-0pa.com", false, true, true],
 ];
 
 const profiles = ["ASCII", "high", "moderate"];
 
 function run_test() {
     var pbi = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
     var oldProfile = pbi.getCharPref("network.IDN.restriction_profile", "moderate");
     var oldWhitelistCom = pbi.getBoolPref("network.IDN.whitelist.com", false);
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -176,17 +176,17 @@ nsHtml5StreamParser::nsHtml5StreamParser
   , mTerminated(false)
   , mInterrupted(false)
   , mTerminatedMutex("nsHtml5StreamParser mTerminatedMutex")
   , mEventTarget(nsHtml5Module::GetStreamParserThread()->SerialEventTarget())
   , mExecutorFlusher(new nsHtml5ExecutorFlusher(aExecutor))
   , mLoadFlusher(new nsHtml5LoadFlusher(aExecutor))
   , mFeedChardet(false)
   , mInitialEncodingWasFromParentFrame(false)
-  , mFlushTimer(do_CreateInstance("@mozilla.org/timer;1"))
+  , mFlushTimer(NS_NewTimer())
   , mFlushTimerMutex("nsHtml5StreamParser mFlushTimerMutex")
   , mFlushTimerArmed(false)
   , mFlushTimerEverFired(false)
   , mMode(aMode)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   mFlushTimer->SetTarget(mEventTarget);
 #ifdef DEBUG
--- a/python/mozbuild/mozbuild/backend/cpp_eclipse.py
+++ b/python/mozbuild/mozbuild/backend/cpp_eclipse.py
@@ -108,21 +108,51 @@ class CppEclipseBackend(CommonBackend):
         workspace_language_path = os.path.join(workspace_language_dir, 'language.settings.xml')
         with open(workspace_language_path, 'wb') as fh:
             workspace_lang_settings = WORKSPACE_LANGUAGE_SETTINGS_TEMPLATE
             workspace_lang_settings = workspace_lang_settings.replace("@COMPILER_FLAGS@", self._cxx + " " + self._cppflags);
             fh.write(workspace_lang_settings)
 
         self._write_launch_files(launch_dir)
 
-        # This will show up as an 'unmanged' formatter. This can be named by generating
-        # another file.
-        formatter_prefs_path = os.path.join(settings_dir, 'org.eclipse.cdt.core.prefs')
-        with open(formatter_prefs_path, 'wb') as fh:
-            fh.write(FORMATTER_SETTINGS);
+        core_resources_prefs_path = os.path.join(workspace_settings_dir, 'org.eclipse.core.resources.prefs')
+        with open(core_resources_prefs_path, 'wb') as fh:
+            fh.write(STATIC_CORE_RESOURCES_PREFS);
+
+        core_runtime_prefs_path = os.path.join(workspace_settings_dir, 'org.eclipse.core.runtime.prefs')
+        with open(core_runtime_prefs_path, 'wb') as fh:
+            fh.write(STATIC_CORE_RUNTIME_PREFS);
+
+        ui_prefs_path = os.path.join(workspace_settings_dir, 'org.eclipse.ui.prefs')
+        with open(ui_prefs_path, 'wb') as fh:
+            fh.write(STATIC_UI_PREFS);
+
+        cdt_ui_prefs_path = os.path.join(workspace_settings_dir, 'org.eclipse.cdt.ui.prefs')
+        cdt_ui_prefs = STATIC_CDT_UI_PREFS
+        # Here we generate the code formatter that will show up in the UI with
+        # the name "Mozilla".  The formatter is stored as a single line of XML
+        # in the org.eclipse.cdt.ui.formatterprofiles pref.
+        cdt_ui_prefs += """org.eclipse.cdt.ui.formatterprofiles=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?>\\n<profiles version\="1">\\n<profile kind\="CodeFormatterProfile" name\="Mozilla" version\="1">\\n"""
+        XML_PREF_TEMPLATE = """<setting id\="@PREF_NAME@" value\="@PREF_VAL@"/>\\n"""
+        for line in FORMATTER_SETTINGS.splitlines():
+            [pref, val] = line.split("=")
+            cdt_ui_prefs += XML_PREF_TEMPLATE.replace("@PREF_NAME@", pref).replace("@PREF_VAL@", val)
+        cdt_ui_prefs += "</profile>\\n</profiles>\\n"
+        with open(cdt_ui_prefs_path, 'wb') as fh:
+            fh.write(cdt_ui_prefs);
+
+        cdt_core_prefs_path = os.path.join(workspace_settings_dir, 'org.eclipse.cdt.core.prefs')
+        with open(cdt_core_prefs_path, 'wb') as fh:
+            cdt_core_prefs = STATIC_CDT_CORE_PREFS
+            # When we generated the code formatter called "Mozilla" above, we
+            # also set it to be the active formatter.  When a formatter is set
+            # as the active formatter all its prefs are set in this prefs file,
+            # so we need add those now:
+            cdt_core_prefs += FORMATTER_SETTINGS
+            fh.write(cdt_core_prefs);
 
         editor_prefs_path = os.path.join(workspace_settings_dir, "org.eclipse.ui.editors.prefs");
         with open(editor_prefs_path, 'wb') as fh:
             fh.write(EDITOR_SETTINGS);
 
         # Now import the project into the workspace
         self._import_project()
 
@@ -192,16 +222,18 @@ class CppEclipseBackend(CommonBackend):
 
         #TODO Add more launch configs (and delegate calls to mach)
 
     def _write_project(self, fh):
         project = PROJECT_TEMPLATE;
 
         project = project.replace('@PROJECT_NAME@', self._project_name)
         project = project.replace('@PROJECT_TOPSRCDIR@', self.environment.topsrcdir)
+        project = project.replace('@GENERATED_IPDL_FILES@', os.path.join(self.environment.topobjdir, "ipc", "ipdl"))
+        project = project.replace('@GENERATED_WEBIDL_FILES@', os.path.join(self.environment.topobjdir, "dom", "bindings"))
         fh.write(project)
 
     def _write_cproject(self, fh):
         cproject_header = CPROJECT_TEMPLATE_HEADER
         cproject_header = cproject_header.replace('@PROJECT_TOPSRCDIR@', self.environment.topobjdir)
         cproject_header = cproject_header.replace('@MACH_COMMAND@', os.path.join(self.environment.topsrcdir, 'mach'))
         fh.write(cproject_header)
 
@@ -248,16 +280,26 @@ PROJECT_TEMPLATE = """<?xml version="1.0
                 <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
         </natures>
         <linkedResources>
                 <link>
                         <name>tree</name>
                         <type>2</type>
                         <location>@PROJECT_TOPSRCDIR@</location>
                 </link>
+                <link>
+                        <name>generated-ipdl</name>
+                        <type>2</type>
+                        <location>@GENERATED_IPDL_FILES@</location>
+                </link>
+                <link>
+                        <name>generated-webidl</name>
+                        <type>2</type>
+                        <location>@GENERATED_WEBIDL_FILES@</location>
+                </link>
         </linkedResources>
         <filteredResources>
                 <filter>
                         <id>17111971</id>
                         <name>tree</name>
                         <type>30</type>
                         <matcher>
                                 <id>org.eclipse.ui.ide.multiFilter</id>
@@ -320,17 +362,17 @@ CPROJECT_TEMPLATE_HEADER = """<?xml vers
                                         <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
                                         <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
                                 </extensions>
                         </storageModule>
                         <storageModule moduleId="cdtBuildSystem" version="4.0.0">
                                 <configuration artifactName="${ProjName}" buildProperties="" description="" id="0.1674256904" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
                                         <folderInfo id="0.1674256904." name="/" resourcePath="">
                                                 <toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.debug.1276586933" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.debug">
-                                                        <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.710759961" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
+                                                        <targetPlatform archList="all" binaryParser="" id="cdt.managedbuild.targetPlatform.gnu.cross.710759961" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
 							<builder arguments="--log-no-times build" buildPath="@PROJECT_TOPSRCDIR@" command="@MACH_COMMAND@" enableCleanBuild="false" incrementalBuildTarget="binaries" id="org.eclipse.cdt.build.core.settings.default.builder.1437267827" keepEnvironmentInBuildfile="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
                                                 </toolChain>
                                         </folderInfo>
 """
 CPROJECT_TEMPLATE_FOLDER_INFO_HEADER = """
 					<folderInfo id="0.1674256904.@FOLDER_ID@" name="/" resourcePath="@FOLDER_NAME@">
 						<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.1022318069" name="No ToolChain" superClass="org.eclipse.cdt.build.core.prefbase.toolchain" unusedChildren="">
 							<tool id="org.eclipse.cdt.build.core.settings.holder.libs.1259030812" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs.1800697532"/>
@@ -510,18 +552,33 @@ showEnclosedSpaces=false
 showLeadingSpaces=false
 showLineFeed=false
 showWhitespaceCharacters=true
 spacesForTabs=true
 tabWidth=2
 undoHistorySize=200
 """
 
-FORMATTER_SETTINGS = """eclipse.preferences.version=1
-org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+
+STATIC_CORE_RESOURCES_PREFS="""eclipse.preferences.version=1
+refresh.enabled=true
+"""
+
+STATIC_CORE_RUNTIME_PREFS="""eclipse.preferences.version=1
+content-types/org.eclipse.cdt.core.cxxSource/file-extensions=mm
+"""
+
+STATIC_UI_PREFS="""eclipse.preferences.version=1
+showIntro=false
+"""
+
+STATIC_CDT_CORE_PREFS="""eclipse.preferences.version=1
+"""
+
+FORMATTER_SETTINGS = """org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
 org.eclipse.cdt.core.formatter.alignment_for_assignment=16
 org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
 org.eclipse.cdt.core.formatter.alignment_for_binary_expression=16
 org.eclipse.cdt.core.formatter.alignment_for_compact_if=16
 org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=34
 org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18
 org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=48
 org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
@@ -675,11 +732,19 @@ org.eclipse.cdt.core.formatter.keep_then
 org.eclipse.cdt.core.formatter.lineSplit=80
 org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
 org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
 org.eclipse.cdt.core.formatter.tabulation.char=space
 org.eclipse.cdt.core.formatter.tabulation.size=2
 org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false
 """
 
+STATIC_CDT_UI_PREFS="""eclipse.preferences.version=1
+ensureNewlineAtEOF=false
+formatter_profile=_Mozilla
+formatter_settings_version=1
+org.eclipse.cdt.ui.formatterprofiles.version=1
+scalability.numberOfLines=15000
+"""
+
 NOINDEX_TEMPLATE = """eclipse.preferences.version=1
 indexer/indexerId=org.eclipse.cdt.core.nullIndexer
 """
--- a/security/manager/ssl/DataStorage.cpp
+++ b/security/manager/ssl/DataStorage.cpp
@@ -958,18 +958,18 @@ DataStorage::SetTimer()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(XRE_IsParentProcess());
 
   MutexAutoLock lock(mMutex);
 
   nsresult rv;
   if (!mTimer) {
-    mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
+    mTimer = NS_NewTimer();
+    if (NS_WARN_IF(!mTimer)) {
       return;
     }
   }
 
   rv = mTimer->InitWithNamedFuncCallback(TimerCallback,
                                          this,
                                          mTimerDelay,
                                          nsITimer::TYPE_ONE_SHOT,
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -725,16 +725,18 @@ public:
                     kTtyIoctls == (FIOASYNC & kTypeMask),
                     "tty-related ioctls use the same type");
 
       Arg<unsigned long> request(1);
       auto shifted_type = request & kTypeMask;
 
       // Rust's stdlib seems to use FIOCLEX instead of equivalent fcntls.
       return If(request == FIOCLEX, Allow())
+        // Rust's stdlib also uses FIONBIO instead of equivalent fcntls.
+        .ElseIf(request == FIONBIO, Allow())
         // ffmpeg, and anything else that calls isatty(), will be told
         // that nothing is a typewriter:
         .ElseIf(request == TCGETS, Error(ENOTTY))
         // Bug 1408498: libgio uses FIONREAD on inotify fds.
         // (We should stop using inotify: bug 1408497.)
         .ElseIf(request == FIONREAD, Allow())
         // Allow anything that isn't a tty ioctl, for now; bug 1302711
         // will cover changing this to a default-deny policy.
--- a/startupcache/StartupCache.cpp
+++ b/startupcache/StartupCache.cpp
@@ -576,19 +576,19 @@ StartupCache::GetDebugObjectOutputStream
 
   return NS_OK;
 }
 
 nsresult
 StartupCache::ResetStartupWriteTimer()
 {
   mStartupWriteInitiated = false;
-  nsresult rv;
+  nsresult rv = NS_OK;
   if (!mTimer)
-    mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
+    mTimer = NS_NewTimer();
   else
     rv = mTimer->Cancel();
   NS_ENSURE_SUCCESS(rv, rv);
   // Wait for 10 seconds, then write out the cache.
   mTimer->InitWithNamedFuncCallback(StartupCache::WriteTimeout, this, 60000,
                                     nsITimer::TYPE_ONE_SHOT,
                                     "StartupCache::WriteTimeout");
   return NS_OK;
--- a/startupcache/StartupCacheUtils.cpp
+++ b/startupcache/StartupCacheUtils.cpp
@@ -6,58 +6,56 @@
 #include "nsIInputStream.h"
 #include "nsIStringStream.h"
 #include "nsNetUtil.h"
 #include "nsIFileURL.h"
 #include "nsIJARURI.h"
 #include "nsIResProtocolHandler.h"
 #include "nsIChromeRegistry.h"
 #include "nsAutoPtr.h"
+#include "nsStringStream.h"
 #include "StartupCacheUtils.h"
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/Omnijar.h"
 
 namespace mozilla {
 namespace scache {
 
 nsresult
 NewObjectInputStreamFromBuffer(UniquePtr<char[]> buffer, uint32_t len,
                                nsIObjectInputStream** stream)
 {
-  nsCOMPtr<nsIStringInputStream> stringStream =
-    do_CreateInstance("@mozilla.org/io/string-input-stream;1");
-  NS_ENSURE_TRUE(stringStream, NS_ERROR_FAILURE);
+  nsCOMPtr<nsIInputStream> stringStream;
+  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream),
+                                      buffer.release(), len,
+                                      NS_ASSIGNMENT_ADOPT);
+  MOZ_ALWAYS_SUCCEEDS(rv);
 
   nsCOMPtr<nsIObjectInputStream> objectInput =
-    do_CreateInstance("@mozilla.org/binaryinputstream;1");
-  NS_ENSURE_TRUE(objectInput, NS_ERROR_FAILURE);
-
-  stringStream->AdoptData(buffer.release(), len);
-  objectInput->SetInputStream(stringStream);
+    NS_NewObjectInputStream(stringStream);
 
   objectInput.forget(stream);
   return NS_OK;
 }
 
 nsresult
 NewObjectOutputWrappedStorageStream(nsIObjectOutputStream **wrapperStream,
                                     nsIStorageStream** stream,
                                     bool wantDebugStream)
 {
   nsCOMPtr<nsIStorageStream> storageStream;
 
   nsresult rv = NS_NewStorageStream(256, UINT32_MAX, getter_AddRefs(storageStream));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIObjectOutputStream> objectOutput
-    = do_CreateInstance("@mozilla.org/binaryoutputstream;1");
   nsCOMPtr<nsIOutputStream> outputStream
     = do_QueryInterface(storageStream);
 
-  objectOutput->SetOutputStream(outputStream);
+  nsCOMPtr<nsIObjectOutputStream> objectOutput
+    = NS_NewObjectOutputStream(outputStream);
 
 #ifdef DEBUG
   if (wantDebugStream) {
     // Wrap in debug stream to detect unsupported writes of
     // multiply-referenced non-singleton objects
     StartupCache* sc = StartupCache::GetSingleton();
     NS_ENSURE_TRUE(sc, NS_ERROR_UNEXPECTED);
     nsCOMPtr<nsIObjectOutputStream> debugStream;
--- a/taskcluster/ci/test/test-platforms.yml
+++ b/taskcluster/ci/test/test-platforms.yml
@@ -36,27 +36,29 @@ linux32-devedition/opt:
         - linux32-opt-tests
 
 linux64/debug:
     build-platform: linux64/debug
     test-sets:
         - common-tests
         - web-platform-tests
         - reftest-stylo
+        - mochitest-headless
 linux64/opt:
     build-platform: linux64/opt
     test-sets:
         - common-tests
         - web-platform-tests
         - opt-only-tests
         - reftest-stylo
         - desktop-screenshot-capture
         - talos
         - linux-talos-stylo-disabled
         - awsy
+        - mochitest-headless
 linux64-nightly/opt:
     build-platform: linux64-nightly/opt
     test-sets:
         - common-tests
         - web-platform-tests
         - opt-only-tests
         - desktop-screenshot-capture
         - awsy
--- a/taskcluster/ci/test/test-sets.yml
+++ b/taskcluster/ci/test/test-sets.yml
@@ -324,8 +324,11 @@ android-gradle-tests:
     - geckoview
 
 android-x86-tests:
     - mochitest-chrome
     - xpcshell
 
 devtools-tests:
     - mochitest-devtools-chrome
+
+mochitest-headless:
+    - mochitest-plain-headless
--- a/taskcluster/ci/test/tests.yml
+++ b/taskcluster/ci/test/tests.yml
@@ -856,16 +856,47 @@ mochitest-media:
                 extra-options:
                     - --mochitest-suite=mochitest-media
     tier:
         by-test-platform:
             linux64-qr/.*: 1
             windows10-64-asan.*: 3
             default: default
 
+mochitest-plain-headless:
+    description: "Mochitest plain headless run"
+    suite: mochitest/plain-chunked
+    treeherder-symbol: tc-M(h)
+    loopback-video: true
+    instance-size: legacy # Bug 1281241: migrating to m3.large instances
+    chunks:
+        by-test-platform:
+            linux.*: 10
+    e10s: true
+    max-run-time: 5400
+    allow-software-gl-layers: false
+    tier: default
+    mozharness:
+        mochitest-flavor: plain
+        script: desktop_unittest.py
+        no-read-buildbot-config: true
+        chunked: true
+        config:
+            by-test-platform:
+                windows.*:
+                    - unittests/win_taskcluster_unittest.py
+                macosx.*:
+                    - unittests/mac_unittest.py
+                linux.*:
+                    - unittests/linux_unittest.py
+                    - remove_executables.py
+        extra-options:
+            - --mochitest-suite=plain-chunked
+            - --headless
+
 mochitest-valgrind:
     description: "Mochitest plain Valgrind run"
     suite: mochitest/valgrind-plain
     treeherder-symbol: tc-M-V()
     run-on-projects: []
     tier: 3
     loopback-video: true
     chunks: 40
--- a/taskcluster/scripts/builder/sm-tooltool-config.sh
+++ b/taskcluster/scripts/builder/sm-tooltool-config.sh
@@ -20,35 +20,45 @@ case $(uname -m) in
     *)
         BITS=64
         ;;
 esac
 
 case "$OSTYPE" in
     darwin*)
         PLATFORM_OS=macosx
+        TOOLTOOL_AUTH_FILE=/builds/relengapi.tok
         ;;
     linux-gnu)
         PLATFORM_OS=linux
+        TOOLTOOL_AUTH_FILE=/builds/relengapi.tok
         ;;
     msys)
         PLATFORM_OS=win
+        TOOLTOOL_AUTH_FILE=c:/builds/relengapi.tok
         ;;
     *)
         echo "Unrecognized OSTYPE '$OSTYPE'" >&2
         PLATFORM_OS=linux
         ;;
 esac
 
+TOOLTOOL_AUTH_FLAGS=
+
+if [ -e "$TOOLTOOL_AUTH_FILE" ]; then
+    # When the worker has the relengapi token pass it down
+    TOOLTOOL_AUTH_FLAGS="--authentication-file=$TOOLTOOL_AUTH_FILE"
+fi
+
 # Install everything needed for the browser on this platform. Not all of it is
 # necessary for the JS shell, but it's less duplication to share tooltool
 # manifests.
 BROWSER_PLATFORM=$PLATFORM_OS$BITS
 
 : ${TOOLTOOL_CHECKOUT:=$WORK}
 export TOOLTOOL_CHECKOUT
 
-(cd $TOOLTOOL_CHECKOUT && ${SRCDIR}/mach artifact toolchain -v --tooltool-url $TOOLTOOL_SERVER --tooltool-manifest $SRCDIR/$TOOLTOOL_MANIFEST ${TOOLTOOL_CACHE:+ --cache-dir $TOOLTOOL_CACHE}${MOZ_TOOLCHAINS:+ ${MOZ_TOOLCHAINS}})
+(cd $TOOLTOOL_CHECKOUT && ${SRCDIR}/mach artifact toolchain -v $TOOLTOOL_AUTH_FLAGS --tooltool-url $TOOLTOOL_SERVER --tooltool-manifest $SRCDIR/$TOOLTOOL_MANIFEST ${TOOLTOOL_CACHE:+ --cache-dir $TOOLTOOL_CACHE}${MOZ_TOOLCHAINS:+ ${MOZ_TOOLCHAINS}})
 
 # Add all the tooltool binaries to our $PATH.
 for bin in ls $TOOLTOOL_CHECKOUT/*/bin; do
     export PATH="$bin:$PATH"
 done
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -469,16 +469,22 @@ class MochitestArguments(ArgumentContain
                   "for storing the screenshots."
           }],
         [["--quiet"],
          {"action": "store_true",
           "dest": "quiet",
           "default": False,
           "help": "Do not print test log lines unless a failure occurs.",
           }],
+        [["--headless"],
+         {"action": "store_true",
+          "dest": "headless",
+          "default": False,
+          "help": "Run tests in headless mode.",
+          }],
         [["--pidfile"],
          {"dest": "pidFile",
           "default": "",
           "help": "Name of the pidfile to generate.",
           "suppress": True,
           }],
         [["--use-test-media-devices"],
          {"action": "store_true",
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -1608,16 +1608,19 @@ toolbar#nav-bar {
             lsanPath=lsanPath,
             ubsanPath=ubsanPath)
 
         if hasattr(options, "topsrcdir"):
             browserEnv["MOZ_DEVELOPER_REPO_DIR"] = options.topsrcdir
         if hasattr(options, "topobjdir"):
             browserEnv["MOZ_DEVELOPER_OBJ_DIR"] = options.topobjdir
 
+        if options.headless:
+            browserEnv["MOZ_HEADLESS"] = '1'
+
         # These variables are necessary for correct application startup; change
         # via the commandline at your own risk.
         browserEnv["XPCOM_DEBUG_BREAK"] = "stack"
 
         # interpolate environment passed with options
         try:
             browserEnv.update(
                 dict(
@@ -2464,16 +2467,17 @@ toolbar#nav-bar {
     def runTests(self, options):
         """ Prepare, configure, run tests and cleanup """
 
         # a11y and chrome tests don't run with e10s enabled in CI. Need to set
         # this here since |mach mochitest| sets the flavor after argument parsing.
         if options.flavor in ('a11y', 'chrome'):
             options.e10s = False
         mozinfo.update({"e10s": options.e10s})  # for test manifest parsing.
+        mozinfo.update({"headless": options.headless})  # for test manifest parsing.
 
         if options.jscov_dir_prefix is not None:
             mozinfo.update({'coverage': True})
 
         self.setTestRoot(options)
 
         # Despite our efforts to clean up servers started by this script, in practice
         # we still see infrequent cases where a process is orphaned and interferes
--- a/testing/mozharness/configs/releases/bouncer_firefox_esr.py
+++ b/testing/mozharness/configs/releases/bouncer_firefox_esr.py
@@ -59,17 +59,17 @@ config = {
                     "bouncer-platform": "win64",
                 },
             },
         },
         "sha1-installer": {
             "product-name": "Firefox-%(version)s-sha1",
             "check_uptake": True,
             # XP/Vista Release users are redicted to ESR52
-            "alias": "firefox-sha1-ssl",
+            "alias": "firefox-sha1",
             "ssl-only": True,
             "add-locales": True,
             "paths": {
                 "win32": {
                     "path": "/firefox/releases/%(version)s/win32-sha1/:lang/Firefox%%20Setup%%20%(version)s.exe",
                     "bouncer-platform": "win",
                 },
             },
--- a/testing/mozharness/scripts/desktop_unittest.py
+++ b/testing/mozharness/scripts/desktop_unittest.py
@@ -120,16 +120,22 @@ class DesktopUnittest(TestingMixin, Merc
                     "any other suites.\nBeware, this may take a while ;)"}
          ],
         [['--e10s', ], {
             "action": "store_true",
             "dest": "e10s",
             "default": False,
             "help": "Run tests with multiple processes."}
          ],
+        [['--headless', ], {
+            "action": "store_true",
+            "dest": "headless",
+            "default": False,
+            "help": "Run tests in headless mode."}
+         ],
         [['--no-random', ], {
             "action": "store_true",
             "dest": "no_random",
             "default": False,
             "help": "Run tests with no random intermittents and bisect in case of real failure."}
          ],
         [["--total-chunks"], {
             "action": "store",
@@ -410,16 +416,20 @@ class DesktopUnittest(TestingMixin, Merc
                                  '--this-chunk', c['this_chunk']])
 
             if c['no_random']:
                 if suite_category == "mochitest":
                     base_cmd.append('--bisect-chunk=default')
                 else:
                     self.warning("--no-random does not currently work with suites other than mochitest.")
 
+
+            if c['headless']:
+                base_cmd.append('--headless');
+
             # set pluginsPath
             abs_res_plugins_dir = os.path.join(abs_res_dir, 'plugins')
             str_format_values['test_plugin_path'] = abs_res_plugins_dir
 
             if suite_category not in c["suite_definitions"]:
                 self.fatal("'%s' not defined in the config!")
 
             if suite in ('browser-chrome-coverage', 'xpcshell-coverage',
--- a/testing/mozharness/scripts/release/beet_mover.py
+++ b/testing/mozharness/scripts/release/beet_mover.py
@@ -142,22 +142,21 @@ class BeetMover(BaseScript, VirtualenvMi
                 'upload-bits',  # beets
             ],
             'require_config_file': False,
             # Default configuration
             'config': {
                 # base index url where to find taskcluster artifact based on taskid
                 "artifact_base_url": 'https://queue.taskcluster.net/v1/task/{taskid}/artifacts/public/{subdir}',
                 "virtualenv_modules": [
-                    "pip==9.0.1",
-                    "setuptools==36.6.0",
                     "boto",
                     "PyYAML",
                     "Jinja2",
                     "redo",
+                    "cryptography==2.0.3",
                     "mar",
                 ],
                 "virtualenv_path": "venv",
             },
         }
         #todo do excludes need to be configured via command line for specific builds?
         super(BeetMover, self).__init__(**beetmover_kwargs)
 
--- a/toolkit/components/alerts/AlertNotification.cpp
+++ b/toolkit/components/alerts/AlertNotification.cpp
@@ -293,22 +293,19 @@ AlertImageRequest::Cancel(nsresult aReas
 nsresult
 AlertImageRequest::Start()
 {
   // Keep the request alive until we notify the image listener.
   NS_ADDREF_THIS();
 
   nsresult rv;
   if (mTimeout > 0) {
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (NS_WARN_IF(!mTimer)) {
-      return NotifyMissing();
-    }
-    rv = mTimer->InitWithCallback(this, mTimeout,
-                                  nsITimer::TYPE_ONE_SHOT);
+    rv = NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                                 this, mTimeout,
+                                 nsITimer::TYPE_ONE_SHOT);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return NotifyMissing();
     }
   }
 
   // Begin loading the image.
   imgLoader* il = imgLoader::NormalLoader();
   if (!il) {
--- a/toolkit/components/autocomplete/nsAutoCompleteController.cpp
+++ b/toolkit/components/autocomplete/nsAutoCompleteController.cpp
@@ -1419,25 +1419,18 @@ nsAutoCompleteController::StartSearches(
       AfterSearches();
       return NS_OK;
     }
   }
 
   MOZ_ASSERT(timeout > 0, "Trying to delay searches with a 0 timeout!");
 
   // Now start the delayed searches.
-  nsresult rv;
-  mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  if (NS_FAILED(rv))
-      return rv;
-  rv = mTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
-  if (NS_FAILED(rv))
-      mTimer = nullptr;
-
-  return rv;
+  return NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                                 this, timeout, nsITimer::TYPE_ONE_SHOT);
 }
 
 nsresult
 nsAutoCompleteController::ClearSearchTimer()
 {
   if (mTimer) {
     mTimer->Cancel();
     mTimer = nullptr;
--- a/toolkit/components/downloads/ApplicationReputation.cpp
+++ b/toolkit/components/downloads/ApplicationReputation.cpp
@@ -1379,18 +1379,18 @@ PendingLookup::SendRemoteQueryInternal()
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = uploadChannel->ExplicitSetUploadStream(sstream,
     NS_LITERAL_CSTRING("application/octet-stream"), serialized.size(),
     NS_LITERAL_CSTRING("POST"), false);
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t timeoutMs = Preferences::GetUint(PREF_SB_DOWNLOADS_REMOTE_TIMEOUT, 10000);
-  mTimeoutTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  mTimeoutTimer->InitWithCallback(this, timeoutMs, nsITimer::TYPE_ONE_SHOT);
+  NS_NewTimerWithCallback(getter_AddRefs(mTimeoutTimer),
+                          this, timeoutMs, nsITimer::TYPE_ONE_SHOT);
 
   rv = mChannel->AsyncOpen2(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/toolkit/components/extensions/test/mochitest/mochitest-common.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest-common.ini
@@ -55,17 +55,17 @@ support-files =
   return_headers.sjs
   slow_response.sjs
   webrequest_worker.js
   !/toolkit/components/passwordmgr/test/authenticate.sjs
   !/dom/tests/mochitest/geolocation/network_geolocation.sjs
 
 [test_ext_clipboard.html]
 [test_ext_clipboard_image.html]
-# skip-if = # disabled test case with_permission_allow_copy, see inline comment.
+skip-if = headless # disabled test case with_permission_allow_copy, see inline comment. Headless: Bug 1405872
 [test_ext_inIncognitoContext_window.html]
 skip-if = os == 'android' # Android does not support multiple windows.
 [test_ext_geturl.html]
 [test_ext_background_canvas.html]
 [test_ext_content_security_policy.html]
 [test_ext_contentscript_api_injection.html]
 [test_ext_contentscript_async_loading.html]
 skip-if = os == 'android' && debug # The generated script takes too long to load on Android debug
--- a/toolkit/components/extensions/test/mochitest/test_ext_webrequest_responseBody.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_webrequest_responseBody.html
@@ -402,16 +402,107 @@ add_task(async function() {
     }
   } else {
     await Promise.all(TASKS.map(runTest));
   }
 
   await extension.unload();
 });
 
+// Test that registering a listener for a cached response does not cause a crash.
+add_task(async function test_cachedResponse() {
+  let extension = ExtensionTestUtils.loadExtension({
+    background() {
+      browser.webRequest.onHeadersReceived.addListener(data => {
+        let filter = browser.webRequest.filterResponseData(data.requestId);
+
+        filter.onstop = event => {
+          filter.close();
+        };
+        filter.ondata = event => {
+          filter.write(event.data);
+        };
+
+        if (data.fromCache) {
+          browser.test.sendMessage("from-cache");
+        }
+      }, {
+        urls: ["http://mochi.test/*/file_sample.html?r=*"],
+      },
+      ["blocking"]);
+    },
+
+    manifest: {
+      permissions: [
+        "webRequest",
+        "webRequestBlocking",
+        "http://mochi.test/",
+      ],
+    },
+  });
+
+  await extension.startup();
+
+  let url = `file_sample.html?r=${Math.random()}`;
+  await fetch(url);
+  await fetch(url);
+  await extension.awaitMessage("from-cache");
+
+  await extension.unload();
+});
+
+// Test that finishing transferring data doesn't overwrite an existing closing/closed state.
+add_task(async function test_late_close() {
+  let extension = ExtensionTestUtils.loadExtension({
+    background() {
+      browser.webRequest.onBeforeRequest.addListener(data => {
+        let filter = browser.webRequest.filterResponseData(data.requestId);
+
+        filter.onstop = event => {
+          browser.test.fail("Should not receive onstop after close()");
+          browser.test.assertEq("closed", filter.status,
+                                "Filter status should still be 'closed'");
+          browser.test.assertThrows(() => { filter.close(); });
+        };
+        filter.ondata = event => {
+          filter.write(event.data);
+          filter.close();
+
+          browser.test.sendMessage(`done-${data.url}`);
+        };
+      }, {
+        urls: ["http://mochi.test/*/file_sample.html?*"],
+      },
+      ["blocking"]);
+    },
+
+    manifest: {
+      permissions: [
+        "webRequest",
+        "webRequestBlocking",
+        "http://mochi.test/",
+      ],
+    },
+  });
+
+  await extension.startup();
+
+  // This issue involves a race, so several requests in parallel to increase
+  // the chances of triggering it.
+  let urls = [];
+  for (let i = 0; i < 32; i++) {
+    urls.push(new URL(`file_sample.html?r=${Math.random()}`, location).href);
+  }
+
+  await Promise.all(urls.map(url => fetch(url)));
+  await Promise.all(urls.map(url => extension.awaitMessage(`done-${url}`)));
+
+  await extension.unload();
+});
+
 add_task(async function test_permissions() {
   let extension = ExtensionTestUtils.loadExtension({
     background() {
       browser.test.assertEq(
           undefined, browser.webRequest.filterResponseData,
           "filterResponseData is undefined without blocking permissions");
     },
 
--- a/toolkit/components/extensions/webrequest/ChannelWrapper.cpp
+++ b/toolkit/components/extensions/webrequest/ChannelWrapper.cpp
@@ -625,16 +625,22 @@ ChannelWrapper::GetFrameAncestors(nsILoa
 
 /*****************************************************************************
  * Response filtering
  *****************************************************************************/
 
 void
 ChannelWrapper::RegisterTraceableChannel(const WebExtensionPolicy& aAddon, nsITabParent* aTabParent)
 {
+  // We can't attach new listeners after the response has started, so don't
+  // bother registering anything.
+  if (mResponseStarted) {
+    return;
+  }
+
   mAddonEntries.Put(aAddon.Id(), aTabParent);
   if (!mChannelEntry) {
     mChannelEntry = WebRequestService::GetSingleton().RegisterChannel(this);
     CheckEventListeners();
   }
 }
 
 already_AddRefed<nsITraceableChannel>
@@ -909,16 +915,17 @@ ChannelWrapper::RequestListener::Init()
 }
 
 NS_IMETHODIMP
 ChannelWrapper::RequestListener::OnStartRequest(nsIRequest *request, nsISupports * aCtxt)
 {
   MOZ_ASSERT(mOrigStreamListener, "Should have mOrigStreamListener");
 
   mChannelWrapper->mChannelEntry = nullptr;
+  mChannelWrapper->mResponseStarted = true;
   mChannelWrapper->ErrorCheck();
   mChannelWrapper->FireEvent(NS_LITERAL_STRING("start"));
 
   return mOrigStreamListener->OnStartRequest(request, aCtxt);
 }
 
 NS_IMETHODIMP
 ChannelWrapper::RequestListener::OnStopRequest(nsIRequest *request, nsISupports *aCtxt,
--- a/toolkit/components/extensions/webrequest/ChannelWrapper.h
+++ b/toolkit/components/extensions/webrequest/ChannelWrapper.h
@@ -283,16 +283,17 @@ private:
   nsCString mContentTypeHdr = VoidCString();
 
   const uint64_t mId = GetNextId();
   nsCOMPtr<nsISupports> mParent;
 
   bool mAddedStreamListener = false;
   bool mFiredErrorEvent = false;
   bool mSuspended = false;
+  bool mResponseStarted = false;
 
 
   nsInterfaceHashtable<nsPtrHashKey<const nsAtom>, nsITabParent> mAddonEntries;
 
 
   class RequestListener final : public nsIStreamListener
                               , public nsIThreadRetargetableStreamListener
   {
--- a/toolkit/components/extensions/webrequest/StreamFilterChild.cpp
+++ b/toolkit/components/extensions/webrequest/StreamFilterChild.cpp
@@ -262,16 +262,18 @@ StreamFilterChild::MaybeStopRequest()
 
   switch (mState) {
   case State::Suspending:
   case State::Resuming:
     mNextState = State::FinishedTransferringData;
     return;
 
   case State::Disconnecting:
+  case State::Closing:
+  case State::Closed:
     break;
 
   default:
     mState = State::FinishedTransferringData;
     if (mStreamFilter) {
       mStreamFilter->FireEvent(NS_LITERAL_STRING("stop"));
       // We don't need access to the stream filter after this point, so break our
       // reference cycle, so that it can be collected if we're the last reference.
--- a/toolkit/components/extensions/webrequest/StreamFilterParent.cpp
+++ b/toolkit/components/extensions/webrequest/StreamFilterParent.cpp
@@ -4,44 +4,120 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "StreamFilterParent.h"
 
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/ContentParent.h"
+#include "mozilla/net/ChannelEventQueue.h"
 #include "nsHttpChannel.h"
 #include "nsIChannel.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIInputStream.h"
 #include "nsITraceableChannel.h"
 #include "nsProxyRelease.h"
 #include "nsQueryObject.h"
 #include "nsSocketTransportService2.h"
 #include "nsStringStream.h"
 
 namespace mozilla {
 namespace extensions {
 
 /*****************************************************************************
+ * Event queueing helpers
+ *****************************************************************************/
+
+using net::ChannelEvent;
+using net::ChannelEventQueue;
+
+namespace {
+
+// Define some simple ChannelEvent sub-classes that store the appropriate
+// EventTarget and delegate their Run methods to a wrapped Runnable or lambda
+// function.
+
+class ChannelEventWrapper : public ChannelEvent
+{
+public:
+  ChannelEventWrapper(nsIEventTarget* aTarget)
+    : mTarget(aTarget)
+  {}
+
+  already_AddRefed<nsIEventTarget> GetEventTarget() override
+  {
+    return do_AddRef(mTarget.get());
+  }
+
+protected:
+  ~ChannelEventWrapper() override = default;
+
+private:
+  nsCOMPtr<nsIEventTarget> mTarget;
+};
+
+class ChannelEventFunction final : public ChannelEventWrapper
+{
+public:
+  ChannelEventFunction(nsIEventTarget* aTarget, std::function<void()>&& aFunc)
+    : ChannelEventWrapper(aTarget)
+    , mFunc(Move(aFunc))
+  {}
+
+  void Run() override
+  {
+    mFunc();
+  }
+
+protected:
+  ~ChannelEventFunction() override = default;
+
+private:
+  std::function<void()> mFunc;
+};
+
+class ChannelEventRunnable final : public ChannelEventWrapper
+{
+public:
+  ChannelEventRunnable(nsIEventTarget* aTarget, already_AddRefed<Runnable> aRunnable)
+    : ChannelEventWrapper(aTarget)
+    , mRunnable(aRunnable)
+  {}
+
+  void Run() override
+  {
+    nsresult rv = mRunnable->Run();
+    Unused << NS_WARN_IF(NS_FAILED(rv));
+  }
+
+protected:
+  ~ChannelEventRunnable() override = default;
+
+private:
+  RefPtr<Runnable> mRunnable;
+};
+
+} // anonymous namespace
+
+/*****************************************************************************
  * Initialization
  *****************************************************************************/
 
 StreamFilterParent::StreamFilterParent()
   : mMainThread(GetCurrentThreadEventTarget())
   , mIOThread(mMainThread)
+  , mQueue(new ChannelEventQueue(static_cast<nsIStreamListener*>(this)))
   , mBufferMutex("StreamFilter buffer mutex")
   , mReceivedStop(false)
   , mSentStop(false)
   , mContext(nullptr)
   , mOffset(0)
   , mState(State::Uninitialized)
-{
-}
+{}
 
 StreamFilterParent::~StreamFilterParent()
 {
   NS_ReleaseOnMainThreadSystemGroup("StreamFilterParent::mOrigListener",
                                     mOrigListener.forget());
   NS_ReleaseOnMainThreadSystemGroup("StreamFilterParent::mContext",
                                     mContext.forget());
 }
@@ -116,18 +192,21 @@ StreamFilterParent::Init(nsIChannel* aCh
  * nsIThreadRetargetableStreamListener
  *****************************************************************************/
 
 NS_IMETHODIMP
 StreamFilterParent::CheckListenerChain()
 {
   AssertIsMainThread();
 
-  // Disable thread retargeting due to segments being delivbered out-of-order.
-  // See bug 1405286.
+  nsCOMPtr<nsIThreadRetargetableStreamListener> trsl =
+    do_QueryInterface(mOrigListener);
+  if (trsl) {
+    return trsl->CheckListenerChain();
+  }
   return NS_ERROR_FAILURE;
 }
 
 /*****************************************************************************
  * Error handling
  *****************************************************************************/
 
 void
@@ -157,23 +236,19 @@ IPCResult
 StreamFilterParent::RecvClose()
 {
   AssertIsActorThread();
 
   mState = State::Closed;
 
   if (!mSentStop) {
     RefPtr<StreamFilterParent> self(this);
-    // Make a trip through the IO thread to be sure OnStopRequest is emitted
-    // after the last OnDataAvailable event.
-    RunOnIOThread(FUNC, [=] {
-      RunOnMainThread(FUNC, [=] {
-        nsresult rv = self->EmitStopRequest(NS_OK);
-        Unused << NS_WARN_IF(NS_FAILED(rv));
-      });
+    RunOnMainThread(FUNC, [=] {
+      nsresult rv = self->EmitStopRequest(NS_OK);
+      Unused << NS_WARN_IF(NS_FAILED(rv));
     });
   }
 
   Unused << SendClosed();
   Destroy();
   return IPC_OK();
 }
 
@@ -235,17 +310,17 @@ StreamFilterParent::RecvResume()
 }
 
 IPCResult
 StreamFilterParent::RecvDisconnect()
 {
   AssertIsActorThread();
 
   if (mState == State::Suspended) {
-  RefPtr<StreamFilterParent> self(this);
+    RefPtr<StreamFilterParent> self(this);
     RunOnMainThread(FUNC, [=] {
       self->mChannel->Resume();
     });
   } else if (mState != State::TransferringData) {
     return IPC_OK();
   }
 
   mState = State::Disconnecting;
@@ -277,26 +352,22 @@ StreamFilterParent::RecvFlushedData()
  * Data output
  *****************************************************************************/
 
 IPCResult
 StreamFilterParent::RecvWrite(Data&& aData)
 {
   AssertIsActorThread();
 
-  if (IsIOThread()) {
-    Write(aData);
-  } else {
-    IOThread()->Dispatch(
-      NewRunnableMethod<Data&&>("StreamFilterParent::WriteMove",
-                                this,
-                                &StreamFilterParent::WriteMove,
-                                Move(aData)),
-      NS_DISPATCH_NORMAL);
-  }
+
+  RunOnIOThread(
+    NewRunnableMethod<Data&&>("StreamFilterParent::WriteMove",
+                              this,
+                              &StreamFilterParent::WriteMove,
+                              Move(aData)));
   return IPC_OK();
 }
 
 void
 StreamFilterParent::WriteMove(Data&& aData)
 {
   nsresult rv = Write(aData);
   Unused << NS_WARN_IF(NS_FAILED(rv));
@@ -337,17 +408,26 @@ StreamFilterParent::OnStartRequest(nsIRe
     RunOnActorThread(FUNC, [=] {
       if (self->IPCActive()) {
         self->mState = State::TransferringData;
         self->CheckResult(self->SendStartRequest());
       }
     });
   }
 
-  return mOrigListener->OnStartRequest(aRequest, aContext);
+  nsresult rv = mOrigListener->OnStartRequest(aRequest, aContext);
+
+  // Important: Do this only *after* running the next listener in the chain, so
+  // that we get the final delivery target after any retargeting that it may do.
+  if (nsCOMPtr<nsIThreadRetargetableRequest> req = do_QueryInterface(aRequest)) {
+    Unused << req->GetDeliveryTarget(getter_AddRefs(mIOThread));
+    MOZ_ASSERT(mIOThread);
+  }
+
+  return rv;
 }
 
 NS_IMETHODIMP
 StreamFilterParent::OnStopRequest(nsIRequest* aRequest,
                                   nsISupports* aContext,
                                   nsresult aStatusCode)
 {
   AssertIsMainThread();
@@ -392,23 +472,17 @@ StreamFilterParent::DoSendData(Data&& aD
 
 NS_IMETHODIMP
 StreamFilterParent::OnDataAvailable(nsIRequest* aRequest,
                                     nsISupports* aContext,
                                     nsIInputStream* aInputStream,
                                     uint64_t aOffset,
                                     uint32_t aCount)
 {
-  // Note: No AssertIsIOThread here. Whatever thread we're on now is, by
-  // definition, the IO thread.
-  if (OnSocketThread()) {
-    mIOThread = nullptr;
-  } else {
-    mIOThread = NS_GetCurrentThread();
-  }
+  AssertIsIOThread();
 
   if (mState == State::Disconnected) {
     // If we're offloading data in a thread pool, it's possible that we'll
     // have buffered some additional data while waiting for the buffer to
     // flush. So, if there's any buffered data left, flush that before we
     // flush this incoming data.
     //
     // Note: When in the eDisconnected state, the buffer list is guaranteed
@@ -476,72 +550,103 @@ StreamFilterParent::FlushBufferedData()
 
   return NS_OK;
 }
 
 /*****************************************************************************
  * Thread helpers
  *****************************************************************************/
 
-void
-StreamFilterParent::AssertIsActorThread()
-{
-  MOZ_ASSERT(OnSocketThread());
-}
-
 nsIEventTarget*
 StreamFilterParent::ActorThread()
 {
   return gSocketTransportService;
 }
 
+bool
+StreamFilterParent::IsActorThread()
+{
+  return ActorThread()->IsOnCurrentThread();
+}
+
+void
+StreamFilterParent::AssertIsActorThread()
+{
+  MOZ_ASSERT(IsActorThread());
+}
+
 nsIEventTarget*
 StreamFilterParent::IOThread()
 {
-  if (mIOThread) {
-    return mIOThread;
-  }
-  return gSocketTransportService;
+  return mIOThread;
 }
 
 bool
 StreamFilterParent::IsIOThread()
 {
-  return (mIOThread ? NS_GetCurrentThread() == mIOThread
-                    : OnSocketThread());
+  return mIOThread->IsOnCurrentThread();
 }
 
 void
 StreamFilterParent::AssertIsIOThread()
 {
   MOZ_ASSERT(IsIOThread());
 }
 
 template<typename Function>
 void
-StreamFilterParent::RunOnActorThread(const char* aName, Function&& aFunc)
+StreamFilterParent::RunOnMainThread(const char* aName, Function&& aFunc)
 {
-  if (OnSocketThread()) {
-    aFunc();
-  } else {
-    gSocketTransportService->Dispatch(
-      Move(NS_NewRunnableFunction(aName, aFunc)),
-      NS_DISPATCH_NORMAL);
-  }
+  mQueue->RunOrEnqueue(new ChannelEventFunction(mMainThread, Move(aFunc)));
+}
+
+void
+StreamFilterParent::RunOnMainThread(already_AddRefed<Runnable> aRunnable)
+{
+  mQueue->RunOrEnqueue(new ChannelEventRunnable(mMainThread, Move(aRunnable)));
 }
 
 template<typename Function>
 void
 StreamFilterParent::RunOnIOThread(const char* aName, Function&& aFunc)
 {
-  if (mIOThread) {
-    mIOThread->Dispatch(Move(NS_NewRunnableFunction(aName, aFunc)),
-                        NS_DISPATCH_NORMAL);
+  mQueue->RunOrEnqueue(new ChannelEventFunction(mIOThread, Move(aFunc)));
+}
+
+void
+StreamFilterParent::RunOnIOThread(already_AddRefed<Runnable> aRunnable)
+{
+  mQueue->RunOrEnqueue(new ChannelEventRunnable(mIOThread, Move(aRunnable)));
+}
+
+template<typename Function>
+void
+StreamFilterParent::RunOnActorThread(const char* aName, Function&& aFunc)
+{
+  // We don't use mQueue for dispatch to the actor thread.
+  //
+  // The main thread and IO thread are used for dispatching events to the
+  // wrapped stream listener, and those events need to be processed
+  // consistently, in the order they were dispatched. An event dispatched to the
+  // main thread can't be run before events that were dispatched to the IO
+  // thread before it.
+  //
+  // Additionally, the IO thread is likely to be a thread pool, which means that
+  // without thread-safe queuing, it's possible for multiple events dispatched
+  // to it to be processed in parallel, or out of order.
+  //
+  // The actor thread, however, is always a serial event target. Its events are
+  // always processed in order, and events dispatched to the actor thread are
+  // independent of the events in the output event queue.
+  if (IsActorThread()) {
+    aFunc();
   } else {
-    RunOnActorThread(aName, Move(aFunc));
+    ActorThread()->Dispatch(
+      Move(NS_NewRunnableFunction(aName, aFunc)),
+      NS_DISPATCH_NORMAL);
   }
 }
 
 /*****************************************************************************
  * Glue
  *****************************************************************************/
 
 void
--- a/toolkit/components/extensions/webrequest/StreamFilterParent.h
+++ b/toolkit/components/extensions/webrequest/StreamFilterParent.h
@@ -25,16 +25,17 @@
 #  define FUNC __PRETTY_FUNCTION__
 #endif
 
 namespace mozilla {
 namespace dom {
   class ContentParent;
 }
 namespace net {
+  class ChannelEventQueue;
   class nsHttpChannel;
 }
 
 namespace extensions {
 
 using namespace mozilla::dom;
 using mozilla::ipc::IPCResult;
 
@@ -132,46 +133,49 @@ private:
   }
 
   inline nsIEventTarget* ActorThread();
 
   inline nsIEventTarget* IOThread();
 
   inline bool IsIOThread();
 
+  inline bool IsActorThread();
+
   inline void AssertIsActorThread();
 
   inline void AssertIsIOThread();
 
   static void
   AssertIsMainThread()
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
   template<typename Function>
-  void
-  RunOnMainThread(const char* aName, Function&& aFunc)
-  {
-    mMainThread->Dispatch(Move(NS_NewRunnableFunction(aName, aFunc)),
-                          NS_DISPATCH_NORMAL);
-  }
+  void RunOnMainThread(const char* aName, Function&& aFunc);
+
+  void RunOnMainThread(already_AddRefed<Runnable> aRunnable);
 
   template<typename Function>
   void RunOnActorThread(const char* aName, Function&& aFunc);
 
   template<typename Function>
   void RunOnIOThread(const char* aName, Function&& aFunc);
 
+  void RunOnIOThread(already_AddRefed<Runnable>);
+
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsIStreamListener> mOrigListener;
 
   nsCOMPtr<nsIEventTarget> mMainThread;
   nsCOMPtr<nsIEventTarget> mIOThread;
 
+  RefPtr<net::ChannelEventQueue> mQueue;
+
   Mutex mBufferMutex;
 
   bool mReceivedStop;
   bool mSentStop;
 
   nsCOMPtr<nsISupports> mContext;
   uint64_t mOffset;
 
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
+++ b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
@@ -598,17 +598,17 @@ PendingAlertsCollector::GetName(nsACStri
 nsresult
 PendingAlertsCollector::Start(uint32_t timerDelayMS) {
   if (mPending) {
     // Collector is already started.
     return NS_OK;
   }
 
   if (!mTimer) {
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mTimer = NS_NewTimer();
   }
 
   nsresult rv = mTimer->InitWithCallback(this, timerDelayMS, nsITimer::TYPE_ONE_SHOT);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   mPending = true;
--- a/toolkit/components/places/nsFaviconService.cpp
+++ b/toolkit/components/places/nsFaviconService.cpp
@@ -162,17 +162,17 @@ nsFaviconService::StoreLastInsertedId(co
 }
 
 nsresult
 nsFaviconService::Init()
 {
   mDB = Database::GetDatabase();
   NS_ENSURE_STATE(mDB);
 
-  mExpireUnassociatedIconsTimer = do_CreateInstance("@mozilla.org/timer;1");
+  mExpireUnassociatedIconsTimer = NS_NewTimer();
   NS_ENSURE_STATE(mExpireUnassociatedIconsTimer);
 
   // Check if there are still icon payloads to be converted.
   bool shouldConvertPayloads =
     Preferences::GetBool(PREF_CONVERT_PAYLOADS, false);
   if (shouldConvertPayloads) {
     ConvertUnsupportedPayloads(mDB->MainConn());
   }
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -668,17 +668,17 @@ nsNavHistory::GetDaysOfHistory() {
 }
 
 PRTime
 nsNavHistory::GetNow()
 {
   if (!mCachedNow) {
     mCachedNow = PR_Now();
     if (!mExpireNowTimer)
-      mExpireNowTimer = do_CreateInstance("@mozilla.org/timer;1");
+      mExpireNowTimer = NS_NewTimer();
     if (mExpireNowTimer)
       mExpireNowTimer->InitWithNamedFuncCallback(expireNowTimerCallback,
                                                  this,
                                                  RENEW_CACHED_NOW_TIMEOUT,
                                                  nsITimer::TYPE_ONE_SHOT,
                                                  "nsNavHistory::GetNow");
   }
   return mCachedNow;
--- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
+++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp
@@ -370,24 +370,21 @@ nsBrowserStatusFilter::MaybeSendStatus()
     }
 }
 
 nsresult
 nsBrowserStatusFilter::StartDelayTimer()
 {
     NS_ASSERTION(!DelayInEffect(), "delay should not be in effect");
 
-    mTimer = do_CreateInstance("@mozilla.org/timer;1");
-    if (!mTimer)
-        return NS_ERROR_FAILURE;
-
-    mTimer->SetTarget(mTarget);
-    return mTimer->InitWithNamedFuncCallback(
-        TimeoutHandler, this, 160, nsITimer::TYPE_ONE_SHOT,
-        "nsBrowserStatusFilter::TimeoutHandler");
+    return NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+                                       TimeoutHandler, this, 160,
+                                       nsITimer::TYPE_ONE_SHOT,
+                                       "nsBrowserStatusFilter::TimeoutHandler",
+                                       mTarget);
 }
 
 void
 nsBrowserStatusFilter::ProcessTimeout()
 {
     mTimer = nullptr;
 
     if (!mListener)
--- a/toolkit/components/telemetry/ipc/TelemetryIPCAccumulator.cpp
+++ b/toolkit/components/telemetry/ipc/TelemetryIPCAccumulator.cpp
@@ -82,20 +82,17 @@ void
 DoArmIPCTimerMainThread(const StaticMutexAutoLock& lock)
 {
   MOZ_ASSERT(NS_IsMainThread());
   gIPCTimerArming = false;
   if (gIPCTimerArmed) {
     return;
   }
   if (!gIPCTimer) {
-    CallCreateInstance(NS_TIMER_CONTRACTID, &gIPCTimer);
-    if (gIPCTimer) {
-      gIPCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::Other));
-    }
+    gIPCTimer = NS_NewTimer(SystemGroup::EventTargetFor(TaskCategory::Other)).take();
   }
   if (gIPCTimer) {
     gIPCTimer->InitWithNamedFuncCallback(TelemetryIPCAccumulator::IPCTimerFired,
                                          nullptr, kBatchTimeoutMs,
                                          nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
                                          "TelemetryIPCAccumulator::IPCTimerFired");
     gIPCTimerArmed = true;
   }
--- a/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.cpp
@@ -14,16 +14,17 @@
 #include "nsNetUtil.h"
 #include "nsStreamUtils.h"
 #include "nsStringStream.h"
 #include "nsToolkitCompsCID.h"
 #include "nsUrlClassifierStreamUpdater.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/ErrorNames.h"
 #include "mozilla/Logging.h"
+#include "mozilla/ResultExtensions.h"
 #include "nsIInterfaceRequestor.h"
 #include "mozilla/LoadContext.h"
 #include "mozilla/Telemetry.h"
 #include "nsContentUtils.h"
 #include "nsIURLFormatter.h"
 #include "Classifier.h"
 #include "UrlClassifierTelemetryUtils.h"
 
@@ -213,33 +214,27 @@ nsUrlClassifierStreamUpdater::FetchUpdat
     preferencesInitialized = true;
   }
 
   if (sResponseTimeoutMs > sTimeoutMs) {
     NS_WARNING("Safe Browsing response timeout is greater than the general "
       "timeout. Disabling these update timeouts.");
     return NS_OK;
   }
-  mResponseTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  if (NS_SUCCEEDED(rv)) {
-    rv = mResponseTimeoutTimer->InitWithCallback(this,
-                                                 sResponseTimeoutMs,
-                                                 nsITimer::TYPE_ONE_SHOT);
-  }
-
-  mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
+  MOZ_TRY_VAR(mResponseTimeoutTimer,
+              NS_NewTimerWithCallback(this, sResponseTimeoutMs,
+                                      nsITimer::TYPE_ONE_SHOT));
 
-  if (NS_SUCCEEDED(rv)) {
-    if (sTimeoutMs < DEFAULT_TIMEOUT_MS) {
-      LOG(("Download update timeout %d ms (< %d ms) would be too small",
-           sTimeoutMs, DEFAULT_TIMEOUT_MS));
-    }
-    rv = mTimeoutTimer->InitWithCallback(this,
-                                         sTimeoutMs,
-                                         nsITimer::TYPE_ONE_SHOT);
+  MOZ_TRY_VAR(mTimeoutTimer,
+              NS_NewTimerWithCallback(this, sTimeoutMs,
+                                      nsITimer::TYPE_ONE_SHOT));
+
+  if (sTimeoutMs < DEFAULT_TIMEOUT_MS) {
+    LOG(("Download update timeout %d ms (< %d ms) would be too small",
+         sTimeoutMs, DEFAULT_TIMEOUT_MS));
   }
 
   return NS_OK;
 }
 
 nsresult
 nsUrlClassifierStreamUpdater::FetchUpdate(const nsACString & aUpdateUrl,
                                           const nsACString & aRequestPayload,
@@ -328,23 +323,19 @@ nsUrlClassifierStreamUpdater::DownloadUp
       return NS_ERROR_OUT_OF_MEMORY;
     }
     BuildUpdateRequest(aRequestTables, aRequestPayload, aIsPostRequest, aUpdateUrl,
                        aSuccessCallback, aUpdateErrorCallback, aDownloadErrorCallback,
                        request);
 
     // We cannot guarantee that we will be notified when DBService is done
     // processing the current update, so we fire a retry timer on our own.
-    nsresult rv;
-    mFetchNextRequestTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-    if (NS_SUCCEEDED(rv)) {
-      rv = mFetchNextRequestTimer->InitWithCallback(this,
-                                                    FETCH_NEXT_REQUEST_RETRY_DELAY_MS,
-                                                    nsITimer::TYPE_ONE_SHOT);
-    }
+    MOZ_TRY_VAR(mFetchNextRequestTimer,
+                NS_NewTimerWithCallback(this, FETCH_NEXT_REQUEST_RETRY_DELAY_MS,
+                                        nsITimer::TYPE_ONE_SHOT));
 
     return NS_OK;
   }
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
@@ -492,21 +483,18 @@ nsUrlClassifierStreamUpdater::StreamFini
     return NS_OK;
   }
 
   // This timer is for fetching indirect updates ("forwards") from any "u:" lines
   // that we encountered while processing the server response. It is NOT for
   // scheduling the next time we pull the list from the server. That's a different
   // timer in listmanager.js (see bug 1110891).
   nsresult rv;
-  mFetchIndirectUpdatesTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-  if (NS_SUCCEEDED(rv)) {
-    rv = mFetchIndirectUpdatesTimer->InitWithCallback(this, requestedDelay,
-                                                      nsITimer::TYPE_ONE_SHOT);
-  }
+  rv = NS_NewTimerWithCallback(getter_AddRefs(mFetchIndirectUpdatesTimer),
+                               this, requestedDelay, nsITimer::TYPE_ONE_SHOT);
 
   if (NS_FAILED(rv)) {
     NS_WARNING("Unable to initialize timer, fetching next safebrowsing item immediately");
     return FetchNext();
   }
 
   return NS_OK;
 }
--- a/toolkit/content/widgets/datetimebox.css
+++ b/toolkit/content/widgets/datetimebox.css
@@ -7,17 +7,16 @@
 
 .datetime-input-box-wrapper {
   -moz-appearance: none;
   display: inline-flex;
   flex: 1;
   cursor: default;
   background-color: inherit;
   color: inherit;
-  font-family: monospace;
   min-width: 0;
   justify-content: space-between;
 }
 
 .datetime-input-edit-wrapper {
   overflow: hidden;
   white-space: nowrap;
 }
--- a/toolkit/modules/addons/WebRequest.jsm
+++ b/toolkit/modules/addons/WebRequest.jsm
@@ -161,17 +161,17 @@ class ResponseHeaderChanger extends Head
   }
 
   readHeaders() {
     return this.channel.getResponseHeaders();
   }
 }
 
 const MAYBE_CACHED_EVENTS = new Set([
-  "onResponseStarted", "onBeforeRedirect", "onCompleted", "onErrorOccurred",
+  "onResponseStarted", "onHeadersReceived", "onBeforeRedirect", "onCompleted", "onErrorOccurred",
 ]);
 
 const OPTIONAL_PROPERTIES = [
   "requestHeaders", "responseHeaders", "statusCode", "statusLine", "error", "redirectUrl",
   "requestBody", "scheme", "realm", "isProxy", "challenger", "proxyInfo", "ip", "frameAncestors",
 ];
 
 function serializeRequestData(eventName) {
--- a/tools/profiler/gecko/ThreadResponsiveness.cpp
+++ b/tools/profiler/gecko/ThreadResponsiveness.cpp
@@ -57,18 +57,18 @@ public:
 
   // Can only run on the main thread.
   NS_IMETHOD Run() override
   {
     mStartToPrevTracer_us = uint64_t(profiler_time() * 1000.0);
 
     if (!mStop) {
       if (!mTimer) {
-        mTimer = do_CreateInstance("@mozilla.org/timer;1");
-        mTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::Other));
+        mTimer = NS_NewTimer(
+          SystemGroup::EventTargetFor(TaskCategory::Other));
       }
       mTimer->InitWithCallback(this, 16, nsITimer::TYPE_ONE_SHOT);
     }
 
     return NS_OK;
   }
 
   // Main thread only
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
 
 /* This must occur *after* base/basictypes.h to avoid typedefs conflicts. */
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Base64.h"
+#include "mozilla/ResultExtensions.h"
 
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/TabChild.h"
 #include "nsXULAppAPI.h"
 
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsIURI.h"
@@ -2526,22 +2527,17 @@ nsresult nsExternalAppHandler::MaybeClos
     nsCOMPtr<nsPIDOMWindowOuter> opener = window->GetOpener();
 
     if (opener && !opener->Closed()) {
       mContentContext = do_GetInterface(opener);
 
       // Now close the old window.  Do it on a timer so that we don't run
       // into issues trying to close the window before it has fully opened.
       NS_ASSERTION(!mTimer, "mTimer was already initialized once!");
-      mTimer = do_CreateInstance("@mozilla.org/timer;1");
-      if (!mTimer) {
-        return NS_ERROR_FAILURE;
-      }
-
-      mTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT);
+      MOZ_TRY_VAR(mTimer, NS_NewTimerWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT));
       mWindowToClose = window;
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/widget/cocoa/TextInputHandler.mm
+++ b/widget/cocoa/TextInputHandler.mm
@@ -2911,17 +2911,17 @@ IMEInputHandler::SyncASCIICapableOnly()
 void
 IMEInputHandler::ResetTimer()
 {
   NS_ASSERTION(mPendingMethods != 0,
                "There are not pending methods, why this is called?");
   if (mTimer) {
     mTimer->Cancel();
   } else {
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mTimer = NS_NewTimer();
     NS_ENSURE_TRUE(mTimer, );
   }
   mTimer->InitWithNamedFuncCallback(FlushPendingMethods, this, 0,
                                     nsITimer::TYPE_ONE_SHOT,
                                     "IMEInputHandler::FlushPendingMethods");
 }
 
 void
--- a/widget/cocoa/nsMacDockSupport.mm
+++ b/widget/cocoa/nsMacDockSupport.mm
@@ -12,17 +12,17 @@
 NS_IMPL_ISUPPORTS(nsMacDockSupport, nsIMacDockSupport, nsITaskbarProgress)
 
 nsMacDockSupport::nsMacDockSupport()
 : mAppIcon(nil)
 , mProgressBackground(nil)
 , mProgressState(STATE_NO_PROGRESS)
 , mProgressFraction(0.0)
 {
-  mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+  mProgressTimer = NS_NewTimer();
 }
 
 nsMacDockSupport::~nsMacDockSupport()
 {
   if (mAppIcon) {
     [mAppIcon release];
     mAppIcon = nil;
   }
@@ -128,17 +128,17 @@ void nsMacDockSupport::RedrawIconCallbac
 // Return whether to draw progress
 bool nsMacDockSupport::InitProgress()
 {
   if (mProgressState != STATE_NORMAL && mProgressState != STATE_INDETERMINATE) {
     return false;
   }
 
   if (!mAppIcon) {
-    mProgressTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mProgressTimer = NS_NewTimer();
     mAppIcon = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
     mProgressBackground = [mAppIcon copyWithZone:nil];
     mTheme = new nsNativeThemeCocoa();
 
     NSSize sz = [mProgressBackground size];
     mProgressBounds = CGRectMake(sz.width * 1/32, sz.height * 3/32,
                                  sz.width * 30/32, sz.height * 4/32);
     [mProgressBackground lockFocus];
--- a/widget/gtk/nsWidgetFactory.cpp
+++ b/widget/gtk/nsWidgetFactory.cpp
@@ -45,16 +45,17 @@
 #include "nsPrintDialogGTK.h"
 
 #if defined(MOZ_X11)
 #include "nsIdleServiceGTK.h"
 #include "GfxInfoX11.h"
 #endif
 
 #include "nsNativeThemeGTK.h"
+#include "HeadlessThemeGTK.h"
 
 #include "nsIComponentRegistrar.h"
 #include "nsComponentManagerUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/widget/ScreenManager.h"
 #include <gtk/gtk.h>
 
 using namespace mozilla;
@@ -82,39 +83,37 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageTo
 
 // from nsWindow.cpp
 extern bool gDisableNativeTheme;
 
 static nsresult
 nsNativeThemeGTKConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult)
 {
-    if (gfxPlatform::IsHeadless()) {
-        return NS_ERROR_NO_INTERFACE;
-    }
     nsresult rv;
-    nsNativeThemeGTK * inst;
+    nsCOMPtr<nsITheme> inst;
 
     if (gDisableNativeTheme)
         return NS_ERROR_NO_INTERFACE;
 
     *aResult = nullptr;
     if (nullptr != aOuter) {
         rv = NS_ERROR_NO_AGGREGATION;
         return rv;
     }
-
-    inst = new nsNativeThemeGTK();
+    if (gfxPlatform::IsHeadless()) {
+        inst = new HeadlessThemeGTK();
+    } else {
+        inst = new nsNativeThemeGTK();
+    }
     if (nullptr == inst) {
         rv = NS_ERROR_OUT_OF_MEMORY;
         return rv;
     }
-    NS_ADDREF(inst);
     rv = inst->QueryInterface(aIID, aResult);
-    NS_RELEASE(inst);
 
     return rv;
 }
 
 #if defined(MOZ_X11)
 namespace mozilla {
 namespace widget {
 // This constructor should really be shared with all platforms.
--- a/widget/headless/HeadlessLookAndFeelGTK.cpp
+++ b/widget/headless/HeadlessLookAndFeelGTK.cpp
@@ -318,29 +318,24 @@ HeadlessLookAndFeel::GetFloatImpl(FloatI
   return res;
 }
 
 bool
 HeadlessLookAndFeel::GetFontImpl(FontID aID, nsString& aFontName,
                gfxFontStyle& aFontStyle,
                float aDevPixPerCSSPixel)
 {
-  // Copied over from the Cocoa equivalent to this file. Hopefully it's good
-  // enough here.
-  if (aID == eFont_Window || aID == eFont_Document) {
-      aFontStyle.style      = NS_FONT_STYLE_NORMAL;
-      aFontStyle.weight     = NS_FONT_WEIGHT_NORMAL;
-      aFontStyle.stretch    = NS_FONT_STRETCH_NORMAL;
-      aFontStyle.size       = 14 * aDevPixPerCSSPixel;
-      aFontStyle.systemFont = true;
+  // Default to san-serif for everything.
+  aFontStyle.style      = NS_FONT_STYLE_NORMAL;
+  aFontStyle.weight     = NS_FONT_WEIGHT_NORMAL;
+  aFontStyle.stretch    = NS_FONT_STRETCH_NORMAL;
+  aFontStyle.size       = 14 * aDevPixPerCSSPixel;
+  aFontStyle.systemFont = true;
 
-      aFontName.AssignLiteral("sans-serif");
-      return true;
-  }
-
+  aFontName.AssignLiteral("sans-serif");
   return true;
 }
 
 char16_t
 HeadlessLookAndFeel::GetPasswordCharacterImpl()
 {
   return UNICODE_BULLET;
 }
new file mode 100644
--- /dev/null
+++ b/widget/headless/HeadlessThemeGTK.cpp
@@ -0,0 +1,448 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "HeadlessThemeGTK.h"
+#include "nsThemeConstants.h"
+#include "nsIFrame.h"
+
+
+namespace mozilla {
+namespace widget {
+
+NS_IMPL_ISUPPORTS_INHERITED(HeadlessThemeGTK, nsNativeTheme, nsITheme)
+
+NS_IMETHODIMP
+HeadlessThemeGTK::DrawWidgetBackground(gfxContext* aContext,
+                                       nsIFrame* aFrame,
+                                       uint8_t aWidgetType,
+                                       const nsRect& aRect,
+                                       const nsRect& aDirtyRect)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HeadlessThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
+                                  uint8_t aWidgetType, nsIntMargin* aResult)
+{
+  aResult->top = aResult->right = aResult->bottom = aResult->left = 0;
+  // The following values are generated from the Ubuntu GTK theme.
+  switch (aWidgetType) {
+    case NS_THEME_BUTTON:
+    case NS_THEME_TOOLBARBUTTON:
+      aResult->top = 6;
+      aResult->right = 7;
+      aResult->bottom = 6;
+      aResult->left = 7;
+      break;
+    case NS_THEME_FOCUS_OUTLINE:
+    case NS_THEME_NUMBER_INPUT:
+    case NS_THEME_TEXTFIELD:
+      aResult->top = 5;
+      aResult->right = 7;
+      aResult->bottom = 5;
+      aResult->left = 7;
+      break;
+    case NS_THEME_STATUSBARPANEL:
+    case NS_THEME_RESIZERPANEL:
+    case NS_THEME_LISTBOX:
+    case NS_THEME_TREEVIEW:
+    case NS_THEME_TREEHEADERSORTARROW:
+    case NS_THEME_PROGRESSBAR:
+    case NS_THEME_PROGRESSBAR_VERTICAL:
+    case NS_THEME_SPINNER_UPBUTTON:
+    case NS_THEME_SPINNER_DOWNBUTTON:
+    case NS_THEME_SPINNER_TEXTFIELD:
+    case NS_THEME_TEXTFIELD_MULTILINE:
+    case NS_THEME_MENUPOPUP:
+    case NS_THEME_GTK_INFO_BAR:
+      aResult->top = 1;
+      aResult->right = 1;
+      aResult->bottom = 1;
+      aResult->left = 1;
+      break;
+    case NS_THEME_TREEHEADERCELL:
+      aResult->top = 5;
+      aResult->right = 7;
+      aResult->bottom = 6;
+      aResult->left = 6;
+      break;
+    case NS_THEME_TAB:
+      aResult->top = 4;
+      aResult->right = 7;
+      aResult->bottom = 2;
+      aResult->left = 7;
+      break;
+    case NS_THEME_TOOLTIP:
+      aResult->top = 6;
+      aResult->right = 6;
+      aResult->bottom = 6;
+      aResult->left = 6;
+      break;
+    case NS_THEME_MENULIST:
+      aResult->top = 6;
+      aResult->right = 22;
+      aResult->bottom = 6;
+      aResult->left = 7;
+      break;
+    case NS_THEME_MENULIST_BUTTON:
+      aResult->top = 1;
+      aResult->right = 1;
+      aResult->bottom = 1;
+      aResult->left = 0;
+      break;
+    case NS_THEME_MENULIST_TEXTFIELD:
+      aResult->top = 1;
+      aResult->right = 0;
+      aResult->bottom = 1;
+      aResult->left = 1;
+      break;
+    case NS_THEME_MENUITEM:
+    case NS_THEME_CHECKMENUITEM:
+    case NS_THEME_RADIOMENUITEM:
+      if (IsRegularMenuItem(aFrame)) {
+        break;
+      }
+      aResult->top = 3;
+      aResult->right = 5;
+      aResult->bottom = 3;
+      aResult->left = 5;
+      break;
+  }
+  return NS_OK;
+}
+
+bool
+HeadlessThemeGTK::GetWidgetPadding(nsDeviceContext* aContext,
+                                   nsIFrame* aFrame, uint8_t aWidgetType,
+                                   nsIntMargin* aResult)
+{
+  // The following values are generated from the Ubuntu GTK theme.
+  switch (aWidgetType) {
+    case NS_THEME_RADIO:
+    case NS_THEME_CHECKBOX:
+    case NS_THEME_TOOLBARBUTTON:
+    case NS_THEME_DUALBUTTON:
+    case NS_THEME_TOOLBARBUTTON_DROPDOWN:
+    case NS_THEME_BUTTON_ARROW_UP:
+    case NS_THEME_BUTTON_ARROW_DOWN:
+    case NS_THEME_BUTTON_ARROW_NEXT:
+    case NS_THEME_BUTTON_ARROW_PREVIOUS:
+    case NS_THEME_TAB_SCROLL_ARROW_BACK:
+    case NS_THEME_TAB_SCROLL_ARROW_FORWARD:
+    case NS_THEME_MENULIST_BUTTON:
+    case NS_THEME_RANGE_THUMB:
+    case NS_THEME_BUTTON_FOCUS:
+      aResult->top = 0;
+      aResult->right = 0;
+      aResult->bottom = 0;
+      aResult->left = 0;
+      return true;
+    case NS_THEME_MENUITEM:
+    case NS_THEME_CHECKMENUITEM:
+    case NS_THEME_RADIOMENUITEM:
+      if (!IsRegularMenuItem(aFrame)) {
+        return false;
+      }
+      aResult->top = 3;
+      aResult->right = 5;
+      aResult->bottom = 3;
+      aResult->left = 5;
+      return true;
+  }
+  return false;
+}
+
+
+NS_IMETHODIMP
+HeadlessThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
+                                       nsIFrame* aFrame, uint8_t aWidgetType,
+                                       LayoutDeviceIntSize* aResult,
+                                       bool* aIsOverridable)
+{
+  aResult->width = aResult->height = 0;
+  *aIsOverridable = true;
+
+  // The following values are generated from the Ubuntu GTK theme.
+  switch (aWidgetType) {
+    case NS_THEME_SPLITTER:
+      if (IsHorizontal(aFrame)) {
+        aResult->width = 6;
+        aResult->height = 0;
+      } else {
+        aResult->width = 0;
+        aResult->height = 6;
+      }
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_BUTTON:
+    case NS_THEME_TOOLBARBUTTON:
+      aResult->width = 14;
+      aResult->height = 12;
+      break;
+    case NS_THEME_RADIO:
+    case NS_THEME_CHECKBOX:
+      aResult->width = 18;
+      aResult->height = 18;
+      break;
+    case NS_THEME_TOOLBARBUTTON_DROPDOWN:
+    case NS_THEME_BUTTON_ARROW_UP:
+    case NS_THEME_BUTTON_ARROW_DOWN:
+    case NS_THEME_BUTTON_ARROW_NEXT:
+    case NS_THEME_BUTTON_ARROW_PREVIOUS:
+    case NS_THEME_RESIZER:
+      aResult->width = 15;
+      aResult->height = 15;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_SEPARATOR:
+      aResult->width = 12;
+      aResult->height = 0;
+      break;
+    case NS_THEME_TREETWISTY:
+    case NS_THEME_TREETWISTYOPEN:
+      aResult->width = 8;
+      aResult->height = 8;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_TREEHEADERCELL:
+      aResult->width = 13;
+      aResult->height = 11;
+      break;
+    case NS_THEME_TREEHEADERSORTARROW:
+    case NS_THEME_SPINNER_UPBUTTON:
+    case NS_THEME_SPINNER_DOWNBUTTON:
+      aResult->width = 14;
+      aResult->height = 13;
+      break;
+    case NS_THEME_TAB_SCROLL_ARROW_BACK:
+    case NS_THEME_TAB_SCROLL_ARROW_FORWARD:
+      aResult->width = 16;
+      aResult->height = 16;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_SPINNER:
+      aResult->width = 14;
+      aResult->height = 26;
+      break;
+    case NS_THEME_NUMBER_INPUT:
+    case NS_THEME_TEXTFIELD:
+      aResult->width = 0;
+      aResult->height = 12;
+      break;
+    case NS_THEME_SCROLLBAR_HORIZONTAL:
+      aResult->width = 31;
+      aResult->height = 10;
+      break;
+    case NS_THEME_SCROLLBAR_VERTICAL:
+      aResult->width = 10;
+      aResult->height = 31;
+      break;
+    case NS_THEME_SCROLLBARBUTTON_UP:
+    case NS_THEME_SCROLLBARBUTTON_DOWN:
+      aResult->width = 10;
+      aResult->height = 13;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_SCROLLBARBUTTON_LEFT:
+    case NS_THEME_SCROLLBARBUTTON_RIGHT:
+      aResult->width = 13;
+      aResult->height = 10;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_SCROLLBARTHUMB_HORIZONTAL:
+      aResult->width = 31;
+      aResult->height = 10;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_SCROLLBARTHUMB_VERTICAL:
+      aResult->width = 10;
+      aResult->height = 31;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_MENULIST:
+      aResult->width = 44;
+      aResult->height = 27;
+      break;
+    case NS_THEME_MENULIST_BUTTON:
+      aResult->width = 29;
+      aResult->height = 28;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_SCALETHUMB_HORIZONTAL:
+    case NS_THEME_RANGE_THUMB:
+      aResult->width = 14;
+      aResult->height = 18;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_SCALETHUMB_VERTICAL:
+      aResult->width = 18;
+      aResult->height = 13;
+      *aIsOverridable = false;
+      break;
+    case NS_THEME_RANGE:
+      aResult->width = 14;
+      aResult->height = 18;
+      break;
+    case NS_THEME_MENUSEPARATOR:
+      aResult->width = 0;
+      aResult->height = 8;
+      *aIsOverridable = false;
+      break;
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HeadlessThemeGTK::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
+                                     nsAtom* aAttribute, bool* aShouldRepaint,
+                                     const nsAttrValue* aOldValue)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HeadlessThemeGTK::ThemeChanged()
+{
+  return NS_OK;
+}
+
+static bool IsFrameContentNodeInNamespace(nsIFrame *aFrame, uint32_t aNamespace)
+{
+  nsIContent *content = aFrame ? aFrame->GetContent() : nullptr;
+  if (!content)
+    return false;
+  return content->IsInNamespace(aNamespace);
+}
+
+NS_IMETHODIMP_(bool)
+HeadlessThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
+                                      nsIFrame* aFrame,
+                                      uint8_t aWidgetType)
+{
+  switch (aWidgetType) {
+    case NS_THEME_BUTTON:
+    case NS_THEME_RADIO:
+    case NS_THEME_CHECKBOX:
+    case NS_THEME_FOCUS_OUTLINE:
+    case NS_THEME_TOOLBOX:
+    case NS_THEME_TOOLBAR:
+    case NS_THEME_TOOLBARBUTTON:
+    case NS_THEME_DUALBUTTON:
+    case NS_THEME_TOOLBARBUTTON_DROPDOWN:
+    case NS_THEME_BUTTON_ARROW_UP:
+    case NS_THEME_BUTTON_ARROW_DOWN:
+    case NS_THEME_BUTTON_ARROW_NEXT:
+    case NS_THEME_BUTTON_ARROW_PREVIOUS:
+    case NS_THEME_SEPARATOR:
+    case NS_THEME_TOOLBARGRIPPER:
+    case NS_THEME_SPLITTER:
+    case NS_THEME_STATUSBAR:
+    case NS_THEME_STATUSBARPANEL:
+    case NS_THEME_RESIZERPANEL:
+    case NS_THEME_RESIZER:
+    case NS_THEME_LISTBOX:
+    case NS_THEME_TREEVIEW:
+    case NS_THEME_TREETWISTY:
+    case NS_THEME_TREEHEADERCELL:
+    case NS_THEME_TREEHEADERSORTARROW:
+    case NS_THEME_TREETWISTYOPEN:
+    case NS_THEME_PROGRESSBAR:
+    case NS_THEME_PROGRESSCHUNK:
+    case NS_THEME_PROGRESSBAR_VERTICAL:
+    case NS_THEME_PROGRESSCHUNK_VERTICAL:
+    case NS_THEME_TAB:
+    case NS_THEME_TABPANELS:
+    case NS_THEME_TAB_SCROLL_ARROW_BACK:
+    case NS_THEME_TAB_SCROLL_ARROW_FORWARD:
+    case NS_THEME_TOOLTIP:
+    case NS_THEME_SPINNER:
+    case NS_THEME_SPINNER_UPBUTTON:
+    case NS_THEME_SPINNER_DOWNBUTTON:
+    case NS_THEME_SPINNER_TEXTFIELD:
+    case NS_THEME_NUMBER_INPUT:
+    case NS_THEME_SCROLLBAR_HORIZONTAL:
+    case NS_THEME_SCROLLBAR_VERTICAL:
+    case NS_THEME_SCROLLBARBUTTON_UP:
+    case NS_THEME_SCROLLBARBUTTON_DOWN:
+    case NS_THEME_SCROLLBARBUTTON_LEFT:
+    case NS_THEME_SCROLLBARBUTTON_RIGHT:
+    case NS_THEME_SCROLLBARTRACK_HORIZONTAL:
+    case NS_THEME_SCROLLBARTRACK_VERTICAL:
+    case NS_THEME_SCROLLBARTHUMB_HORIZONTAL:
+    case NS_THEME_SCROLLBARTHUMB_VERTICAL:
+    case NS_THEME_TEXTFIELD:
+    case NS_THEME_TEXTFIELD_MULTILINE:
+    case NS_THEME_MENULIST:
+    case NS_THEME_MENULIST_TEXT:
+    case NS_THEME_MENULIST_TEXTFIELD:
+    case NS_THEME_SCALE_HORIZONTAL:
+    case NS_THEME_SCALE_VERTICAL:
+    case NS_THEME_SCALETHUMB_HORIZONTAL:
+    case NS_THEME_SCALETHUMB_VERTICAL:
+    case NS_THEME_RANGE:
+    case NS_THEME_RANGE_THUMB:
+    case NS_THEME_CHECKBOX_CONTAINER:
+    case NS_THEME_RADIO_CONTAINER:
+    case NS_THEME_CHECKBOX_LABEL:
+    case NS_THEME_RADIO_LABEL:
+    case NS_THEME_BUTTON_FOCUS:
+    case NS_THEME_WINDOW:
+    case NS_THEME_DIALOG:
+    case NS_THEME_MENUBAR:
+    case NS_THEME_MENUPOPUP:
+    case NS_THEME_MENUITEM:
+    case NS_THEME_CHECKMENUITEM:
+    case NS_THEME_RADIOMENUITEM:
+    case NS_THEME_MENUSEPARATOR:
+    case NS_THEME_MENUARROW:
+    case NS_THEME_GTK_INFO_BAR:
+      return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
+    case NS_THEME_MENULIST_BUTTON:
+      return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) &&
+              !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
+  }
+  return false;
+}
+
+NS_IMETHODIMP_(bool)
+HeadlessThemeGTK::WidgetIsContainer(uint8_t aWidgetType)
+{
+    if (aWidgetType == NS_THEME_MENULIST_BUTTON ||
+        aWidgetType == NS_THEME_RADIO ||
+        aWidgetType == NS_THEME_RANGE_THUMB ||
+        aWidgetType == NS_THEME_CHECKBOX ||
+        aWidgetType == NS_THEME_TAB_SCROLL_ARROW_BACK ||
+        aWidgetType == NS_THEME_TAB_SCROLL_ARROW_FORWARD ||
+        aWidgetType == NS_THEME_BUTTON_ARROW_UP ||
+        aWidgetType == NS_THEME_BUTTON_ARROW_DOWN ||
+        aWidgetType == NS_THEME_BUTTON_ARROW_NEXT ||
+        aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS) {
+
+    return false;
+  }
+  return true;
+}
+
+bool
+HeadlessThemeGTK::ThemeDrawsFocusForWidget(uint8_t aWidgetType)
+{
+   if (aWidgetType == NS_THEME_MENULIST ||
+       aWidgetType == NS_THEME_BUTTON ||
+       aWidgetType == NS_THEME_TREEHEADERCELL) {
+    return true;
+  }
+  return false;
+}
+
+bool
+HeadlessThemeGTK::ThemeNeedsComboboxDropmarker()
+{
+  return false;
+}
+
+
+} // namespace widget
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/widget/headless/HeadlessThemeGTK.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_widget_HeadlessThemeGTK_h
+#define mozilla_widget_HeadlessThemeGTK_h
+
+#include "nsITheme.h"
+#include "nsNativeTheme.h"
+
+namespace mozilla {
+namespace widget {
+
+class HeadlessThemeGTK final : private nsNativeTheme,
+                               public nsITheme {
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  HeadlessThemeGTK() = default;
+  NS_IMETHOD DrawWidgetBackground(gfxContext* aContext,
+                                  nsIFrame* aFrame, uint8_t aWidgetType,
+                                  const nsRect& aRect,
+                                  const nsRect& aDirtyRect) override;
+
+  NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
+                             uint8_t aWidgetType,
+                             nsIntMargin* aResult) override;
+
+  virtual bool GetWidgetPadding(nsDeviceContext* aContext,
+                                nsIFrame* aFrame,
+                                uint8_t aWidgetType,
+                                nsIntMargin* aResult) override;
+  NS_IMETHOD GetMinimumWidgetSize(nsPresContext* aPresContext,
+                                  nsIFrame* aFrame, uint8_t aWidgetType,
+                                  mozilla::LayoutDeviceIntSize* aResult,
+                                  bool* aIsOverridable) override;
+
+  NS_IMETHOD WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
+                                nsAtom* aAttribute,
+                                bool* aShouldRepaint,
+                                const nsAttrValue* aOldValue) override;
+
+  NS_IMETHOD ThemeChanged() override;
+
+  NS_IMETHOD_(bool) ThemeSupportsWidget(nsPresContext* aPresContext,
+                                        nsIFrame* aFrame,
+                                        uint8_t aWidgetType) override;
+
+  NS_IMETHOD_(bool) WidgetIsContainer(uint8_t aWidgetType) override;
+
+  NS_IMETHOD_(bool) ThemeDrawsFocusForWidget(uint8_t aWidgetType) override;
+
+  virtual bool ThemeNeedsComboboxDropmarker() override;
+
+protected:
+  virtual ~HeadlessThemeGTK() { }
+};
+
+} // namespace widget
+} // namespace mozilla
+
+#endif // mozilla_widget_HeadlessThemeGTK_h
--- a/widget/headless/HeadlessWidget.cpp
+++ b/widget/headless/HeadlessWidget.cpp
@@ -2,21 +2,40 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "HeadlessWidget.h"
 #include "HeadlessCompositorWidget.h"
 #include "Layers.h"
 #include "BasicLayers.h"
 #include "BasicEvents.h"
+#include "MouseEvents.h"
 #include "mozilla/gfx/gfxVars.h"
+#include "mozilla/ClearOnShutdown.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
+using mozilla::LogLevel;
+
+#ifdef MOZ_LOGGING
+
+#include "mozilla/Logging.h"
+static mozilla::LazyLogModule sWidgetLog("Widget");
+static mozilla::LazyLogModule sWidgetFocusLog("WidgetFocus");
+#define LOG(args) MOZ_LOG(sWidgetLog, mozilla::LogLevel::Debug, args)
+#define LOGFOCUS(args) MOZ_LOG(sWidgetFocusLog, mozilla::LogLevel::Debug, args)
+
+#else
+
+#define LOG(args)
+#define LOGFOCUS(args)
+
+#endif /* MOZ_LOGGING */
+
 /*static*/ already_AddRefed<nsIWidget>
 nsIWidget::CreateHeadlessWidget()
 {
   nsCOMPtr<nsIWidget> widget = new mozilla::widget::HeadlessWidget();
   return widget.forget();
 }
 
 namespace mozilla {
@@ -30,33 +49,82 @@ CreateDefaultTarget(IntSize aSize)
   IntSize size = (aSize.width <= 0 || aSize.height <= 0) ? gfx::IntSize(1, 1) : aSize;
   RefPtr<DrawTarget> target = Factory::CreateDrawTarget(gfxVars::ContentBackend(), size, SurfaceFormat::B8G8R8A8);
   RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target);
   return ctx.forget();
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(HeadlessWidget, nsBaseWidget)
 
-HeadlessWidget* HeadlessWidget::sActiveWindow = nullptr;
+StaticAutoPtr<nsTArray<HeadlessWidget*>> HeadlessWidget::sActiveWindows;
+
+already_AddRefed<HeadlessWidget>
+HeadlessWidget::GetActiveWindow()
+{
+  if (!sActiveWindows) {
+    return nullptr;
+  }
+  auto length = sActiveWindows->Length();
+  if (length == 0) {
+    return nullptr;
+  }
+  RefPtr<HeadlessWidget> widget = sActiveWindows->ElementAt(length - 1);
+  return widget.forget();
+}
 
 HeadlessWidget::HeadlessWidget()
   : mEnabled(true)
   , mVisible(false)
+  , mDestroyed(false)
   , mTopLevel(nullptr)
   , mCompositorWidget(nullptr)
   , mLastSizeMode(nsSizeMode_Normal)
   , mEffectiveSizeMode(nsSizeMode_Normal)
   , mRestoreBounds(0,0,0,0)
 {
+  if (!sActiveWindows) {
+    sActiveWindows = new nsTArray<HeadlessWidget*>();
+    ClearOnShutdown(&sActiveWindows);
+  }
 }
 
 HeadlessWidget::~HeadlessWidget()
 {
-  if (sActiveWindow == this)
-    sActiveWindow = nullptr;
+  LOG(("HeadlessWidget::~HeadlessWidget() [%p]\n", (void *)this));
+
+  Destroy();
+}
+
+void
+HeadlessWidget::Destroy()
+{
+  if (mDestroyed) {
+    return;
+  }
+  LOG(("HeadlessWidget::Destroy [%p]\n", (void *)this));
+  mDestroyed = true;
+
+  if (sActiveWindows) {
+    int32_t index = sActiveWindows->IndexOf(this);
+    if (index != -1) {
+      RefPtr<HeadlessWidget> activeWindow = GetActiveWindow();
+      sActiveWindows->RemoveElementAt(index);
+      // If this is the currently active widget and there's a previously active
+      // widget, activate the previous widget.
+      RefPtr<HeadlessWidget> previousActiveWindow = GetActiveWindow();
+      if (this == activeWindow && previousActiveWindow &&
+          previousActiveWindow->mWidgetListener) {
+        previousActiveWindow->mWidgetListener->WindowActivated();
+      }
+    }
+  }
+
+  nsBaseWidget::OnDestroy();
+
+  nsBaseWidget::Destroy();
 }
 
 nsresult
 HeadlessWidget::Create(nsIWidget* aParent,
                        nsNativeWidget aNativeParent,
                        const LayoutDeviceIntRect& aRect,
                        nsWidgetInitData* aInitData)
 {
@@ -100,58 +168,73 @@ nsIWidget*
 HeadlessWidget::GetTopLevelWidget()
 {
   return mTopLevel;
 }
 
 void
 HeadlessWidget::RaiseWindow()
 {
-  MOZ_ASSERT(mTopLevel == this, "Raising a non-toplevel window.");
+  MOZ_ASSERT(mTopLevel == this || mWindowType == eWindowType_dialog, "Raising a non-toplevel window.");
 
-  if (sActiveWindow == this)
+  // Do nothing if this is the currently active window.
+  RefPtr<HeadlessWidget> activeWindow = GetActiveWindow();
+  if (activeWindow == this) {
     return;
+  }
 
   // Raise the window to the top of the stack.
   nsWindowZ placement = nsWindowZTop;
   nsCOMPtr<nsIWidget> actualBelow;
   if (mWidgetListener)
     mWidgetListener->ZLevelChanged(true, &placement, nullptr, getter_AddRefs(actualBelow));
 
   // Deactivate the last active window.
-  if (sActiveWindow && sActiveWindow->mWidgetListener)
-    sActiveWindow->mWidgetListener->WindowDeactivated();
+  if (activeWindow && activeWindow->mWidgetListener) {
+    activeWindow->mWidgetListener->WindowDeactivated();
+  }
+
+  // Remove this window if it's already tracked.
+  int32_t index = sActiveWindows->IndexOf(this);
+  if (index != -1) {
+    sActiveWindows->RemoveElementAt(index);
+  }
 
   // Activate this window.
-  sActiveWindow = this;
+  sActiveWindows->AppendElement(this);
   if (mWidgetListener)
     mWidgetListener->WindowActivated();
 }
 
 void
 HeadlessWidget::Show(bool aState)
 {
   mVisible = aState;
 
-  // Top-level windows are activated/raised when shown.
-  if (aState && mTopLevel == this)
+  LOG(("HeadlessWidget::Show [%p] state %d\n", (void *)this, aState));
+
+  // Top-level window and dialogs are activated/raised when shown.
+  if (aState && (mTopLevel == this || mWindowType == eWindowType_dialog)) {
     RaiseWindow();
+  }
 
   ApplySizeModeSideEffects();
 }
 
 bool
 HeadlessWidget::IsVisible() const
 {
   return mVisible;
 }
 
 nsresult
 HeadlessWidget::SetFocus(bool aRaise)
 {
+  LOGFOCUS(("  SetFocus %d [%p]\n", aRaise, (void *)this));
+
   // aRaise == true means we request activation of our toplevel window.
   if (aRaise) {
     HeadlessWidget* topLevel = (HeadlessWidget*) GetTopLevelWidget();
 
     // The toplevel only becomes active if it's currently visible; otherwise, it
     // will be activated anyway when it's shown.
     if (topLevel->IsVisible())
       topLevel->RaiseWindow();
@@ -169,16 +252,19 @@ bool
 HeadlessWidget::IsEnabled() const
 {
   return mEnabled;
 }
 
 void
 HeadlessWidget::Move(double aX, double aY)
 {
+  LOG(("HeadlessWidget::Move [%p] %f %f\n", (void *)this,
+       aX, aY));
+
   double scale = BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0;
   int32_t x = NSToIntRound(aX * scale);
   int32_t y = NSToIntRound(aY * scale);
 
   if (mWindowType == eWindowType_toplevel ||
       mWindowType == eWindowType_dialog) {
       SetSizeMode(nsSizeMode_Normal);
   }
@@ -254,16 +340,18 @@ HeadlessWidget::Resize(double aX,
     NotifyWindowMoved(aX, aY);
   }
   return Resize(aWidth, aHeight, aRepaint);
 }
 
 void
 HeadlessWidget::SetSizeMode(nsSizeMode aMode)
 {
+  LOG(("HeadlessWidget::SetSizeMode [%p] %d\n", (void *)this, aMode));
+
   if (aMode == mSizeMode) {
     return;
   }
 
   nsBaseWidget::SetSizeMode(aMode);
 
   // Normally in real widget backends a window event would be triggered that
   // would cause the window manager to handle resizing the window. In headless
@@ -349,10 +437,98 @@ HeadlessWidget::DispatchEvent(WidgetGUIE
     aStatus = mAttachedWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
   } else if (mWidgetListener) {
     aStatus = mWidgetListener->HandleEvent(aEvent, mUseAttachedEvents);
   }
 
   return NS_OK;
 }
 
+nsresult
+HeadlessWidget::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
+                                           uint32_t aNativeMessage,
+                                           uint32_t aModifierFlags,
+                                           nsIObserver* aObserver)
+{
+  AutoObserverNotifier notifier(aObserver, "mouseevent");
+  EventMessage msg;
+  switch (aNativeMessage) {
+    case MOZ_HEADLESS_MOUSE_MOVE:
+      msg = eMouseMove;
+      break;
+    case MOZ_HEADLESS_MOUSE_DOWN:
+      msg = eMouseDown;
+      break;
+    case MOZ_HEADLESS_MOUSE_UP:
+      msg = eMouseUp;
+      break;
+    default:
+      MOZ_ASSERT_UNREACHABLE("Unsupported synthesized mouse event");
+      return NS_ERROR_UNEXPECTED;
+  }
+  WidgetMouseEvent event(true, msg, this, WidgetMouseEvent::eReal);
+  event.mRefPoint = aPoint - WidgetToScreenOffset();
+  if (msg == eMouseDown || msg == eMouseUp) {
+    event.button = WidgetMouseEvent::eLeftButton;
+  }
+  if (msg == eMouseDown) {
+    event.mClickCount = 1;
+  }
+  event.AssignEventTime(WidgetEventTime());
+  DispatchInputEvent(&event);
+  return NS_OK;
+}
+
+nsresult
+HeadlessWidget::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPoint,
+                                                 uint32_t aNativeMessage,
+                                                 double aDeltaX,
+                                                 double aDeltaY,
+                                                 double aDeltaZ,
+                                                 uint32_t aModifierFlags,
+                                                 uint32_t aAdditionalFlags,
+                                                 nsIObserver* aObserver)
+{
+  AutoObserverNotifier notifier(aObserver, "mousescrollevent");
+  // The various platforms seem to handle scrolling deltas differently,
+  // but the following seems to emulate it well enough.
+  WidgetWheelEvent event(true, eWheel, this);
+  event.mDeltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
+  event.mIsNoLineOrPageDelta = true;
+  event.mDeltaX = -aDeltaX * MOZ_HEADLESS_SCROLL_MULTIPLIER;
+  event.mDeltaY = -aDeltaY * MOZ_HEADLESS_SCROLL_MULTIPLIER;
+  event.mDeltaZ = -aDeltaZ * MOZ_HEADLESS_SCROLL_MULTIPLIER;
+  event.mRefPoint = aPoint - WidgetToScreenOffset();
+  event.AssignEventTime(WidgetEventTime());
+  DispatchInputEvent(&event);
+  return NS_OK;
+}
+
+nsresult
+HeadlessWidget::SynthesizeNativeTouchPoint(uint32_t aPointerId,
+                                           TouchPointerState aPointerState,
+                                           LayoutDeviceIntPoint aPoint,
+                                           double aPointerPressure,
+                                           uint32_t aPointerOrientation,
+                                           nsIObserver* aObserver)
+{
+  AutoObserverNotifier notifier(aObserver, "touchpoint");
+
+  MOZ_ASSERT(NS_IsMainThread());
+  if (aPointerState == TOUCH_HOVER) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  if (!mSynthesizedTouchInput) {
+    mSynthesizedTouchInput = MakeUnique<MultiTouchInput>();
+  }
+
+  LayoutDeviceIntPoint pointInWindow = aPoint - WidgetToScreenOffset();
+  MultiTouchInput inputToDispatch = UpdateSynthesizedTouchState(
+      mSynthesizedTouchInput.get(), PR_IntervalNow(), TimeStamp::Now(),
+      aPointerId, aPointerState, pointInWindow, aPointerPressure,
+      aPointerOrientation);
+  DispatchTouchInput(inputToDispatch);
+  return NS_OK;
+}
+
 } // namespace widget
 } // namespace mozilla
--- a/widget/headless/HeadlessWidget.h
+++ b/widget/headless/HeadlessWidget.h
@@ -6,16 +6,45 @@
 
 #ifndef HEADLESSWIDGET_H
 #define HEADLESSWIDGET_H
 
 #include "mozilla/widget/InProcessCompositorWidget.h"
 #include "nsBaseWidget.h"
 #include "CompositorWidget.h"
 
+// The various synthesized event values are hardcoded to avoid pulling
+// in the platform specific widget code.
+#if defined(MOZ_WIDGET_GTK)
+#define MOZ_HEADLESS_MOUSE_MOVE 3 // GDK_MOTION_NOTIFY
+#define MOZ_HEADLESS_MOUSE_DOWN 4 // GDK_BUTTON_PRESS
+#define MOZ_HEADLESS_MOUSE_UP   7 // GDK_BUTTON_RELEASE
+#define MOZ_HEADLESS_SCROLL_MULTIPLIER 3
+#elif defined(XP_WIN)
+#define MOZ_HEADLESS_MOUSE_MOVE 1 // MOUSEEVENTF_MOVE
+#define MOZ_HEADLESS_MOUSE_DOWN 2 // MOUSEEVENTF_LEFTDOWN
+#define MOZ_HEADLESS_MOUSE_UP   4 // MOUSEEVENTF_LEFTUP
+#define MOZ_HEADLESS_SCROLL_MULTIPLIER 1
+#elif defined(XP_MACOSX)
+#define MOZ_HEADLESS_MOUSE_MOVE 5 // NSMouseMoved
+#define MOZ_HEADLESS_MOUSE_DOWN 1 // NSLeftMouseDown
+#define MOZ_HEADLESS_MOUSE_UP   2 // NSLeftMouseUp
+#define MOZ_HEADLESS_SCROLL_MULTIPLIER 1
+#elif defined(ANDROID)
+#define MOZ_HEADLESS_MOUSE_MOVE 7 // ACTION_HOVER_MOVE
+#define MOZ_HEADLESS_MOUSE_DOWN 5 // ACTION_POINTER_DOWN
+#define MOZ_HEADLESS_MOUSE_UP   6 // ACTION_POINTER_UP
+#define MOZ_HEADLESS_SCROLL_MULTIPLIER 1
+#else
+#define MOZ_HEADLESS_MOUSE_MOVE -1
+#define MOZ_HEADLESS_MOUSE_DOWN -1
+#define MOZ_HEADLESS_MOUSE_UP   -1
+#define MOZ_HEADLESS_SCROLL_MULTIPLIER = -1
+#endif
+
 namespace mozilla {
 namespace widget {
 
 class HeadlessWidget : public nsBaseWidget
 {
 public:
   HeadlessWidget();
 
@@ -35,16 +64,17 @@ public:
   virtual already_AddRefed<nsIWidget> CreateChild(const LayoutDeviceIntRect& aRect,
                                                   nsWidgetInitData* aInitData = nullptr,
                                                   bool aForceUseIWidgetParent = false) override;
 
   virtual nsIWidget* GetTopLevelWidget() override;
 
   virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override;
 
+  virtual void Destroy() override;
   virtual void Show(bool aState) override;
   virtual bool IsVisible() const override;
   virtual void Move(double aX, double aY) override;
   virtual void Resize(double aWidth,
                       double aHeight,
                       bool   aRepaint) override;
   virtual void Resize(double aX,
                       double aY,
@@ -86,33 +116,64 @@ public:
                   LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
                   LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT) override;
 
   void SetCompositorWidgetDelegate(CompositorWidgetDelegate* delegate) override;
 
   virtual nsresult DispatchEvent(WidgetGUIEvent* aEvent,
                                  nsEventStatus& aStatus) override;
 
+  virtual nsresult SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
+                                              uint32_t aNativeMessage,
+                                              uint32_t aModifierFlags,
+                                              nsIObserver* aObserver) override;
+  virtual nsresult SynthesizeNativeMouseMove(LayoutDeviceIntPoint aPoint,
+                                             nsIObserver* aObserver) override
+                   { return SynthesizeNativeMouseEvent(aPoint, MOZ_HEADLESS_MOUSE_MOVE, 0, aObserver); };
+
+  virtual nsresult SynthesizeNativeMouseScrollEvent(LayoutDeviceIntPoint aPoint,
+                                                    uint32_t aNativeMessage,
+                                                    double aDeltaX,
+                                                    double aDeltaY,
+                                                    double aDeltaZ,
+                                                    uint32_t aModifierFlags,
+                                                    uint32_t aAdditionalFlags,
+                                                    nsIObserver* aObserver) override;
+
+  virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
+                                              TouchPointerState aPointerState,
+                                              LayoutDeviceIntPoint aPoint,
+                                              double aPointerPressure,
+                                              uint32_t aPointerOrientation,
+                                              nsIObserver* aObserver) override;
+
 private:
   ~HeadlessWidget();
   bool mEnabled;
   bool mVisible;
+  bool mDestroyed;
   nsIWidget* mTopLevel;
   HeadlessCompositorWidget* mCompositorWidget;
   // The size mode before entering fullscreen mode.
   nsSizeMode mLastSizeMode;
   // The last size mode set while the window was visible.
   nsSizeMode mEffectiveSizeMode;
   InputContext mInputContext;
+  mozilla::UniquePtr<mozilla::MultiTouchInput> mSynthesizedTouchInput;
   // In headless there is no window manager to track window bounds
   // across size mode changes, so we must track it to emulate.
   LayoutDeviceIntRect mRestoreBounds;
   void ApplySizeModeSideEffects();
   // Similarly, we must track the active window ourselves in order
   // to dispatch (de)activation events properly.
   void RaiseWindow();
-  static HeadlessWidget* sActiveWindow;
+  // The top level widgets are tracked for window ordering. They are
+  // stored in order of activation where the last element is always the
+  // currently active widget.
+  static StaticAutoPtr<nsTArray<HeadlessWidget*>> sActiveWindows;
+  // Get the most recently activated widget or null if there are none.
+  static already_AddRefed<HeadlessWidget>GetActiveWindow();
 };
 
 } // namespace widget
 } // namespace mozilla
 
 #endif
--- a/widget/headless/moz.build
+++ b/widget/headless/moz.build
@@ -30,13 +30,14 @@ UNIFIED_SOURCES += [
     'HeadlessScreenHelper.cpp',
     'HeadlessSound.cpp',
     'HeadlessWidget.cpp',
 ]
 
 if widget_dir == 'gtk':
     UNIFIED_SOURCES += [
         'HeadlessLookAndFeelGTK.cpp',
+        'HeadlessThemeGTK.cpp',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -1987,18 +1987,18 @@ nsIWidget::SynthesizeNativeTouchTap(Layo
     return SynthesizeNativeTouchPoint(pointerId, TOUCH_REMOVE,
                                       aPoint, 0, 0, nullptr);
   }
 
   // initiate a long tap
   int elapse = Preferences::GetInt("ui.click_hold_context_menus.delay",
                                    TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC);
   if (!mLongTapTimer) {
-    mLongTapTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-    if (NS_FAILED(rv)) {
+    mLongTapTimer = NS_NewTimer();
+    if (!mLongTapTimer) {
       SynthesizeNativeTouchPoint(pointerId, TOUCH_CANCEL,
                                  aPoint, 0, 0, nullptr);
       return NS_ERROR_UNEXPECTED;
     }
     // Windows requires recuring events, so we set this to a smaller window
     // than the pref value.
     int timeout = elapse;
     if (timeout > TOUCH_INJECT_PUMP_TIMER_MSEC) {
--- a/widget/nsIdleService.cpp
+++ b/widget/nsIdleService.cpp
@@ -149,17 +149,17 @@ nsIdleServiceDaily::Observe(nsISupports 
                                           nsITimer::TYPE_ONE_SHOT,
                                           "nsIdleServiceDaily::Observe");
 
   return NS_OK;
 }
 
 nsIdleServiceDaily::nsIdleServiceDaily(nsIIdleService* aIdleService)
   : mIdleService(aIdleService)
-  , mTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
+  , mTimer(NS_NewTimer())
   , mCategoryObservers(OBSERVER_TOPIC_IDLE_DAILY)
   , mShutdownInProgress(false)
   , mExpectedTriggerTime(0)
   , mIdleDailyTriggerWait(DAILY_SIGNIFICANT_IDLE_SERVICE_SEC)
 {
 }
 
 void
@@ -446,19 +446,18 @@ nsIdleService::AddIdleObserver(nsIObserv
   IdleListener listener(aObserver, aIdleTimeInS);
 
   if (!mArrayListeners.AppendElement(listener)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   // Create our timer callback if it's not there already.
   if (!mTimer) {
-    nsresult rv;
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    mTimer = NS_NewTimer();
+    NS_ENSURE_TRUE(mTimer, NS_ERROR_OUT_OF_MEMORY);
   }
 
   // Check if the newly added observer has a smaller wait time than what we
   // are waiting for now.
   if (mDeltaToNextIdleSwitchInS > aIdleTimeInS) {
     // If it is, then this is the next to move to idle (at this point we
     // don't care if it should have switched already).
     MOZ_LOG(sLog, LogLevel::Debug,
--- a/widget/nsNativeTheme.cpp
+++ b/widget/nsNativeTheme.cpp
@@ -631,17 +631,17 @@ nsNativeTheme::QueueAnimatedContentForRe
   NS_ASSERTION(aMinimumFrameRate, "aMinimumFrameRate must be non-zero!");
   NS_ASSERTION(aMinimumFrameRate <= 1000,
                "aMinimumFrameRate must be less than 1000!");
 
   uint32_t timeout = 1000 / aMinimumFrameRate;
   timeout = std::min(mAnimatedContentTimeout, timeout);
 
   if (!mAnimatedContentTimer) {
-    mAnimatedContentTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mAnimatedContentTimer = NS_NewTimer();
     NS_ENSURE_TRUE(mAnimatedContentTimer, false);
   }
 
   if (mAnimatedContentList.IsEmpty() || timeout != mAnimatedContentTimeout) {
     nsresult rv;
     if (!mAnimatedContentList.IsEmpty()) {
       rv = mAnimatedContentTimer->Cancel();
       NS_ENSURE_SUCCESS(rv, false);
--- a/widget/nsNativeTheme.h
+++ b/widget/nsNativeTheme.h
@@ -1,16 +1,19 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // This defines a common base class for nsITheme implementations, to reduce
 // code duplication.
 
+#ifndef _NSNATIVETHEME_H_
+#define _NSNATIVETHEME_H_
+
 #include "nsAlgorithm.h"
 #include "nsAtom.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsMargin.h"
 #include "nsGkAtoms.h"
 #include "nsTArray.h"
 #include "nsINamed.h"
@@ -182,8 +185,10 @@ class nsNativeTheme : public nsITimerCal
   // scrollbar
   bool IsDarkBackground(nsIFrame* aFrame);
 
  private:
   uint32_t mAnimatedContentTimeout;
   nsCOMPtr<nsITimer> mAnimatedContentTimer;
   AutoTArray<nsCOMPtr<nsIContent>, 20> mAnimatedContentList;
 };
+
+#endif // _NSNATIVETHEME_H_
--- a/widget/windows/nsDataObj.cpp
+++ b/widget/windows/nsDataObj.cpp
@@ -450,21 +450,21 @@ public:
 
   // The attach method is seperate from the constructor as we may be addref-ing
   // ourself, and we want to be sure someone has a strong reference to us.
   void Attach()
   {
     // We need to listen to both the xpcom shutdown message and our timer, and
     // fire when the first of either of these two messages is received.
     nsresult rv;
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
+    rv = NS_NewTimerWithObserver(getter_AddRefs(mTimer),
+                                 this, 500, nsITimer::TYPE_ONE_SHOT);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
-    mTimer->Init(this, 500, nsITimer::TYPE_ONE_SHOT);
 
     nsCOMPtr<nsIObserverService> observerService =
       do_GetService("@mozilla.org/observer-service;1");
     if (NS_WARN_IF(!observerService)) {
       mTimer->Cancel();
       mTimer = nullptr;
       return;
     }
--- a/widget/windows/nsFilePicker.cpp
+++ b/widget/windows/nsFilePicker.cpp
@@ -154,26 +154,25 @@ public:
     }
   }
 
 private:
   void Init(nsFilePicker* aTarget,
             nsTimerCallbackFunc aCallbackFunc,
             const char* aName)
   {
-    mPickerCallbackTimer = do_CreateInstance("@mozilla.org/timer;1");
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mPickerCallbackTimer),
+                                aCallbackFunc,
+                                aTarget,
+                                kDialogTimerTimeout,
+                                nsITimer::TYPE_REPEATING_SLACK,
+                                aName);
     if (!mPickerCallbackTimer) {
       NS_WARNING("do_CreateInstance for timer failed??");
-      return;
     }
-    mPickerCallbackTimer->InitWithNamedFuncCallback(aCallbackFunc,
-                                                    aTarget,
-                                                    kDialogTimerTimeout,
-                                                    nsITimer::TYPE_REPEATING_SLACK,
-                                                    aName);
   }
   nsCOMPtr<nsITimer> mPickerCallbackTimer;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
 // nsIFilePicker
 
 nsFilePicker::nsFilePicker() :
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -1731,23 +1731,19 @@ nsMemoryReporterManager::StartGettingRep
 
   if (gfx::GPUProcessManager* gpu = gfx::GPUProcessManager::Get()) {
     if (RefPtr<MemoryReportingProcess> proc = gpu->GetProcessMemoryReporter()) {
       s->mChildrenPending.AppendElement(proc.forget());
     }
   }
 
   if (!s->mChildrenPending.IsEmpty()) {
-    nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    // Don't use NS_ENSURE_* here; can't return until the report is finished.
-    if (NS_WARN_IF(!timer)) {
-      FinishReporting();
-      return NS_ERROR_FAILURE;
-    }
-    rv = timer->InitWithNamedFuncCallback(
+    nsCOMPtr<nsITimer> timer;
+    rv = NS_NewTimerWithFuncCallback(
+      getter_AddRefs(timer),
       TimeoutCallback,
       this,
       kTimeoutLengthMS,
       nsITimer::TYPE_ONE_SHOT,
       "nsMemoryReporterManager::StartGettingReports");
     if (NS_WARN_IF(NS_FAILED(rv))) {
       FinishReporting();
       return rv;
--- a/xpcom/base/nsMessageLoop.cpp
+++ b/xpcom/base/nsMessageLoop.cpp
@@ -93,26 +93,21 @@ MessageLoopIdleTask::MessageLoopIdleTask
     mTask = nullptr;
     mTimer = nullptr;
   }
 }
 
 nsresult
 MessageLoopIdleTask::Init(uint32_t aEnsureRunsAfterMS)
 {
-  mTimer = do_CreateInstance("@mozilla.org/timer;1");
-  if (NS_WARN_IF(!mTimer)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
   RefPtr<MessageLoopTimerCallback> callback =
     new MessageLoopTimerCallback(this);
-
-  return mTimer->InitWithCallback(callback, aEnsureRunsAfterMS,
-                                  nsITimer::TYPE_ONE_SHOT);
+  return NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                                 callback, aEnsureRunsAfterMS,
+                                 nsITimer::TYPE_ONE_SHOT);
 }
 
 NS_IMETHODIMP
 MessageLoopIdleTask::Run()
 {
   // Null out our pointers because if Run() was called by the timer, this
   // object will be kept alive by the MessageLoop until the MessageLoop calls
   // Run().
--- a/xpcom/ds/nsExpirationTracker.h
+++ b/xpcom/ds/nsExpirationTracker.h
@@ -440,36 +440,32 @@ private:
     tracker->HandleTimeout();
   }
 
   nsresult CheckStartTimerLocked(const AutoLock& aAutoLock)
   {
     if (mTimer || !mTimerPeriod) {
       return NS_OK;
     }
-    mTimer = do_CreateInstance("@mozilla.org/timer;1");
-    if (!mTimer) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-    if (mEventTarget) {
-      mTimer->SetTarget(mEventTarget);
-    } else if (!NS_IsMainThread()) {
+    nsCOMPtr<nsIEventTarget> target = mEventTarget;
+    if (!target && !NS_IsMainThread()) {
       // TimerCallback should always be run on the main thread to prevent races
       // to the destruction of the tracker.
-      nsCOMPtr<nsIEventTarget> target = do_GetMainThread();
+      target = do_GetMainThread();
       NS_ENSURE_STATE(target);
-      mTimer->SetTarget(target);
     }
-    mTimer->InitWithNamedFuncCallback(
+
+    return NS_NewTimerWithFuncCallback(
+      getter_AddRefs(mTimer),
       TimerCallback,
       this,
       mTimerPeriod,
       nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
-      mName);
-    return NS_OK;
+      mName,
+      target);
   }
 };
 
 namespace detail {
 
 class PlaceholderLock {
 public:
   void Lock() {}
--- a/xpcom/io/nsAnonymousTemporaryFile.cpp
+++ b/xpcom/io/nsAnonymousTemporaryFile.cpp
@@ -12,16 +12,17 @@
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "prio.h"
 
 #ifdef XP_WIN
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
+#include "mozilla/ResultExtensions.h"
 #include "mozilla/Services.h"
 #include "nsIIdleService.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIFile.h"
 #include "nsAutoPtr.h"
 #include "nsITimer.h"
 #include "nsCRT.h"
 
@@ -169,26 +170,19 @@ public:
 
   nsresult Init()
   {
     // We add the idle observer in a timer, so that the app has enough
     // time to start up before we add the idle observer. If we register the
     // idle observer too early, it will be registered before the fake idle
     // service is installed when running in xpcshell, and this interferes with
     // the fake idle service, causing xpcshell-test failures.
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (NS_WARN_IF(!mTimer)) {
-      return NS_ERROR_FAILURE;
-    }
-    nsresult rv = mTimer->Init(this,
-                               SCHEDULE_TIMEOUT_MS,
-                               nsITimer::TYPE_ONE_SHOT);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
+    MOZ_TRY_VAR(mTimer, NS_NewTimerWithObserver(this,
+                                                SCHEDULE_TIMEOUT_MS,
+                                                nsITimer::TYPE_ONE_SHOT));
 
     // Register shutdown observer so we can cancel the timer if we shutdown before
     // the timer runs.
     nsCOMPtr<nsIObserverService> obsSrv = services::GetObserverService();
     if (NS_WARN_IF(!obsSrv)) {
       return NS_ERROR_FAILURE;
     }
     return obsSrv->AddObserver(this, XPCOM_SHUTDOWN_TOPIC, false);
--- a/xpcom/io/nsBinaryStream.cpp
+++ b/xpcom/io/nsBinaryStream.cpp
@@ -20,32 +20,53 @@
  */
 #include <algorithm>
 #include <string.h>
 
 #include "nsBinaryStream.h"
 
 #include "mozilla/EndianUtils.h"
 #include "mozilla/PodOperations.h"
+#include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsISerializable.h"
 #include "nsIClassInfo.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIURI.h" // for NS_IURI_IID
 #include "nsIX509Cert.h" // for NS_IX509CERT_IID
 
 #include "jsfriendapi.h"
 
 using mozilla::MakeUnique;
 using mozilla::PodCopy;
 using mozilla::UniquePtr;
 
+already_AddRefed<nsIObjectOutputStream>
+NS_NewObjectOutputStream(nsIOutputStream* aOutputStream)
+{
+  MOZ_ASSERT(aOutputStream);
+  auto stream = mozilla::MakeRefPtr<nsBinaryOutputStream>();
+
+  MOZ_ALWAYS_SUCCEEDS(stream->SetOutputStream(aOutputStream));
+  return stream.forget();
+}
+
+already_AddRefed<nsIObjectInputStream>
+NS_NewObjectInputStream(nsIInputStream* aInputStream)
+{
+  MOZ_ASSERT(aInputStream);
+  auto stream = mozilla::MakeRefPtr<nsBinaryInputStream>();
+
+  MOZ_ALWAYS_SUCCEEDS(stream->SetInputStream(aInputStream));
+  return stream.forget();
+}
+
 NS_IMPL_ISUPPORTS(nsBinaryOutputStream,
                   nsIObjectOutputStream,
                   nsIBinaryOutputStream,
                   nsIOutputStream)
 
 NS_IMETHODIMP
 nsBinaryOutputStream::Flush()
 {
--- a/xpcom/io/nsBinaryStream.h
+++ b/xpcom/io/nsBinaryStream.h
@@ -28,16 +28,18 @@
 class nsBinaryOutputStream final : public nsIObjectOutputStream
 {
 public:
   nsBinaryOutputStream()
   {
   }
 
 protected:
+  friend already_AddRefed<nsIObjectOutputStream> NS_NewObjectOutputStream(nsIOutputStream*);
+
   // nsISupports methods
   NS_DECL_ISUPPORTS
 
   // nsIOutputStream methods
   NS_DECL_NSIOUTPUTSTREAM
 
   // nsIBinaryOutputStream methods
   NS_DECL_NSIBINARYOUTPUTSTREAM
@@ -71,16 +73,18 @@ private:
 class nsBinaryInputStream final : public nsIObjectInputStream
 {
 public:
   nsBinaryInputStream()
   {
   }
 
 protected:
+  friend already_AddRefed<nsIObjectInputStream> NS_NewObjectInputStream(nsIInputStream*);
+
   // nsISupports methods
   NS_DECL_ISUPPORTS
 
   // nsIInputStream methods
   NS_DECL_NSIINPUTSTREAM
 
   // nsIBinaryInputStream methods
   NS_DECL_NSIBINARYINPUTSTREAM
--- a/xpcom/io/nsIObjectInputStream.idl
+++ b/xpcom/io/nsIObjectInputStream.idl
@@ -30,16 +30,19 @@ interface nsIObjectInputStream : nsIBina
      * Optimized deserialization support -- see nsIStreamBufferAccess.idl.
      */
     [notxpcom] charPtr getBuffer(in uint32_t aLength, in uint32_t aAlignMask);
     [notxpcom] void    putBuffer(in charPtr aBuffer, in uint32_t aLength);
 };
 
 %{C++
 
+already_AddRefed<nsIObjectInputStream>
+NS_NewObjectInputStream(nsIInputStream* aOutputStream);
+
 inline nsresult
 NS_ReadOptionalObject(nsIObjectInputStream* aStream, bool aIsStrongRef,
                       nsISupports* *aResult)
 {
     bool nonnull;
     nsresult rv = aStream->ReadBoolean(&nonnull);
     if (NS_SUCCEEDED(rv)) {
         if (nonnull)
--- a/xpcom/io/nsIObjectOutputStream.idl
+++ b/xpcom/io/nsIObjectOutputStream.idl
@@ -53,16 +53,18 @@ interface nsIObjectOutputStream : nsIBin
     /**
      * Optimized serialization support -- see nsIStreamBufferAccess.idl.
      */
     [notxpcom] charPtr getBuffer(in uint32_t aLength, in uint32_t aAlignMask);
     [notxpcom] void    putBuffer(in charPtr aBuffer, in uint32_t aLength);
 };
 
 %{C++
+already_AddRefed<nsIObjectOutputStream>
+NS_NewObjectOutputStream(nsIOutputStream* aOutputStream);
 
 inline nsresult
 NS_WriteOptionalObject(nsIObjectOutputStream* aStream, nsISupports* aObject,
                        bool aIsStrongRef)
 {
     bool nonnull = (aObject != nullptr);
     nsresult rv = aStream->WriteBoolean(nonnull);
     if (NS_SUCCEEDED(rv) && nonnull)
--- a/xpcom/tests/gtest/TestThreadUtils.cpp
+++ b/xpcom/tests/gtest/TestThreadUtils.cpp
@@ -586,19 +586,19 @@ public:
     mSetIdleDeadlineCalled = false;
     NS_DispatchToCurrentThread(NewRunnableMethod("IdleObject::Method3", this, &IdleObject::Method3));
   }
 
   void Method3()
   {
     CheckExecutedMethods("Method3", 3);
 
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    mTimer->InitWithNamedFuncCallback(
-      Method4, this, 10, nsITimer::TYPE_ONE_SHOT, "IdleObject::Method3");
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+                                Method4, this, 10, nsITimer::TYPE_ONE_SHOT,
+                                "IdleObject::Method3");
     NS_IdleDispatchToCurrentThread(
       NewIdleRunnableMethodWithTimer("IdleObject::Method5", this, &IdleObject::Method5), 50);
     NS_IdleDispatchToCurrentThread(
       NewRunnableMethod("IdleObject::Method6", this, &IdleObject::Method6),
       100);
 
     PR_Sleep(PR_MillisecondsToInterval(200));
     mRunnableExecuted[3] = true;
--- a/xpcom/tests/gtest/TestTimers.cpp
+++ b/xpcom/tests/gtest/TestTimers.cpp
@@ -107,61 +107,53 @@ NS_IMPL_ISUPPORTS(TimerCallback, nsITime
 TEST(Timers, TargetedTimers)
 {
   AutoCreateAndDestroyReentrantMonitor newMon;
   ASSERT_TRUE(newMon);
 
   AutoTestThread testThread;
   ASSERT_TRUE(testThread);
 
-  nsresult rv;
-  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  ASSERT_TRUE(NS_SUCCEEDED(rv));
-
-  nsIEventTarget* target = static_cast<nsIEventTarget*>(testThread);
-
-  rv = timer->SetTarget(target);
-  ASSERT_TRUE(NS_SUCCEEDED(rv));
-
   nsIThread* notifiedThread = nullptr;
 
   nsCOMPtr<nsITimerCallback> callback =
     new TimerCallback(&notifiedThread, newMon);
   ASSERT_TRUE(callback);
 
-  rv = timer->InitWithCallback(callback, 2000, nsITimer::TYPE_ONE_SHOT);
+  nsIEventTarget* target = static_cast<nsIEventTarget*>(testThread);
+
+  nsCOMPtr<nsITimer> timer;
+  nsresult rv = NS_NewTimerWithCallback(getter_AddRefs(timer),
+                                        callback, 2000, nsITimer::TYPE_ONE_SHOT,
+                                        target);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   ReentrantMonitorAutoEnter mon(*newMon);
   while (!notifiedThread) {
     mon.Wait();
   }
   ASSERT_EQ(notifiedThread, testThread);
 }
 
 TEST(Timers, TimerWithStoppedTarget)
 {
   AutoTestThread testThread;
   ASSERT_TRUE(testThread);
 
-  nsresult rv;
-  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  ASSERT_TRUE(NS_SUCCEEDED(rv));
-
   nsIEventTarget* target = static_cast<nsIEventTarget*>(testThread);
 
-  rv = timer->SetTarget(target);
-  ASSERT_TRUE(NS_SUCCEEDED(rv));
-
   // If this is called, we'll assert
   nsCOMPtr<nsITimerCallback> callback =
     new TimerCallback(nullptr, nullptr);
   ASSERT_TRUE(callback);
 
-  rv = timer->InitWithCallback(callback, 100, nsITimer::TYPE_ONE_SHOT);
+  nsCOMPtr<nsITimer> timer;
+  nsresult rv = NS_NewTimerWithCallback(getter_AddRefs(timer),
+                                        callback, 100, nsITimer::TYPE_ONE_SHOT,
+                                        target);
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   testThread->Shutdown();
 
   PR_Sleep(400);
 }
 
 // gtest on 32bit Win7 debug build is unstable and somehow this test
@@ -224,23 +216,22 @@ public:
       // Clear whatever random timers there might be pending.
       uint32_t waitTime = 10;
       if (t > TimeStamp::Now()) {
         waitTime = uint32_t((t - TimeStamp::Now()).ToMilliseconds());
       }
       PR_Sleep(PR_MillisecondsToInterval(waitTime));
     } while(true);
 
-    nsresult rv;
     mBefore = TimeStamp::Now();
     mMiddle = mBefore + TimeDuration::FromMilliseconds(
         kTimerOffset + kTimerInterval * kNumTimers / 2);
     for (uint32_t i = 0; i < kNumTimers; ++i) {
-      nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-      ASSERT_TRUE(NS_SUCCEEDED(rv));
+      nsCOMPtr<nsITimer> timer = NS_NewTimer();
+      ASSERT_TRUE(timer);
 
       if (i < aNumDifferingTimers) {
         if (aTarget) {
           timer->SetTarget(aTarget);
         }
 
         timer->InitWithNamedFuncCallback(&UnusedCallbackFunc,
                                          nullptr,
@@ -559,22 +550,18 @@ class FuzzTestThreadState final : public
       // Reschedule some timers without a Cancel first.
       for (size_t i = 0; i < kNumRescheduled; ++i) {
         InitRandomTimer(RemoveRandomTimer().get());
       }
     }
 
     void CreateRandomTimer()
     {
-      nsresult rv;
-      nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-      MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv), "Failed to create timer.");
-
-      rv = timer->SetTarget(static_cast<nsIEventTarget*>(mThread.get()));
-      MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv), "Failed to set target.");
+      nsCOMPtr<nsITimer> timer = NS_NewTimer(static_cast<nsIEventTarget*>(mThread.get()));
+      MOZ_RELEASE_ASSERT(timer, "Failed to create timer.");
 
       InitRandomTimer(timer.get());
     }
 
     nsCOMPtr<nsITimer> CancelRandomTimer()
     {
       nsCOMPtr<nsITimer> timer(RemoveRandomTimer());
       timer->Cancel();
--- a/xpcom/threads/IdleTaskRunner.cpp
+++ b/xpcom/threads/IdleTaskRunner.cpp
@@ -140,17 +140,17 @@ IdleTaskRunner::Schedule(bool aAllowIdle
   } else {
     // RefreshDriver doesn't seem to be running.
     if (aAllowIdleDispatch) {
       nsCOMPtr<nsIRunnable> runnable = this;
       SetTimerInternal(mDelay);
       NS_IdleDispatchToCurrentThread(runnable.forget());
     } else {
       if (!mScheduleTimer) {
-        mScheduleTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+        mScheduleTimer = NS_NewTimer();
         if (!mScheduleTimer) {
           return;
         }
       } else {
         mScheduleTimer->Cancel();
       }
       if (TaskCategory::Count != mTaskCategory) {
         mScheduleTimer->SetTarget(SystemGroup::EventTargetFor(mTaskCategory));
@@ -185,17 +185,17 @@ IdleTaskRunner::CancelTimer()
 void
 IdleTaskRunner::SetTimerInternal(uint32_t aDelay)
 {
   if (mTimerActive) {
     return;
   }
 
   if (!mTimer) {
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    mTimer = NS_NewTimer();
   } else {
     mTimer->Cancel();
   }
 
   if (mTimer) {
     if (TaskCategory::Count != mTaskCategory) {
       mTimer->SetTarget(SystemGroup::EventTargetFor(mTaskCategory));
     }
--- a/xpcom/threads/LazyIdleThread.cpp
+++ b/xpcom/threads/LazyIdleThread.cpp
@@ -148,17 +148,17 @@ LazyIdleThread::EnsureThread()
     }
 
     rv = obs->AddObserver(this, "xpcom-shutdown-threads", false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
-  mIdleTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
+  mIdleTimer = NS_NewTimer();
   if (NS_WARN_IF(!mIdleTimer)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsCOMPtr<nsIRunnable> runnable = NewRunnableMethod(
     "LazyIdleThread::InitThread", this, &LazyIdleThread::InitThread);
   if (NS_WARN_IF(!runnable)) {
     return NS_ERROR_UNEXPECTED;
--- a/xpcom/threads/ThreadEventTarget.cpp
+++ b/xpcom/threads/ThreadEventTarget.cpp
@@ -37,25 +37,19 @@ public:
     , mDelayedFrom(TimeStamp::NowLoRes())
     , mDelay(aDelay)
   { }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   nsresult Init()
   {
-    nsresult rv;
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    MOZ_ASSERT(mTimer);
-    rv = mTimer->SetTarget(mTarget);
-
-    NS_ENSURE_SUCCESS(rv, rv);
-    return mTimer->InitWithCallback(this, mDelay, nsITimer::TYPE_ONE_SHOT);
+    return NS_NewTimerWithCallback(getter_AddRefs(mTimer),
+                                   this, mDelay, nsITimer::TYPE_ONE_SHOT,
+                                   mTarget);
   }
 
   nsresult DoRun()
   {
     nsCOMPtr<nsIRunnable> r = mWrappedRunnable.forget();
     return r->Run();
   }
 
--- a/xpcom/threads/nsITimer.idl
+++ b/xpcom/threads/nsITimer.idl
@@ -257,11 +257,85 @@ interface nsITimer : nsISupports
   [noscript] readonly attribute unsigned long allowedEarlyFiringMicroseconds;
 
 %{C++
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const = 0;
 %}
 };
 
 %{C++
+#include "nsCOMPtr.h"
+
+already_AddRefed<nsITimer> NS_NewTimer();
+
+already_AddRefed<nsITimer> NS_NewTimer(nsIEventTarget* aTarget);
+
+nsresult
+NS_NewTimerWithObserver(nsITimer** aTimer,
+                        nsIObserver* aObserver,
+                        uint32_t aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget = nullptr);
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithObserver(nsIObserver* aObserver,
+                        uint32_t aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget = nullptr);
+
+nsresult
+NS_NewTimerWithCallback(nsITimer** aTimer,
+                        nsITimerCallback* aCallback,
+                        uint32_t aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget = nullptr);
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithCallback(nsITimerCallback* aCallback,
+                        uint32_t aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget = nullptr);
+
+nsresult
+NS_NewTimerWithCallback(nsITimer** aTimer,
+                        nsITimerCallback* aCallback,
+                        const mozilla::TimeDuration& aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget = nullptr);
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithCallback(nsITimerCallback* aCallback,
+                        const mozilla::TimeDuration& aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget = nullptr);
+
+nsresult
+NS_NewTimerWithFuncCallback(nsITimer** aTimer,
+                            nsTimerCallbackFunc aCallback,
+                            void* aClosure,
+                            uint32_t aDelay,
+                            uint32_t aType,
+                            const char* aNameString,
+                            nsIEventTarget* aTarget = nullptr);
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithFuncCallback(nsTimerCallbackFunc aCallback,
+                            void* aClosure,
+                            uint32_t aDelay,
+                            uint32_t aType,
+                            const char* aNameString,
+                            nsIEventTarget* aTarget = nullptr);
+
+nsresult
+NS_NewTimerWithFuncCallback(nsITimer** aTimer,
+                            nsTimerCallbackFunc aCallback,
+                            void* aClosure,
+                            uint32_t aDelay,
+                            uint32_t aType,
+                            nsTimerNameCallbackFunc aNameCallback,
+                            nsIEventTarget* aTarget = nullptr);
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithFuncCallback(nsTimerCallbackFunc aCallback,
+                            void* aClosure,
+                            uint32_t aDelay,
+                            uint32_t aType,
+                            nsTimerNameCallbackFunc aNameCallback,
+                            nsIEventTarget* aTarget = nullptr);
+
 #define NS_TIMER_CONTRACTID "@mozilla.org/timer;1"
 #define NS_TIMER_CALLBACK_TOPIC "timer-callback"
 %}
--- a/xpcom/threads/nsThreadUtils.cpp
+++ b/xpcom/threads/nsThreadUtils.cpp
@@ -76,26 +76,16 @@ CancelableRunnable::Cancel()
 {
   // Do nothing
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(IdleRunnable, CancelableRunnable,
                             nsIIdleRunnable)
 
-namespace mozilla {
-namespace detail {
-already_AddRefed<nsITimer> CreateTimer()
-{
-  nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
-  return timer.forget();
-}
-} // namespace detail
-} // namespace mozilla
-
 NS_IMPL_ISUPPORTS_INHERITED(PrioritizableRunnable, Runnable,
                             nsIRunnablePriority)
 
 PrioritizableRunnable::PrioritizableRunnable(already_AddRefed<nsIRunnable>&& aRunnable,
                                              uint32_t aPriority)
  // Real runnable name is managed by overridding the GetName function.
  : Runnable("PrioritizableRunnable")
  , mRunnable(Move(aRunnable))
@@ -355,25 +345,23 @@ public:
       static_cast<IdleRunnableWrapper*>(aClosure);
     runnable->Run();
   }
 
   void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) override
   {
     MOZ_ASSERT(aTarget);
     MOZ_ASSERT(!mTimer);
-    mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
-    if (mTimer) {
-      mTimer->SetTarget(aTarget);
-      mTimer->InitWithNamedFuncCallback(TimedOut,
-                                        this,
-                                        aDelay,
-                                        nsITimer::TYPE_ONE_SHOT,
-                                        "IdleRunnableWrapper::SetTimer");
-    }
+    NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+                                TimedOut,
+                                this,
+                                aDelay,
+                                nsITimer::TYPE_ONE_SHOT,
+                                "IdleRunnableWrapper::SetTimer",
+                                aTarget);
   }
 
   NS_IMETHOD GetName(nsACString& aName) override
   {
     aName.AssignLiteral("IdleRunnableWrapper");
     if (nsCOMPtr<nsINamed> named = do_QueryInterface(mRunnable)) {
       nsAutoCString name;
       named->GetName(name);
--- a/xpcom/threads/nsThreadUtils.h
+++ b/xpcom/threads/nsThreadUtils.h
@@ -635,18 +635,16 @@ NS_NewRunnableFunction(const char* aName
   return do_AddRef(
     new mozilla::detail::RunnableFunctionImpl<Function>(
       aName, mozilla::Forward<Function>(aFunction)));
 }
 
 namespace mozilla {
 namespace detail {
 
-already_AddRefed<nsITimer> CreateTimer();
-
 template <RunnableKind Kind>
 class TimerBehaviour
 {
 public:
   nsITimer* GetTimer() { return nullptr; }
   void CancelTimer() {}
 
 protected:
@@ -655,17 +653,17 @@ protected:
 
 template <>
 class TimerBehaviour<IdleWithTimer>
 {
 public:
   nsITimer* GetTimer()
   {
     if (!mTimer) {
-      mTimer = CreateTimer();
+      mTimer = NS_NewTimer();
     }
 
     return mTimer;
   }
 
   void CancelTimer()
   {
     if (mTimer) {
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -11,32 +11,34 @@
 #include "nsThreadUtils.h"
 #include "pratom.h"
 #include "GeckoProfiler.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Move.h"
 #include "mozilla/Mutex.h"
+#include "mozilla/ResultExtensions.h"
 #ifdef MOZ_TASK_TRACER
 #include "GeckoTaskTracerImpl.h"
 using namespace mozilla::tasktracer;
 #endif
 
 #ifdef XP_WIN
 #include <process.h>
 #ifndef getpid
 #define getpid _getpid
 #endif
 #else
 #include <unistd.h>
 #endif
 
 using mozilla::Atomic;
 using mozilla::LogLevel;
+using mozilla::MakeRefPtr;
 using mozilla::Move;
 using mozilla::MutexAutoLock;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 
 static TimerThread*     gThread = nullptr;
 
 // This module prints info about the precision of timers.
@@ -51,16 +53,203 @@ GetTimerLog()
 TimeStamp
 NS_GetTimerDeadlineHintOnCurrentThread(TimeStamp aDefault, uint32_t aSearchBound)
 {
   return gThread
            ? gThread->FindNextFireTimeForCurrentThread(aDefault, aSearchBound)
            : TimeStamp();
 }
 
+already_AddRefed<nsITimer>
+NS_NewTimer()
+{
+  return do_AddRef(new nsTimer());
+}
+
+already_AddRefed<nsITimer>
+NS_NewTimer(nsIEventTarget* aTarget)
+{
+  auto timer = MakeRefPtr<nsTimer>();
+  if (aTarget && MOZ_LIKELY(timer)) {
+    MOZ_ALWAYS_SUCCEEDS(timer->SetTarget(aTarget));
+  }
+  return timer.forget();
+}
+
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithObserver(nsIObserver* aObserver,
+                        uint32_t aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget)
+{
+  nsCOMPtr<nsITimer> timer;
+  MOZ_TRY(NS_NewTimerWithObserver(getter_AddRefs(timer),
+                                  aObserver,
+                                  aDelay,
+                                  aType,
+                                  aTarget));
+  return Move(timer);
+}
+nsresult
+NS_NewTimerWithObserver(nsITimer** aTimer,
+                        nsIObserver* aObserver,
+                        uint32_t aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget)
+{
+  auto timer = MakeRefPtr<nsTimer>();
+  if (aTarget) {
+    MOZ_ALWAYS_SUCCEEDS(timer->SetTarget(aTarget));
+  }
+
+  MOZ_TRY(timer->Init(aObserver, aDelay, aType));
+  timer.forget(aTimer);
+  return NS_OK;
+}
+
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithCallback(nsITimerCallback* aCallback,
+                        uint32_t aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget)
+{
+  nsCOMPtr<nsITimer> timer;
+  MOZ_TRY(NS_NewTimerWithCallback(getter_AddRefs(timer),
+                                  aCallback,
+                                  aDelay,
+                                  aType,
+                                  aTarget));
+  return Move(timer);
+}
+nsresult
+NS_NewTimerWithCallback(nsITimer** aTimer,
+                        nsITimerCallback* aCallback,
+                        uint32_t aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget)
+{
+  auto timer = MakeRefPtr<nsTimer>();
+  if (aTarget) {
+    MOZ_ALWAYS_SUCCEEDS(timer->SetTarget(aTarget));
+  }
+
+  MOZ_TRY(timer->InitWithCallback(aCallback, aDelay, aType));
+  timer.forget(aTimer);
+  return NS_OK;
+}
+
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithCallback(nsITimerCallback* aCallback,
+                        const TimeDuration& aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget)
+{
+  nsCOMPtr<nsITimer> timer;
+  MOZ_TRY(NS_NewTimerWithCallback(getter_AddRefs(timer),
+                                  aCallback,
+                                  aDelay,
+                                  aType,
+                                  aTarget));
+  return Move(timer);
+}
+nsresult
+NS_NewTimerWithCallback(nsITimer** aTimer,
+                        nsITimerCallback* aCallback,
+                        const TimeDuration& aDelay,
+                        uint32_t aType,
+                        nsIEventTarget* aTarget)
+{
+  auto timer = MakeRefPtr<nsTimer>();
+  if (aTarget) {
+    MOZ_ALWAYS_SUCCEEDS(timer->SetTarget(aTarget));
+  }
+
+  MOZ_TRY(timer->InitHighResolutionWithCallback(aCallback, aDelay, aType));
+  timer.forget(aTimer);
+  return NS_OK;
+}
+
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithFuncCallback(nsTimerCallbackFunc aCallback,
+                            void* aClosure,
+                            uint32_t aDelay,
+                            uint32_t aType,
+                            const char* aNameString,
+                            nsIEventTarget* aTarget)
+{
+  nsCOMPtr<nsITimer> timer;
+  MOZ_TRY(NS_NewTimerWithFuncCallback(getter_AddRefs(timer),
+                                      aCallback,
+                                      aClosure,
+                                      aDelay,
+                                      aType,
+                                      aNameString,
+                                      aTarget));
+  return Move(timer);
+}
+nsresult
+NS_NewTimerWithFuncCallback(nsITimer** aTimer,
+                            nsTimerCallbackFunc aCallback,
+                            void* aClosure,
+                            uint32_t aDelay,
+                            uint32_t aType,
+                            const char* aNameString,
+                            nsIEventTarget* aTarget)
+{
+  auto timer = MakeRefPtr<nsTimer>();
+  if (aTarget) {
+    MOZ_ALWAYS_SUCCEEDS(timer->SetTarget(aTarget));
+  }
+
+  MOZ_TRY(timer->InitWithNamedFuncCallback(aCallback, aClosure,
+                                           aDelay, aType,
+                                           aNameString));
+  timer.forget(aTimer);
+  return NS_OK;
+}
+
+mozilla::Result<nsCOMPtr<nsITimer>, nsresult>
+NS_NewTimerWithFuncCallback(nsTimerCallbackFunc aCallback,
+            void* aClosure,
+            uint32_t aDelay,
+            uint32_t aType,
+            nsTimerNameCallbackFunc aNameCallback,
+            nsIEventTarget* aTarget)
+{
+  nsCOMPtr<nsITimer> timer;
+  MOZ_TRY(NS_NewTimerWithFuncCallback(getter_AddRefs(timer),
+                                      aCallback,
+                                      aClosure,
+                                      aDelay,
+                                      aType,
+                                      aNameCallback,
+                                      aTarget));
+  return Move(timer);
+}
+nsresult
+NS_NewTimerWithFuncCallback(nsITimer** aTimer,
+                            nsTimerCallbackFunc aCallback,
+                            void* aClosure,
+                            uint32_t aDelay,
+                            uint32_t aType,
+                            nsTimerNameCallbackFunc aNameCallback,
+                            nsIEventTarget* aTarget)
+{
+  auto timer = MakeRefPtr<nsTimer>();
+  if (aTarget) {
+    MOZ_ALWAYS_SUCCEEDS(timer->SetTarget(aTarget));
+  }
+
+  MOZ_TRY(timer->InitWithNameableFuncCallback(aCallback, aClosure,
+                                              aDelay, aType,
+                                              aNameCallback));
+  timer.forget(aTimer);
+  return NS_OK;
+}
+
 // This module prints info about which timers are firing, which is useful for
 // wakeups for the purposes of power profiling. Set the following environment
 // variable before starting the browser.
 //
 //   MOZ_LOG=TimerFirings:4
 //
 // Then a line will be printed for every timer that fires. The name used for a
 // |Callback::Type::Function| timer depends on the circumstances.
--- a/xpfe/appshell/nsWebShellWindow.cpp
+++ b/xpfe/appshell/nsWebShellWindow.cpp
@@ -569,17 +569,17 @@ NS_IMPL_ISUPPORTS(WebShellWindowTimerCal
 
 } // namespace mozilla
 
 void
 nsWebShellWindow::SetPersistenceTimer(uint32_t aDirtyFlags)
 {
   MutexAutoLock lock(mSPTimerLock);
   if (!mSPTimer) {
-    mSPTimer = do_CreateInstance("@mozilla.org/timer;1");
+    mSPTimer = NS_NewTimer();
     if (!mSPTimer) {
       NS_WARNING("Couldn't create @mozilla.org/timer;1 instance?");
       return;
     }
   }
 
   RefPtr<WebShellWindowTimerCallback> callback =
     new WebShellWindowTimerCallback(this);
--- a/xpfe/components/directory/nsDirectoryViewer.cpp
+++ b/xpfe/components/directory/nsDirectoryViewer.cpp
@@ -853,67 +853,59 @@ nsHTTPIndex::GetTargets(nsIRDFResource *
 		    {
     		    // add aSource into list of connections to make
 	    	    mConnectionList->AppendElement(aSource, /*weak =*/ false);
 
                 // if we don't have a timer about to fire, create one
                 // which should fire as soon as possible (out-of-band)
             	if (!mTimer)
             	{
-            		mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
+                    rv = NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+                                                     nsHTTPIndex::FireTimer,
+                                                     this,
+                                                     1,
+                                                     nsITimer::TYPE_ONE_SHOT,
+                                                     "nsHTTPIndex::GetTargets");
+                    // Note: don't addref "this" as we'll cancel the
+                    // timer in the httpIndex destructor
             		NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer");
-            		if (NS_SUCCEEDED(rv))
-            		{
-                          mTimer->InitWithNamedFuncCallback(
-                            nsHTTPIndex::FireTimer,
-                            this,
-                            1,
-                            nsITimer::TYPE_ONE_SHOT,
-                            "nsHTTPIndex::GetTargets");
-                          // Note: don't addref "this" as we'll cancel the
-                          // timer in the httpIndex destructor
-                        }
             	}
 	    	}
 		}
 	}
 
 	return(rv);
 }
 
 
 nsresult
 nsHTTPIndex::AddElement(nsIRDFResource *parent, nsIRDFResource *prop, nsIRDFNode *child)
 {
-    nsresult    rv;
 
     if (!mNodeList)
     {
         mNodeList = nsArray::Create();
     }
 
     // order required: parent, prop, then child
     mNodeList->AppendElement(parent, /*weak =*/ false);
     mNodeList->AppendElement(prop, /*weak =*/ false);
     mNodeList->AppendElement(child, /*weak = */ false);
 
 	if (!mTimer)
 	{
-		mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
-		NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create a timer");
-		if (NS_FAILED(rv))  return(rv);
-
-                mTimer->InitWithNamedFuncCallback(nsHTTPIndex::FireTimer,
-                                                  this,
-                                                  1,
-                                                  nsITimer::TYPE_ONE_SHOT,
-                                                  "nsHTTPIndex::AddElement");
-                // Note: don't addref "this" as we'll cancel the
-                // timer in the httpIndex destructor
-        }
+        return NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+                                           nsHTTPIndex::FireTimer,
+                                           this,
+                                           1,
+                                           nsITimer::TYPE_ONE_SHOT,
+                                           "nsHTTPIndex::AddElement");
+        // Note: don't addref "this" as we'll cancel the
+        // timer in the httpIndex destructor
+    }
 
     return(NS_OK);
 }
 
 void
 nsHTTPIndex::FireTimer(nsITimer* aTimer, void* aClosure)
 {
   nsHTTPIndex *httpIndex = static_cast<nsHTTPIndex *>(aClosure);
@@ -1029,27 +1021,24 @@ nsHTTPIndex::FireTimer(nsITimer* aTimer,
   // weak reference back to nsHTTPIndex
   httpIndex->mTimer->Cancel();
   httpIndex->mTimer = nullptr;
 
   // after firing off any/all of the connections be sure
   // to cancel the timer if we don't need to refire it
   if (refireTimer)
   {
-    httpIndex->mTimer = do_CreateInstance("@mozilla.org/timer;1");
-    if (httpIndex->mTimer)
-    {
-      httpIndex->mTimer->InitWithNamedFuncCallback(nsHTTPIndex::FireTimer,
-                                                   aClosure,
-                                                   10,
-                                                   nsITimer::TYPE_ONE_SHOT,
-                                                   "nsHTTPIndex::FireTimer");
-      // Note: don't addref "this" as we'll cancel the
-      // timer in the httpIndex destructor
-    }
+    NS_NewTimerWithFuncCallback(getter_AddRefs(httpIndex->mTimer),
+                                nsHTTPIndex::FireTimer,
+                                aClosure,
+                                10,
+                                nsITimer::TYPE_ONE_SHOT,
+                                "nsHTTPIndex::FireTimer");
+    // Note: don't addref "this" as we'll cancel the
+    // timer in the httpIndex destructor
   }
 }
 
 NS_IMETHODIMP
 nsHTTPIndex::Assert(nsIRDFResource *aSource, nsIRDFResource *aProperty, nsIRDFNode *aTarget,
 			bool aTruthValue)
 {
 	nsresult	rv = NS_ERROR_UNEXPECTED;