Bug 1263311: Part 1 - Change the nsICancelableRunnable interface. r=froydnj
☠☠ backed out by 61ca2f5fd696 ☠ ☠
authorKyle Huey <khuey@kylehuey.com>
Mon, 11 Apr 2016 11:40:06 -0700
changeset 332521 18132498bc40463a9a0aef248bf14496a4ddd50c
parent 332520 f1b139f6ed93fc428a1ffed1db24e7c7ff9d76df
child 332522 60b1be29446cdbaad6ea03ca64aadf992906eaae
push id1146
push userCallek@gmail.com
push dateMon, 25 Jul 2016 16:35:44 +0000
treeherdermozilla-release@a55778f9cd5a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1263311
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1263311: Part 1 - Change the nsICancelableRunnable interface. r=froydnj
dom/base/nsPerformance.cpp
dom/broadcastchannel/BroadcastChannel.cpp
dom/cache/CachePushStreamChild.cpp
dom/cache/ReadStream.cpp
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContextLossHandler.cpp
dom/events/AsyncEventDispatcher.cpp
dom/events/AsyncEventDispatcher.h
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/IDBDatabase.cpp
dom/ipc/Blob.cpp
dom/messagechannel/MessagePort.cpp
dom/workers/ScriptLoader.cpp
dom/workers/ServiceWorkerPrivate.cpp
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerRunnable.cpp
dom/workers/WorkerRunnable.h
dom/workers/XMLHttpRequest.cpp
ipc/glue/BackgroundImpl.cpp
ipc/glue/MessagePump.cpp
xpcom/base/DebuggerOnGCRunnable.cpp
xpcom/base/DebuggerOnGCRunnable.h
xpcom/glue/nsThreadUtils.cpp
xpcom/glue/nsThreadUtils.h
xpcom/io/nsStreamUtils.cpp
xpcom/threads/TimerThread.cpp
xpcom/threads/moz.build
xpcom/threads/nsICancelableRunnable.h
xpcom/threads/nsICancelableRunnable.idl
xpcom/threads/nsThread.cpp
--- a/dom/base/nsPerformance.cpp
+++ b/dom/base/nsPerformance.cpp
@@ -1147,17 +1147,17 @@ public:
 
   NS_IMETHOD Run() override
   {
     MOZ_ASSERT(mPerformance);
     mPerformance->NotifyObservers();
     return NS_OK;
   }
 
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     mPerformance->CancelNotificationObservers();
     mPerformance = nullptr;
     return NS_OK;
   }
 
 private:
   ~NotifyObserversTask()
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -137,17 +137,18 @@ public:
 private:
   WorkerPrivate* mWorkerPrivate;
   nsACString& mOrigin;
   PrincipalInfo& mPrincipalInfo;
   bool& mPrivateBrowsing;
   ErrorResult& mRv;
 };
 
-class BCPostMessageRunnable final : public nsICancelableRunnable
+class BCPostMessageRunnable final : public nsIRunnable,
+                                    public nsICancelableRunnable
 {
 public:
   NS_DECL_ISUPPORTS
 
   BCPostMessageRunnable(BroadcastChannelChild* aActor,
                         BroadcastChannelMessage* aData)
     : mActor(aActor)
     , mData(aData)
@@ -185,63 +186,65 @@ public:
         message.blobsChild().AppendElement(blobChild);
       }
     }
 
     mActor->SendPostMessage(message);
     return NS_OK;
   }
 
-  NS_IMETHODIMP Cancel() override
+  nsresult Cancel() override
   {
     mActor = nullptr;
     return NS_OK;
   }
 
 private:
   ~BCPostMessageRunnable() {}
 
   RefPtr<BroadcastChannelChild> mActor;
   RefPtr<BroadcastChannelMessage> mData;
 };
 
 NS_IMPL_ISUPPORTS(BCPostMessageRunnable, nsICancelableRunnable, nsIRunnable)
 
-class CloseRunnable final : public nsICancelableRunnable
+class CloseRunnable final : public nsIRunnable,
+                            public nsICancelableRunnable
 {
 public:
   NS_DECL_ISUPPORTS
 
   explicit CloseRunnable(BroadcastChannel* aBC)
     : mBC(aBC)
   {
     MOZ_ASSERT(mBC);
   }
 
   NS_IMETHODIMP Run() override
   {
     mBC->Shutdown();
     return NS_OK;
   }
 
-  NS_IMETHODIMP Cancel() override
+  nsresult Cancel() override
   {
     mBC = nullptr;
     return NS_OK;
   }
 
 private:
   ~CloseRunnable() {}
 
   RefPtr<BroadcastChannel> mBC;
 };
 
 NS_IMPL_ISUPPORTS(CloseRunnable, nsICancelableRunnable, nsIRunnable)
 
-class TeardownRunnable final : public nsICancelableRunnable
+class TeardownRunnable final : public nsIRunnable,
+                               public nsICancelableRunnable
 {
 public:
   NS_DECL_ISUPPORTS
 
   explicit TeardownRunnable(BroadcastChannelChild* aActor)
     : mActor(aActor)
   {
     MOZ_ASSERT(mActor);
@@ -251,17 +254,17 @@ public:
   {
     MOZ_ASSERT(mActor);
     if (!mActor->IsActorDestroyed()) {
       mActor->SendClose();
     }
     return NS_OK;
   }
 
-  NS_IMETHODIMP Cancel() override
+  nsresult Cancel() override
   {
     mActor = nullptr;
     return NS_OK;
   }
 
 private:
   ~TeardownRunnable() {}
 
--- a/dom/cache/CachePushStreamChild.cpp
+++ b/dom/cache/CachePushStreamChild.cpp
@@ -12,17 +12,17 @@
 #include "nsIThread.h"
 #include "nsStreamUtils.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 class CachePushStreamChild::Callback final : public nsIInputStreamCallback
-                                           , public nsICancelableRunnable
+                                           , public nsCancelableRunnable
 {
 public:
   explicit Callback(CachePushStreamChild* aActor)
     : mActor(aActor)
     , mOwningThread(NS_GetCurrentThread())
   {
     MOZ_ASSERT(mActor);
   }
@@ -51,17 +51,17 @@ public:
   {
     MOZ_ASSERT(mOwningThread == NS_GetCurrentThread());
     if (mActor) {
       mActor->OnStreamReady(this);
     }
     return NS_OK;
   }
 
-  NS_IMETHOD
+  nsresult
   Cancel() override
   {
     // Cancel() gets called when the Worker thread is being shutdown.  We have
     // nothing to do here because CachePushStreamChild handles this case via
     // the Feature.
     return NS_OK;
   }
 
@@ -80,22 +80,22 @@ private:
 
     // ClearActor() should be called before the Callback is destroyed
     MOZ_ASSERT(!mActor);
   }
 
   CachePushStreamChild* mActor;
   nsCOMPtr<nsIThread> mOwningThread;
 
-  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_ISUPPORTS_INHERITED
 };
 
-NS_IMPL_ISUPPORTS(CachePushStreamChild::Callback, nsIInputStreamCallback,
-                                                  nsIRunnable,
-                                                  nsICancelableRunnable);
+NS_IMPL_ISUPPORTS_INHERITED(CachePushStreamChild::Callback,
+                            nsCancelableRunnable,
+                            nsIInputStreamCallback);
 
 CachePushStreamChild::CachePushStreamChild(Feature* aFeature,
                                            nsISupports* aParent,
                                            nsIAsyncInputStream* aStream)
   : mParent(aParent)
   , mStream(aStream)
   , mClosed(false)
 {
--- a/dom/cache/ReadStream.cpp
+++ b/dom/cache/ReadStream.cpp
@@ -128,17 +128,17 @@ public:
   {
     mStream->NoteClosedOnOwningThread();
     mStream = nullptr;
     return NS_OK;
   }
 
   // Note, we must proceed with the Run() method since our actor will not
   // clean itself up until we note that the stream is closed.
-  NS_IMETHOD Cancel()
+  nsresult Cancel()
   {
     Run();
     return NS_OK;
   }
 
 private:
   ~NoteClosedRunnable() { }
 
@@ -163,17 +163,17 @@ public:
   {
     mStream->ForgetOnOwningThread();
     mStream = nullptr;
     return NS_OK;
   }
 
   // Note, we must proceed with the Run() method so that we properly
   // call RemoveListener on the actor.
-  NS_IMETHOD Cancel()
+  nsresult Cancel()
   {
     Run();
     return NS_OK;
   }
 
 private:
   ~ForgetRunnable() { }
 
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1543,24 +1543,24 @@ class UpdateContextLossStatusTask : publ
     RefPtr<WebGLContext> mWebGL;
 
 public:
     explicit UpdateContextLossStatusTask(WebGLContext* webgl)
         : mWebGL(webgl)
     {
     }
 
-    NS_IMETHOD Run() {
+    NS_IMETHOD Run() override {
         if (mWebGL)
             mWebGL->UpdateContextLossStatus();
 
         return NS_OK;
     }
 
-    NS_IMETHOD Cancel() {
+    nsresult Cancel() override {
         mWebGL = nullptr;
         return NS_OK;
     }
 };
 
 void
 WebGLContext::EnqueueUpdateContextLossStatus()
 {
--- a/dom/canvas/WebGLContextLossHandler.cpp
+++ b/dom/canvas/WebGLContextLossHandler.cpp
@@ -33,26 +33,25 @@ public:
 
 protected:
     ~ContextLossWorkerEventTarget() {}
 
 private:
     nsCOMPtr<nsIEventTarget> mEventTarget;
 };
 
-class ContextLossWorkerRunnable final : public nsICancelableRunnable
+class ContextLossWorkerRunnable final : public nsCancelableRunnable
 {
 public:
     explicit ContextLossWorkerRunnable(nsIRunnable* aRunnable)
         : mRunnable(aRunnable)
     {
     }
 
-    NS_DECL_NSICANCELABLERUNNABLE
-    NS_DECL_THREADSAFE_ISUPPORTS
+    nsresult Cancel() override;
 
     NS_FORWARD_NSIRUNNABLE(mRunnable->)
 
 protected:
     ~ContextLossWorkerRunnable() {}
 
 private:
     nsCOMPtr<nsIRunnable> mRunnable;
@@ -79,20 +78,17 @@ ContextLossWorkerEventTarget::Dispatch(a
 }
 
 NS_IMETHODIMP
 ContextLossWorkerEventTarget::IsOnCurrentThread(bool* aResult)
 {
     return mEventTarget->IsOnCurrentThread(aResult);
 }
 
-NS_IMPL_ISUPPORTS(ContextLossWorkerRunnable, nsICancelableRunnable,
-                  nsIRunnable)
-
-NS_IMETHODIMP
+nsresult
 ContextLossWorkerRunnable::Cancel()
 {
     mRunnable = nullptr;
     return NS_OK;
 }
 
 // -------------------------------------------------------------------
 // End worker-specific code
--- a/dom/events/AsyncEventDispatcher.cpp
+++ b/dom/events/AsyncEventDispatcher.cpp
@@ -49,17 +49,17 @@ AsyncEventDispatcher::Run()
     MOZ_ASSERT(event->IsTrusted());
     event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   }
   bool dummy;
   mTarget->DispatchEvent(event, &dummy);
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 AsyncEventDispatcher::Cancel()
 {
   mCanceled = true;
   return NS_OK;
 }
 
 nsresult
 AsyncEventDispatcher::PostDOMEvent()
--- a/dom/events/AsyncEventDispatcher.h
+++ b/dom/events/AsyncEventDispatcher.h
@@ -55,17 +55,17 @@ public:
     : mTarget(aTarget)
     , mEvent(aEvent)
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, WidgetEvent& aEvent);
 
   NS_IMETHOD Run() override;
-  NS_IMETHOD Cancel() override;
+  nsresult Cancel() override;
   nsresult PostDOMEvent();
   void RunDOMEventWhenSafe();
 
   nsCOMPtr<dom::EventTarget> mTarget;
   nsCOMPtr<nsIDOMEvent> mEvent;
   nsString              mEventType;
   bool                  mBubbles = false;
   bool                  mOnlyChromeDispatch = false;
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -2525,18 +2525,20 @@ BackgroundRequestChild::Recv__delete__(c
 
   return true;
 }
 
 /*******************************************************************************
  * BackgroundCursorChild
  ******************************************************************************/
 
+// Does not need to be threadsafe since this only runs on one thread, but
+// inheriting from nsCancelableRunnable is easy.
 class BackgroundCursorChild::DelayedActionRunnable final
-  : public nsICancelableRunnable
+  : public nsCancelableRunnable
 {
   using ActionFunc = void (BackgroundCursorChild::*)();
 
   BackgroundCursorChild* mActor;
   RefPtr<IDBRequest> mRequest;
   ActionFunc mActionFunc;
 
 public:
@@ -2547,25 +2549,22 @@ public:
     , mActionFunc(aActionFunc)
   {
     MOZ_ASSERT(aActor);
     aActor->AssertIsOnOwningThread();
     MOZ_ASSERT(mRequest);
     MOZ_ASSERT(mActionFunc);
   }
 
-  // Does not need to be threadsafe since this only runs on one thread.
-  NS_DECL_ISUPPORTS
-
 private:
   ~DelayedActionRunnable()
   { }
 
   NS_DECL_NSIRUNNABLE
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult Cancel() override;
 };
 
 BackgroundCursorChild::BackgroundCursorChild(IDBRequest* aRequest,
                                              IDBObjectStore* aObjectStore,
                                              Direction aDirection)
   : mRequest(aRequest)
   , mTransaction(aRequest->GetTransaction())
   , mObjectStore(aObjectStore)
@@ -2992,20 +2991,16 @@ BackgroundCursorChild::RecvResponse(cons
       MOZ_CRASH("Should never get here!");
   }
 
   mTransaction->OnRequestFinished(/* aActorDestroyedNormally */ true);
 
   return true;
 }
 
-NS_IMPL_ISUPPORTS(BackgroundCursorChild::DelayedActionRunnable,
-                  nsIRunnable,
-                  nsICancelableRunnable)
-
 NS_IMETHODIMP
 BackgroundCursorChild::
 DelayedActionRunnable::Run()
 {
   MOZ_ASSERT(mActor);
   mActor->AssertIsOnOwningThread();
   MOZ_ASSERT(mRequest);
   MOZ_ASSERT(mActionFunc);
@@ -3013,17 +3008,17 @@ DelayedActionRunnable::Run()
   (mActor->*mActionFunc)();
 
   mActor = nullptr;
   mRequest = nullptr;
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 BackgroundCursorChild::
 DelayedActionRunnable::Cancel()
 {
   if (NS_WARN_IF(!mActor)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   // This must always run to clean up our state.
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -62,36 +62,34 @@ using namespace mozilla::services;
 
 namespace {
 
 const char kCycleCollectionObserverTopic[] = "cycle-collector-end";
 const char kMemoryPressureObserverTopic[] = "memory-pressure";
 const char kWindowObserverTopic[] = "inner-window-destroyed";
 
 class CancelableRunnableWrapper final
-  : public nsICancelableRunnable
+  : public nsCancelableRunnable
 {
   nsCOMPtr<nsIRunnable> mRunnable;
 
 public:
   explicit
   CancelableRunnableWrapper(nsIRunnable* aRunnable)
     : mRunnable(aRunnable)
   {
     MOZ_ASSERT(aRunnable);
   }
 
-  NS_DECL_ISUPPORTS
-
 private:
   ~CancelableRunnableWrapper()
   { }
 
   NS_DECL_NSIRUNNABLE
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult Cancel() override;
 };
 
 class DatabaseFile final
   : public PBackgroundIDBDatabaseFileChild
 {
   IDBDatabase* mDatabase;
 
 public:
@@ -1270,32 +1268,30 @@ IDBDatabase::PostHandleEvent(EventChainP
 }
 
 JSObject*
 IDBDatabase::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return IDBDatabaseBinding::Wrap(aCx, this, aGivenProto);
 }
 
-NS_IMPL_ISUPPORTS(CancelableRunnableWrapper, nsIRunnable, nsICancelableRunnable)
-
 NS_IMETHODIMP
 CancelableRunnableWrapper::Run()
 {
   nsCOMPtr<nsIRunnable> runnable;
   mRunnable.swap(runnable);
 
   if (runnable) {
     return runnable->Run();
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 CancelableRunnableWrapper::Cancel()
 {
   if (mRunnable) {
     mRunnable = nullptr;
     return NS_OK;
   }
 
   return NS_ERROR_UNEXPECTED;
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -233,17 +233,17 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
 private:
   ~CancelableRunnableWrapper()
   { }
 
   NS_DECL_NSIRUNNABLE
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult Cancel() override;
 };
 
 NS_IMPL_ISUPPORTS_INHERITED0(CancelableRunnableWrapper, nsCancelableRunnable)
 
 NS_IMETHODIMP
 CancelableRunnableWrapper::Run()
 {
   DebugOnly<bool> onTarget;
@@ -256,17 +256,17 @@ CancelableRunnableWrapper::Run()
 
   if (runnable) {
     return runnable->Run();
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 CancelableRunnableWrapper::Cancel()
 {
   DebugOnly<bool> onTarget;
   MOZ_ASSERT(mDEBUGEventTarget);
   MOZ_ASSERT(NS_SUCCEEDED(mDEBUGEventTarget->IsOnCurrentThread(&onTarget)));
   MOZ_ASSERT(onTarget);
 
   if (NS_WARN_IF(!mRunnable)) {
--- a/dom/messagechannel/MessagePort.cpp
+++ b/dom/messagechannel/MessagePort.cpp
@@ -43,23 +43,21 @@
 #undef PostMessage
 #endif
 
 using namespace mozilla::dom::workers;
 
 namespace mozilla {
 namespace dom {
 
-class PostMessageRunnable final : public nsICancelableRunnable
+class PostMessageRunnable final : public nsCancelableRunnable
 {
   friend class MessagePort;
 
 public:
-  NS_DECL_ISUPPORTS
-
   PostMessageRunnable(MessagePort* aPort, SharedMessagePortMessage* aData)
     : mPort(aPort)
     , mData(aData)
   {
     MOZ_ASSERT(aPort);
     MOZ_ASSERT(aData);
   }
 
@@ -76,17 +74,17 @@ public:
     mPort->UpdateMustKeepAlive();
 
     mPort->mPostMessageRunnable = nullptr;
     mPort->Dispatch();
 
     return rv;
   }
 
-  NS_IMETHOD
+  nsresult
   Cancel() override
   {
     mPort = nullptr;
     mData = nullptr;
     return NS_OK;
   }
 
 private:
@@ -160,18 +158,16 @@ private:
 private:
   ~PostMessageRunnable()
   {}
 
   RefPtr<MessagePort> mPort;
   RefPtr<SharedMessagePortMessage> mData;
 };
 
-NS_IMPL_ISUPPORTS(PostMessageRunnable, nsICancelableRunnable, nsIRunnable)
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
                                                 DOMEventTargetHelper)
   if (tmp->mPostMessageRunnable) {
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mPostMessageRunnable->mPort);
   }
 
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -313,17 +313,18 @@ private:
 
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
 
   virtual void
   PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
           override;
 
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult
+  Cancel() override;
 
   void
   ShutdownScriptLoader(JSContext* aCx,
                        WorkerPrivate* aWorkerPrivate,
                        bool aResult,
                        bool aMutedError);
 
   void LogExceptionToConsole(JSContext* aCx,
@@ -1887,17 +1888,17 @@ ScriptExecutorRunnable::PostRun(JSContex
     // script and GetOrCreateGlobalScope() fails.  In that case we would have
     // returned false from WorkerRun, so assert that.
     MOZ_ASSERT_IF(!result && !mScriptLoader.mRv.Failed(),
                   !aRunResult);
     ShutdownScriptLoader(aCx, aWorkerPrivate, result, mutedError);
   }
 }
 
-NS_IMETHODIMP
+nsresult
 ScriptExecutorRunnable::Cancel()
 {
   if (mLastIndex == mScriptLoader.mLoadInfos.Length() - 1) {
     ShutdownScriptLoader(mWorkerPrivate->GetJSContext(), mWorkerPrivate,
                          false, false);
   }
   return MainThreadWorkerSyncRunnable::Cancel();
 }
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -156,17 +156,17 @@ public:
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
     aWorkerPrivate->AssertIsOnWorkerThread();
     Done(aWorkerPrivate->WorkerScriptExecutedSuccessfully());
 
     return true;
   }
 
-  NS_IMETHOD
+  nsresult
   Cancel() override
   {
     Done(false);
     return WorkerRunnable::Cancel();
   }
 
 private:
   void
@@ -373,17 +373,17 @@ public:
 
   bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
     MOZ_ASSERT(aWorkerPrivate);
     return DispatchLifecycleEvent(aCx, aWorkerPrivate);
   }
 
-  NS_IMETHOD
+  nsresult
   Cancel() override
   {
     mCallback->SetResult(false);
     MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(mCallback));
 
     return WorkerRunnable::Cancel();
   }
 
@@ -1259,17 +1259,17 @@ public:
 
   bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
     MOZ_ASSERT(aWorkerPrivate);
     return DispatchFetchEvent(aCx, aWorkerPrivate);
   }
 
-  NS_IMETHOD
+  nsresult
   Cancel() override
   {
     nsCOMPtr<nsIRunnable> runnable = new ResumeRequest(mInterceptedChannel);
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       NS_WARNING("Failed to resume channel on FetchEventRunnable::Cancel()!\n");
     }
     WorkerRunnable::Cancel();
     return NS_OK;
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -208,21 +208,21 @@ SwapToISupportsArray(SmartPtr<T>& aSrc,
   dest->swap(rawSupports);
 }
 
 // This class is used to wrap any runnables that the worker receives via the
 // nsIEventTarget::Dispatch() method (either from NS_DispatchToCurrentThread or
 // from the worker's EventTarget).
 class ExternalRunnableWrapper final : public WorkerRunnable
 {
-  nsCOMPtr<nsICancelableRunnable> mWrappedRunnable;
+  nsCOMPtr<nsIRunnable> mWrappedRunnable;
 
 public:
   ExternalRunnableWrapper(WorkerPrivate* aWorkerPrivate,
-                          nsICancelableRunnable* aWrappedRunnable)
+                          nsIRunnable* aWrappedRunnable)
   : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount),
     mWrappedRunnable(aWrappedRunnable)
   {
     MOZ_ASSERT(aWorkerPrivate);
     MOZ_ASSERT(aWrappedRunnable);
   }
 
   NS_DECL_ISUPPORTS_INHERITED
@@ -239,20 +239,24 @@ private:
       if (!JS_IsExceptionPending(aCx)) {
         Throw(aCx, rv);
       }
       return false;
     }
     return true;
   }
 
-  NS_IMETHOD
+  nsresult
   Cancel() override
   {
-    nsresult rv = mWrappedRunnable->Cancel();
+    nsresult rv;
+    nsCOMPtr<nsICancelableRunnable> cancelable =
+      do_QueryInterface(mWrappedRunnable);
+    MOZ_ASSERT(cancelable); // We checked this earlier!
+    rv = cancelable->Cancel();
     nsresult rv2 = WorkerRunnable::Cancel();
     return NS_FAILED(rv) ? rv : rv2;
   }
 };
 
 struct WindowAction
 {
   nsPIDOMWindowInner* mWindow;
@@ -619,17 +623,17 @@ private:
     event->InitEvent(NS_LITERAL_STRING("close"), false, false);
     event->SetTrusted(true);
 
     globalScope->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
 
     return true;
   }
 
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     // We need to run regardless.
     Run();
     return WorkerRunnable::Cancel();
   }
 
   virtual void
   PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
@@ -1340,17 +1344,17 @@ private:
     if (mTimer) {
       mTimer->Cancel();
       mTimer = nullptr;
     }
 
     return true;
   }
 
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     // We need to run regardless.
     Run();
     return WorkerRunnable::Cancel();
   }
 };
 
 class UpdateRuntimeOptionsRunnable final : public WorkerControlRunnable
@@ -1650,17 +1654,17 @@ private:
   { }
 
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
   {
     return aWorkerPrivate->ConnectMessagePort(aCx, mPortIdentifier);
   }
 
-  NS_IMETHOD
+  nsresult
   Cancel() override
   {
     MessagePort::ForceClose(mPortIdentifier);
     return WorkerRunnable::Cancel();
   }
 };
 
 class DummyRunnable final
@@ -2467,17 +2471,17 @@ WorkerPrivateParent<Derived>::MaybeWrapA
   }
 
   nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(runnable);
   if (!cancelable) {
     MOZ_CRASH("All runnables destined for a worker thread must be cancelable!");
   }
 
   workerRunnable =
-    new ExternalRunnableWrapper(ParentAsWorkerPrivate(), cancelable);
+    new ExternalRunnableWrapper(ParentAsWorkerPrivate(), runnable);
   return workerRunnable.forget();
 }
 
 template <class Derived>
 already_AddRefed<nsIEventTarget>
 WorkerPrivateParent<Derived>::GetEventTarget()
 {
   WorkerPrivate* self = ParentAsWorkerPrivate();
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -210,17 +210,17 @@ WorkerRunnable::FromRunnable(nsIRunnable
 }
 
 NS_IMPL_ADDREF(WorkerRunnable)
 NS_IMPL_RELEASE(WorkerRunnable)
 
 NS_INTERFACE_MAP_BEGIN(WorkerRunnable)
   NS_INTERFACE_MAP_ENTRY(nsIRunnable)
   NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable)
   // kWorkerRunnableIID is special in that it does not AddRef its result.
   if (aIID.Equals(kWorkerRunnableIID)) {
     *aInstancePtr = this;
     return NS_OK;
   }
   else
 NS_INTERFACE_MAP_END
 
@@ -397,17 +397,17 @@ WorkerRunnable::Run()
   // (CompileScriptRunnable) it actually doesn't matter which compartment we're
   // in for PostRun.
   PostRun(cx, mWorkerPrivate, result);
   MOZ_ASSERT(!jsapi->HasException());
 
   return result ? NS_OK : NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP
+nsresult
 WorkerRunnable::Cancel()
 {
   uint32_t canceledCount = ++mCanceled;
 
   MOZ_ASSERT(canceledCount, "Cancel() overflow!");
 
   // The docs say that Cancel() should not be called more than once and that we
   // should throw NS_ERROR_UNEXPECTED if it is.
@@ -472,17 +472,17 @@ StopSyncLoopRunnable::StopSyncLoopRunnab
                                bool aResult)
 : WorkerSyncRunnable(aWorkerPrivate, Move(aSyncLoopTarget)), mResult(aResult)
 {
 #ifdef DEBUG
   mWorkerPrivate->AssertValidSyncLoop(mSyncLoopTarget);
 #endif
 }
 
-NS_IMETHODIMP
+nsresult
 StopSyncLoopRunnable::Cancel()
 {
   nsresult rv = Run();
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Run() failed");
 
   nsresult rv2 = WorkerSyncRunnable::Cancel();
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv2), "Cancel() failed");
 
@@ -529,17 +529,17 @@ WorkerControlRunnable::WorkerControlRunn
 {
   MOZ_ASSERT(aWorkerPrivate);
   MOZ_ASSERT(aBehavior == ParentThreadUnchangedBusyCount ||
              aBehavior == WorkerThreadUnchangedBusyCount,
              "WorkerControlRunnables should not modify the busy count");
 }
 #endif
 
-NS_IMETHODIMP
+nsresult
 WorkerControlRunnable::Cancel()
 {
   if (NS_FAILED(Run())) {
     NS_WARNING("WorkerControlRunnable::Run() failed.");
   }
 
   return WorkerRunnable::Cancel();
 }
--- a/dom/workers/WorkerRunnable.h
+++ b/dom/workers/WorkerRunnable.h
@@ -24,17 +24,18 @@ class ErrorResult;
 
 BEGIN_WORKERS_NAMESPACE
 
 class WorkerPrivate;
 
 // Use this runnable to communicate from the worker to its parent or vice-versa.
 // The busy count must be taken into consideration and declared at construction
 // time.
-class WorkerRunnable : public nsICancelableRunnable
+class WorkerRunnable : public nsIRunnable,
+                       public nsICancelableRunnable
 {
 public:
   enum TargetAndBusyBehavior {
     // Target the main thread for top-level workers, otherwise target the
     // WorkerThread of the worker's parent. No change to the busy count.
     ParentThreadUnchangedBusyCount,
 
     // Target the thread where the worker event loop runs. The busy count will
@@ -66,17 +67,18 @@ private:
   bool mCallingCancelWithinRun;
 
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // If you override Cancel() then you'll need to either call the base class
   // Cancel() method or override IsCanceled() so that the Run() method bails out
   // appropriately.
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult
+  Cancel() override;
 
   // The return value is true if and only if both PreDispatch and
   // DispatchInternal return true.
   bool
   Dispatch();
 
   // See above note about Cancel().
   virtual bool
@@ -272,17 +274,18 @@ class StopSyncLoopRunnable : public Work
 public:
   // Passing null for aSyncLoopTarget is not allowed.
   StopSyncLoopRunnable(WorkerPrivate* aWorkerPrivate,
                        already_AddRefed<nsIEventTarget>&& aSyncLoopTarget,
                        bool aResult);
 
   // By default StopSyncLoopRunnables cannot be canceled since they could leave
   // a sync loop spinning forever.
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult
+  Cancel() override;
 
 protected:
   virtual ~StopSyncLoopRunnable()
   { }
 
   // Called on the worker thread, in WorkerRun, right before stopping the
   // syncloop to set an exception (however subclasses want to handle that) if
   // mResult is false.  Note that overrides of this method must NOT set an
@@ -349,17 +352,17 @@ protected:
 #else
   : WorkerRunnable(aWorkerPrivate, aBehavior)
   { }
 #endif
 
   virtual ~WorkerControlRunnable()
   { }
 
-  NS_IMETHOD
+  nsresult
   Cancel() override;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
 private:
   virtual bool
   DispatchInternal() override;
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -494,17 +494,17 @@ class LoadStartDetectionRunnable final :
 
       if (mXMLHttpRequestPrivate->SendInProgress()) {
         mXMLHttpRequestPrivate->Unpin();
       }
 
       return true;
     }
 
-    NS_IMETHOD
+    nsresult
     Cancel() override
     {
       // This must run!
       nsresult rv = MainThreadProxyRunnable::Cancel();
       nsresult rv2 = Run();
       return NS_FAILED(rv) ? rv : rv2;
     }
   };
--- a/ipc/glue/BackgroundImpl.cpp
+++ b/ipc/glue/BackgroundImpl.cpp
@@ -703,24 +703,22 @@ class ChildImpl::AlreadyCreatedCallbackR
   public nsCancelableRunnable
 {
 public:
   AlreadyCreatedCallbackRunnable()
   {
     // May be created on any thread!
   }
 
-  NS_DECL_ISUPPORTS_INHERITED
-
 protected:
   virtual ~AlreadyCreatedCallbackRunnable()
   { }
 
   NS_DECL_NSIRUNNABLE
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult Cancel() override;
 };
 
 class ChildImpl::FailedCreateCallbackRunnable final : public nsRunnable
 {
 public:
   FailedCreateCallbackRunnable()
   {
     // May be created on any thread!
@@ -1809,19 +1807,16 @@ ChildImpl::GetNextCallback()
   nsCOMPtr<nsIIPCBackgroundChildCreateCallback> callback;
   threadLocalInfo->mCallbacks[0].swap(callback);
 
   threadLocalInfo->mCallbacks.RemoveElementAt(0);
 
   return callback.forget();
 }
 
-NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::AlreadyCreatedCallbackRunnable,
-                             nsCancelableRunnable)
-
 NS_IMETHODIMP
 ChildImpl::AlreadyCreatedCallbackRunnable::Run()
 {
   // May run on any thread!
 
   // Report the current actor back in the callback.
   PBackgroundChild* actor = ChildImpl::GetForCurrentThread();
 
@@ -1839,17 +1834,17 @@ ChildImpl::AlreadyCreatedCallbackRunnabl
   while (callback) {
     callback->ActorCreated(actor);
     callback = ChildImpl::GetNextCallback();
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 ChildImpl::AlreadyCreatedCallbackRunnable::Cancel()
 {
   // These are IPC infrastructure objects and need to run unconditionally.
   Run();
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(ChildImpl::FailedCreateCallbackRunnable,
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -34,30 +34,30 @@ NS_DEFINE_NAMED_CID(NS_TIMER_CID);
 
 #ifdef DEBUG
 static MessagePump::Delegate* gFirstDelegate;
 #endif
 
 namespace mozilla {
 namespace ipc {
 
-class DoWorkRunnable final : public nsICancelableRunnable,
+class DoWorkRunnable final : public nsCancelableRunnable,
                              public nsITimerCallback
 {
 public:
   explicit DoWorkRunnable(MessagePump* aPump)
   : mPump(aPump)
   {
     MOZ_ASSERT(aPump);
   }
 
-  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSITIMERCALLBACK
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult Cancel() override;
 
 private:
   ~DoWorkRunnable()
   { }
 
   MessagePump* mPump;
   // DoWorkRunnable is designed as a stateless singleton.  Do not add stateful
   // members here!
@@ -204,18 +204,18 @@ void
 MessagePump::DoDelayedWork(base::MessagePump::Delegate* aDelegate)
 {
   aDelegate->DoDelayedWork(&delayed_work_time_);
   if (!delayed_work_time_.is_null()) {
     ScheduleDelayedWork(delayed_work_time_);
   }
 }
 
-NS_IMPL_ISUPPORTS(DoWorkRunnable, nsIRunnable, nsITimerCallback,
-                                  nsICancelableRunnable)
+NS_IMPL_ISUPPORTS_INHERITED(DoWorkRunnable, nsCancelableRunnable,
+			    nsITimerCallback)
 
 NS_IMETHODIMP
 DoWorkRunnable::Run()
 {
   MessageLoop* loop = MessageLoop::current();
   MOZ_ASSERT(loop);
 
   bool nestableTasksAllowed = loop->NestableTasksAllowed();
@@ -239,17 +239,17 @@ DoWorkRunnable::Notify(nsITimer* aTimer)
   bool nestableTasksAllowed = loop->NestableTasksAllowed();
   loop->SetNestableTasksAllowed(true);
   mPump->DoDelayedWork(loop);
   loop->SetNestableTasksAllowed(nestableTasksAllowed);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 DoWorkRunnable::Cancel()
 {
   // Workers require cancelable runnables, but we can't really cancel cleanly
   // here.  If we don't process this runnable then we will leave something
   // unprocessed in the message_loop.  Therefore, eagerly complete our work
   // instead by immediately calling Run().  Run() should be called separately
   // after this.  Unfortunately we cannot use flags to verify this because
   // DoWorkRunnable is a stateless singleton that can be in the event queue
--- a/xpcom/base/DebuggerOnGCRunnable.cpp
+++ b/xpcom/base/DebuggerOnGCRunnable.cpp
@@ -32,16 +32,16 @@ DebuggerOnGCRunnable::Run()
   AutoJSAPI jsapi;
   jsapi.Init();
   if (!JS::dbg::FireOnGarbageCollectionHook(jsapi.cx(), Move(mGCData))) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
+nsresult
 DebuggerOnGCRunnable::Cancel()
 {
   mGCData = nullptr;
   return NS_OK;
 }
 
 } // namespace mozilla
--- a/xpcom/base/DebuggerOnGCRunnable.h
+++ b/xpcom/base/DebuggerOnGCRunnable.h
@@ -22,14 +22,14 @@ class DebuggerOnGCRunnable : public nsCa
   explicit DebuggerOnGCRunnable(JS::dbg::GarbageCollectionEvent::Ptr&& aGCData)
     : mGCData(Move(aGCData))
   { }
 
 public:
   static NS_METHOD Enqueue(JSRuntime* aRt, const JS::GCDescription& aDesc);
 
   NS_DECL_NSIRUNNABLE
-  NS_DECL_NSICANCELABLERUNNABLE
+  nsresult Cancel() override;
 };
 
 } // namespace mozilla
 
 #endif // ifdef mozilla_dom_DebuggerOnGCRunnable_h
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -36,27 +36,20 @@ NS_IMPL_ISUPPORTS(nsRunnable, nsIRunnabl
 
 NS_IMETHODIMP
 nsRunnable::Run()
 {
   // Do nothing
   return NS_OK;
 }
 
-NS_IMPL_ISUPPORTS(nsCancelableRunnable, nsICancelableRunnable,
-                  nsIRunnable)
+NS_IMPL_ISUPPORTS_INHERITED(nsCancelableRunnable, nsRunnable,
+                            nsICancelableRunnable)
 
-NS_IMETHODIMP
-nsCancelableRunnable::Run()
-{
-  // Do nothing
-  return NS_OK;
-}
-
-NS_IMETHODIMP
+nsresult
 nsCancelableRunnable::Cancel()
 {
   // Do nothing
   return NS_OK;
 }
 
 #endif  // XPCOM_GLUE_AVOID_NSPR
 
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -228,22 +228,23 @@ public:
 
   nsRunnable() {}
 
 protected:
   virtual ~nsRunnable() {}
 };
 
 // This class is designed to be subclassed.
-class nsCancelableRunnable : public nsICancelableRunnable
+class nsCancelableRunnable : public nsRunnable,
+                             public nsICancelableRunnable
 {
 public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-  NS_DECL_NSICANCELABLERUNNABLE
+  NS_DECL_ISUPPORTS_INHERITED
+  // nsICancelableRunnable
+  virtual nsresult Cancel() override;
 
   nsCancelableRunnable() {}
 
 protected:
   virtual ~nsCancelableRunnable() {}
 };
 
 // An event that can be used to call a C++11 functions or function objects,
--- a/xpcom/io/nsStreamUtils.cpp
+++ b/xpcom/io/nsStreamUtils.cpp
@@ -15,30 +15,31 @@
 #include "nsICancelableRunnable.h"
 #include "nsISafeOutputStream.h"
 #include "nsString.h"
 #include "nsIAsyncInputStream.h"
 #include "nsIAsyncOutputStream.h"
 #include "nsIBufferedStreams.h"
 #include "nsNetCID.h"
 #include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
 
 using namespace mozilla;
 
 //-----------------------------------------------------------------------------
 
 // This is a nsICancelableRunnable because we can dispatch it to Workers and
 // those can be shut down at any time, and in these cases, Cancel() is called
 // instead of Run().
 class nsInputStreamReadyEvent final
-  : public nsICancelableRunnable
+  : public nsCancelableRunnable
   , public nsIInputStreamCallback
 {
 public:
-  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_ISUPPORTS_INHERITED
 
   nsInputStreamReadyEvent(nsIInputStreamCallback* aCallback,
                           nsIEventTarget* aTarget)
     : mCallback(aCallback)
     , mTarget(aTarget)
   {
   }
 
@@ -93,42 +94,42 @@ public:
       if (mStream) {
         mCallback->OnInputStreamReady(mStream);
       }
       mCallback = nullptr;
     }
     return NS_OK;
   }
 
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     mCallback = nullptr;
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIAsyncInputStream>    mStream;
   nsCOMPtr<nsIInputStreamCallback> mCallback;
   nsCOMPtr<nsIEventTarget>         mTarget;
 };
 
-NS_IMPL_ISUPPORTS(nsInputStreamReadyEvent, nsICancelableRunnable,
-                  nsIRunnable, nsIInputStreamCallback)
+NS_IMPL_ISUPPORTS_INHERITED(nsInputStreamReadyEvent, nsCancelableRunnable,
+                            nsIInputStreamCallback)
 
 //-----------------------------------------------------------------------------
 
 // This is a nsICancelableRunnable because we can dispatch it to Workers and
 // those can be shut down at any time, and in these cases, Cancel() is called
 // instead of Run().
 class nsOutputStreamReadyEvent final
-  : public nsICancelableRunnable
+  : public nsCancelableRunnable
   , public nsIOutputStreamCallback
 {
 public:
-  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_ISUPPORTS_INHERITED
 
   nsOutputStreamReadyEvent(nsIOutputStreamCallback* aCallback,
                            nsIEventTarget* aTarget)
     : mCallback(aCallback)
     , mTarget(aTarget)
   {
   }
 
@@ -183,30 +184,30 @@ public:
       if (mStream) {
         mCallback->OnOutputStreamReady(mStream);
       }
       mCallback = nullptr;
     }
     return NS_OK;
   }
 
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     mCallback = nullptr;
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIAsyncOutputStream>    mStream;
   nsCOMPtr<nsIOutputStreamCallback> mCallback;
   nsCOMPtr<nsIEventTarget>          mTarget;
 };
 
-NS_IMPL_ISUPPORTS(nsOutputStreamReadyEvent, nsICancelableRunnable,
-                  nsIRunnable, nsIOutputStreamCallback)
+NS_IMPL_ISUPPORTS_INHERITED(nsOutputStreamReadyEvent, nsCancelableRunnable,
+                            nsIOutputStreamCallback)
 
 //-----------------------------------------------------------------------------
 
 already_AddRefed<nsIInputStreamCallback>
 NS_NewInputStreamReadyEvent(nsIInputStreamCallback* aCallback,
                             nsIEventTarget* aTarget)
 {
   NS_ASSERTION(aCallback, "null callback");
@@ -229,20 +230,20 @@ NS_NewOutputStreamReadyEvent(nsIOutputSt
 
 //-----------------------------------------------------------------------------
 // NS_AsyncCopy implementation
 
 // abstract stream copier...
 class nsAStreamCopier
   : public nsIInputStreamCallback
   , public nsIOutputStreamCallback
-  , public nsICancelableRunnable
+  , public nsCancelableRunnable
 {
 public:
-  NS_DECL_THREADSAFE_ISUPPORTS
+  NS_DECL_ISUPPORTS_INHERITED
 
   nsAStreamCopier()
     : mLock("nsAStreamCopier.mLock")
     , mCallback(nullptr)
     , mProgressCallback(nullptr)
     , mClosure(nullptr)
     , mChunkSize(0)
     , mEventInProcess(false)
@@ -446,17 +447,17 @@ public:
     if (mEventIsPending) {
       mEventIsPending = false;
       PostContinuationEvent_Locked();
     }
 
     return NS_OK;
   }
 
-  NS_IMETHOD Cancel() MOZ_MUST_OVERRIDE override = 0;
+  nsresult Cancel() MOZ_MUST_OVERRIDE override = 0;
 
   nsresult PostContinuationEvent()
   {
     // we cannot post a continuation event if there is currently
     // an event in process.  doing so could result in Process being
     // run simultaneously on multiple threads, so we mark the event
     // as pending, and if an event is already in process then we
     // just let that existing event take care of posting the real
@@ -501,21 +502,20 @@ protected:
   nsresult                       mCancelStatus;
 
   // virtual since subclasses call superclass Release()
   virtual ~nsAStreamCopier()
   {
   }
 };
 
-NS_IMPL_ISUPPORTS(nsAStreamCopier,
-                  nsIInputStreamCallback,
-                  nsIOutputStreamCallback,
-                  nsICancelableRunnable,
-                  nsIRunnable)
+NS_IMPL_ISUPPORTS_INHERITED(nsAStreamCopier,
+                            nsCancelableRunnable,
+                            nsIInputStreamCallback,
+                            nsIOutputStreamCallback)
 
 class nsStreamCopierIB final : public nsAStreamCopier
 {
 public:
   nsStreamCopierIB() : nsAStreamCopier()
   {
   }
   virtual ~nsStreamCopierIB()
@@ -557,17 +557,17 @@ public:
 
     uint32_t n;
     *aSourceCondition =
       mSource->ReadSegments(ConsumeInputBuffer, &state, mChunkSize, &n);
     *aSinkCondition = state.mSinkCondition;
     return n;
   }
 
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     return NS_OK;
   }
 };
 
 class nsStreamCopierOB final : public nsAStreamCopier
 {
 public:
@@ -613,17 +613,17 @@ public:
 
     uint32_t n;
     *aSinkCondition =
       mSink->WriteSegments(FillOutputBuffer, &state, mChunkSize, &n);
     *aSourceCondition = state.mSourceCondition;
     return n;
   }
 
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     return NS_OK;
   }
 };
 
 //-----------------------------------------------------------------------------
 
 nsresult
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -134,17 +134,17 @@ public:
 // This is a nsICancelableRunnable because we can dispatch it to Workers and
 // those can be shut down at any time, and in these cases, Cancel() is called
 // instead of Run().
 class nsTimerEvent : public nsCancelableRunnable
 {
 public:
   NS_IMETHOD Run() override;
 
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     // Since nsTimerImpl is not thread-safe, we should release |mTimer|
     // here in the target thread to avoid race condition. Otherwise,
     // ~nsTimerEvent() which calls nsTimerImpl::Release() could run in the
     // timer thread and result in race condition.
     mTimer = nullptr;
     return NS_OK;
   }
--- a/xpcom/threads/moz.build
+++ b/xpcom/threads/moz.build
@@ -1,32 +1,32 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 XPIDL_SOURCES += [
-    'nsICancelableRunnable.idl',
     'nsIEnvironment.idl',
     'nsIEventTarget.idl',
     'nsIProcess.idl',
     'nsIRunnable.idl',
     'nsISupportsPriority.idl',
     'nsIThread.idl',
     'nsIThreadInternal.idl',
     'nsIThreadManager.idl',
     'nsIThreadPool.idl',
     'nsITimer.idl',
 ]
 
 XPIDL_MODULE = 'xpcom_threads'
 
 EXPORTS += [
     'nsEventQueue.h',
+    'nsICancelableRunnable.h',
     'nsMemoryPressure.h',
     'nsProcess.h',
     'nsThread.h',
 ]
 
 EXPORTS.mozilla += [
     'AbstractThread.h',
     'BackgroundHangMonitor.h',
new file mode 100644
--- /dev/null
+++ b/xpcom/threads/nsICancelableRunnable.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 2; 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/. */
+
+#ifndef nsICancelableRunnable_h__
+#define nsICancelableRunnable_h__
+
+#include "nsISupports.h"
+
+#define NS_ICANCELABLERUNNABLE_IID \
+{ 0xde93dc4c, 0x5eea, 0x4eb7, \
+{ 0xb6, 0xd1, 0xdb, 0xf1, 0xe0, 0xce, 0xf6, 0x5c } }
+
+class nsICancelableRunnable : public nsISupports
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANCELABLERUNNABLE_IID)
+
+  /*
+   * Cancels a pending task.  If the task has already been executed this will
+   * be a no-op.  Calling this method twice is considered an error.
+   *
+   * @throws NS_ERROR_UNEXPECTED
+   *   Indicates that the runnable has already been canceled.
+   */
+  virtual nsresult Cancel() = 0;
+
+protected:
+  nsICancelableRunnable() { }
+  virtual ~nsICancelableRunnable() {}
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsICancelableRunnable,
+                              NS_ICANCELABLERUNNABLE_IID)
+
+#endif // nsICancelableRunnable_h__
deleted file mode 100644
--- a/xpcom/threads/nsICancelableRunnable.idl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; 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 "nsIRunnable.idl"
-
-/**
- * Represents a task which can be dispatched to a thread for execution and
- * which can be cancelled if necessary.
- */
-
-[scriptable, uuid(de93dc4c-5eea-4eb7-b6d1-dbf1e0cef65c)]
-interface nsICancelableRunnable : nsIRunnable
-{
-    /**
-     * Cancels a pending task.  If the task has already been executed this will
-     * be a no-op.  Calling this method twice is considered an error.
-     * If cancel() is called, run() will not be called.
-     *
-     * @throws NS_ERROR_UNEXPECTED
-     *   Indicates that the runnable has already been canceled.
-     */
-    void cancel();
-};
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -263,17 +263,17 @@ public:
   {
   }
   NS_DECL_ISUPPORTS_INHERITED
   NS_IMETHOD Run() override
   {
     mShutdownContext->terminatingThread->ShutdownComplete(mShutdownContext);
     return NS_OK;
   }
-  NS_IMETHOD Cancel() override
+  nsresult Cancel() override
   {
     return Run();
   }
 private:
   virtual ~nsThreadShutdownAckEvent() { }
 
   nsThreadShutdownContext* mShutdownContext;
 };