Bug 1540962 - Make nsICommandManager builtinclass and make users use nsCommandManager directly r=bzbarsky
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 03 Apr 2019 12:51:38 +0000
changeset 467760 b8484c4d2e849ddabf314bc425407570b219b503
parent 467759 d021cea258c726b6a3bca41eab30bda959967aeb
child 467761 d2d7393a6a90a61ce6b575005827dc9f28519245
push id35810
push useraciure@mozilla.com
push dateThu, 04 Apr 2019 04:33:36 +0000
treeherdermozilla-central@b72c02e34261 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1540962
milestone68.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 1540962 - Make nsICommandManager builtinclass and make users use nsCommandManager directly r=bzbarsky `nsICommandManager` isn't implemented by JS even in comm-central nor BlueGriffon. Therefore, we can make it a builtinclass. Additionally, this patch makes all users in C++ use `nsCommandManager` which is the only implementation of `nsICommandManager`. This avoids QI from `nsICommandManager` to `nsPICommandUpdater`. Differential Revision: https://phabricator.services.mozilla.com/D25726
accessible/generic/DocAccessible.cpp
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
dom/commandhandler/nsCommandManager.cpp
dom/commandhandler/nsCommandManager.h
dom/commandhandler/nsICommandManager.idl
dom/html/nsHTMLDocument.cpp
dom/html/nsHTMLDocument.h
editor/composer/ComposerCommandsUpdater.cpp
editor/composer/nsEditingSession.cpp
editor/libeditor/HTMLEditorDocumentCommands.cpp
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -14,19 +14,19 @@
 #include "nsAccUtils.h"
 #include "nsEventShell.h"
 #include "nsTextEquivUtils.h"
 #include "Role.h"
 #include "RootAccessible.h"
 #include "TreeWalker.h"
 #include "xpcAccessibleDocument.h"
 
+#include "nsCommandManager.h"
 #include "nsContentUtils.h"
 #include "nsIMutableArray.h"
-#include "nsICommandManager.h"
 #include "nsIDocShell.h"
 #include "mozilla/dom/Document.h"
 #include "nsPIDOMWindow.h"
 #include "nsIEditingSession.h"
 #include "nsIFrame.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsImageFrame.h"
 #include "nsIPersistentProperties2.h"
@@ -500,17 +500,17 @@ nsRect DocAccessible::RelativeBounds(nsI
 
 // DocAccessible protected member
 nsresult DocAccessible::AddEventListeners() {
   nsCOMPtr<nsIDocShell> docShell(mDocumentNode->GetDocShell());
 
   // We want to add a command observer only if the document is content and has
   // an editor.
   if (docShell->ItemType() == nsIDocShellTreeItem::typeContent) {
-    nsCOMPtr<nsICommandManager> commandManager = docShell->GetCommandManager();
+    RefPtr<nsCommandManager> commandManager = docShell->GetCommandManager();
     if (commandManager)
       commandManager->AddCommandObserver(this, "obs_documentCreated");
   }
 
   SelectionMgr()->AddDocSelectionListener(mPresShell);
 
   // Add document observer.
   mDocumentNode->AddObserver(this);
@@ -528,18 +528,17 @@ nsresult DocAccessible::RemoveEventListe
   if (mDocumentNode) {
     mDocumentNode->RemoveObserver(this);
 
     nsCOMPtr<nsIDocShell> docShell(mDocumentNode->GetDocShell());
     NS_ASSERTION(docShell, "doc should support nsIDocShellTreeItem.");
 
     if (docShell) {
       if (docShell->ItemType() == nsIDocShellTreeItem::typeContent) {
-        nsCOMPtr<nsICommandManager> commandManager =
-            docShell->GetCommandManager();
+        RefPtr<nsCommandManager> commandManager = docShell->GetCommandManager();
         if (commandManager) {
           commandManager->RemoveCommandObserver(this, "obs_documentCreated");
         }
       }
     }
   }
 
   if (mScrollWatchTimer) {
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -74,17 +74,16 @@
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIAuthPrompt.h"
 #include "nsIAuthPrompt2.h"
 #include "nsICachingChannel.h"
 #include "nsICaptivePortalService.h"
 #include "nsIChannel.h"
 #include "nsIChannelEventSink.h"
 #include "nsIClassOfService.h"
-#include "nsICommandManager.h"
 #include "nsIConsoleReportCollector.h"
 #include "nsIContent.h"
 #include "nsIContentInlines.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIContentViewer.h"
 #include "nsIController.h"
 #include "nsICookieService.h"
 #include "nsIDocShellTreeItem.h"
@@ -570,17 +569,17 @@ NS_INTERFACE_MAP_END_INHERITING(nsDocLoa
 NS_IMETHODIMP
 nsDocShell::GetInterface(const nsIID& aIID, void** aSink) {
   MOZ_ASSERT(aSink, "null out param");
 
   *aSink = nullptr;
 
   if (aIID.Equals(NS_GET_IID(nsICommandManager))) {
     NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE);
-    *aSink = mCommandManager;
+    *aSink = static_cast<nsICommandManager*>(mCommandManager.get());
   } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener))) {
     *aSink = mContentListener;
   } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)) ||
               aIID.Equals(NS_GET_IID(nsIGlobalObject)) ||
               aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)) ||
               aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)) ||
               aIID.Equals(NS_GET_IID(nsIDOMWindow))) &&
              NS_SUCCEEDED(EnsureScriptEnvironment())) {
@@ -12378,22 +12377,21 @@ nsDocShell::DoCommandWithParams(const ch
     return rv;
   }
 
   return commandController->DoCommandWithParams(aCommand, aParams);
 }
 
 nsresult nsDocShell::EnsureCommandHandler() {
   if (!mCommandManager) {
-    nsCOMPtr<nsPICommandUpdater> commandUpdater = new nsCommandManager();
-
+    RefPtr<nsCommandManager> commandManager = new nsCommandManager();
     nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow();
-    nsresult rv = commandUpdater->Init(domWindow);
+    nsresult rv = commandManager->Init(domWindow);
     if (NS_SUCCEEDED(rv)) {
-      mCommandManager = do_QueryInterface(commandUpdater);
+      mCommandManager = std::move(commandManager);
     }
   }
 
   return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
 }
 
 // link handling
 
@@ -13284,17 +13282,17 @@ nsDocShell::GetScriptableTabChild(nsITab
   return *aTabChild ? NS_OK : NS_ERROR_FAILURE;
 }
 
 already_AddRefed<nsITabChild> nsDocShell::GetTabChild() {
   nsCOMPtr<nsITabChild> tc = do_QueryReferent(mTabChild);
   return tc.forget();
 }
 
-nsICommandManager* nsDocShell::GetCommandManager() {
+nsCommandManager* nsDocShell::GetCommandManager() {
   NS_ENSURE_SUCCESS(EnsureCommandHandler(), nullptr);
   return mCommandManager;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetIsOnlyToplevelInTabGroup(bool* aResult) {
   MOZ_ASSERT(aResult);
 
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -68,33 +68,33 @@ class HTMLEditor;
 enum class TaskCategory;
 namespace dom {
 class ClientInfo;
 class ClientSource;
 class EventTarget;
 }  // namespace dom
 }  // namespace mozilla
 
-class nsICommandManager;
 class nsIContentViewer;
 class nsIController;
 class nsIDocShellTreeOwner;
 class nsIHttpChannel;
 class nsIMutableArray;
 class nsIPrompt;
 class nsIScrollableFrame;
 class nsISecureBrowserUI;
 class nsISHistory;
 class nsIStringBundle;
 class nsIURIFixup;
 class nsIURILoader;
 class nsIWebBrowserFind;
 class nsIWidget;
 class nsIReferrerInfo;
 
+class nsCommandManager;
 class nsDocShell;
 class nsDocShellEditorData;
 class nsDOMNavigationTiming;
 class nsDSURIContentListener;
 class nsGlobalWindowInner;
 class nsGlobalWindowOuter;
 
 class FramingChecker;
@@ -949,17 +949,17 @@ class nsDocShell final : public nsDocLoa
   nsCOMPtr<nsIMutableArray> mRefreshURIList;
   nsCOMPtr<nsIMutableArray> mSavedRefreshURIList;
   nsCOMPtr<nsIDOMStorageManager> mSessionStorageManager;
   uint64_t mContentWindowID;
   nsCOMPtr<nsIContentViewer> mContentViewer;
   nsCOMPtr<nsIWidget> mParentWidget;
   RefPtr<mozilla::dom::ChildSHistory> mSessionHistory;
   nsCOMPtr<nsIWebBrowserFind> mFind;
-  nsCOMPtr<nsICommandManager> mCommandManager;
+  RefPtr<nsCommandManager> mCommandManager;
   RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
 
   // Weak reference to our TabChild actor.
   nsWeakPtr mTabChild;
 
   // Dimensions of the docshell
   nsIntRect mBounds;
 
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -10,16 +10,17 @@
 
 %{ C++
 #include "js/TypeDecls.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/UniquePtr.h"
 #include "nsCOMPtr.h"
 #include "nsIURI.h"
+class nsCommandManager;
 class nsPresContext;
 class nsIPresShell;
 class nsDocShellLoadState;
 namespace mozilla {
 class Encoding;
 class HTMLEditor;
 namespace dom {
 class BrowsingContext;
@@ -29,16 +30,17 @@ class ClientSource;
 %}
 
 /**
  * The nsIDocShell interface.
  */
 
 [ptr] native nsPresContext(nsPresContext);
 [ptr] native nsIPresShell(nsIPresShell);
+[ptr] native nsCommandManager(nsCommandManager);
 [ref] native MaybeURI(mozilla::Maybe<nsCOMPtr<nsIURI>>);
 [ref] native Encoding(const mozilla::Encoding*);
       native UniqueClientSource(mozilla::UniquePtr<mozilla::dom::ClientSource>);
 
 interface nsIURI;
 interface nsIChannel;
 interface nsIContentViewer;
 interface nsIDocShellLoadInfo;
@@ -55,17 +57,16 @@ interface nsIStructuredCloneContainer;
 interface nsIDOMStorage;
 interface nsIPrincipal;
 interface nsIWebBrowserPrint;
 interface nsIPrivacyTransitionObserver;
 interface nsIReflowObserver;
 interface nsIScrollObserver;
 interface nsITabParent;
 interface nsITabChild;
-interface nsICommandManager;
 interface nsICommandParams;
 interface nsILoadURIDelegate;
 native TabChildRef(already_AddRefed<nsITabChild>);
 native nsDocShellLoadStatePtr(nsDocShellLoadState*);
 
 webidl BrowsingContext;
 webidl ContentFrameMessageManager;
 webidl EventTarget;
@@ -999,17 +1000,17 @@ interface nsIDocShell : nsIDocShellTreeI
   readonly attribute nsIEditingSession editingSession;
 
   /**
    * The tab child for this docshell.
    */
   [binaryname(ScriptableTabChild)] readonly attribute nsITabChild tabChild;
   [noscript,notxpcom,nostdcall] TabChildRef GetTabChild();
 
-  [noscript,nostdcall,notxpcom] nsICommandManager GetCommandManager();
+  [noscript,nostdcall,notxpcom] nsCommandManager GetCommandManager();
 
   cenum TouchEventsOverride: 8 {
     /**
      * Override platform/pref default behaviour and force-disable touch events.
      */
     TOUCHEVENTS_OVERRIDE_DISABLED = 0,
     /**
      * Override platform/pref default behaviour and force-enable touch events.
--- a/dom/commandhandler/nsCommandManager.cpp
+++ b/dom/commandhandler/nsCommandManager.cpp
@@ -139,27 +139,36 @@ nsCommandManager::IsCommandSupported(con
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCommandManager::IsCommandEnabled(const char* aCommandName,
                                    mozIDOMWindowProxy* aTargetWindow,
                                    bool* aResult) {
   NS_ENSURE_ARG_POINTER(aResult);
-
-  bool commandEnabled = false;
+  if (!aCommandName) {
+    *aResult = false;
+    return NS_OK;
+  }
+  *aResult = IsCommandEnabled(nsDependentCString(aCommandName), aTargetWindow);
+  return NS_OK;
+}
 
+bool nsCommandManager::IsCommandEnabled(const nsCString& aCommandName,
+                                        mozIDOMWindowProxy* aTargetWindow) {
   nsCOMPtr<nsIController> controller;
-  GetControllerForCommand(aCommandName, aTargetWindow,
+  GetControllerForCommand(aCommandName.get(), aTargetWindow,
                           getter_AddRefs(controller));
-  if (controller) {
-    controller->IsCommandEnabled(aCommandName, &commandEnabled);
+  if (!controller) {
+    return false;
   }
-  *aResult = commandEnabled;
-  return NS_OK;
+
+  bool enabled = false;
+  controller->IsCommandEnabled(aCommandName.get(), &enabled);
+  return enabled;
 }
 
 NS_IMETHODIMP
 nsCommandManager::GetCommandState(const char* aCommandName,
                                   mozIDOMWindowProxy* aTargetWindow,
                                   nsICommandParams* aCommandParams) {
   nsCOMPtr<nsIController> controller;
   nsAutoString tValue;
--- a/dom/commandhandler/nsCommandManager.h
+++ b/dom/commandhandler/nsCommandManager.h
@@ -14,36 +14,47 @@
 #include "nsICommandManager.h"
 #include "nsPICommandUpdater.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsIController;
 template <class E>
 class nsCOMArray;
 
-class nsCommandManager : public nsICommandManager,
-                         public nsPICommandUpdater,
-                         public nsSupportsWeakReference {
+class nsCommandManager final : public nsICommandManager,
+                               public nsPICommandUpdater,
+                               public nsSupportsWeakReference {
  public:
   typedef nsTArray<nsCOMPtr<nsIObserver> > ObserverList;
 
   nsCommandManager();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsCommandManager, nsICommandManager)
 
   NS_DECL_NSICOMMANDMANAGER
   NS_DECL_NSPICOMMANDUPDATER
 
+  bool IsCommandEnabled(const nsCString& aCommandName,
+                        mozIDOMWindowProxy* aTargetWindow);
+
  protected:
   virtual ~nsCommandManager();
 
   nsresult GetControllerForCommand(const char* aCommand,
                                    mozIDOMWindowProxy* aDirectedToThisWindow,
                                    nsIController** aResult);
 
  protected:
   nsClassHashtable<nsCharPtrHashKey, ObserverList> mObserversTable;
 
   mozIDOMWindowProxy* mWindow;  // weak ptr. The window should always outlive us
 };
 
+nsCommandManager* nsICommandManager::AsCommandManager() {
+  return static_cast<nsCommandManager*>(this);
+}
+
+const nsCommandManager* nsICommandManager::AsCommandManager() const {
+  return static_cast<const nsCommandManager*>(this);
+}
+
 #endif  // nsCommandManager_h__
--- a/dom/commandhandler/nsICommandManager.idl
+++ b/dom/commandhandler/nsICommandManager.idl
@@ -4,28 +4,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsIObserver.idl"
 #include "nsICommandParams.idl"
 
 interface mozIDOMWindowProxy;
 
+%{C++
+class nsCommandManager;
+%}
+
 /*
  * nsICommandManager is an interface used to executing user-level commands,
  * and getting the state of available commands.
  *
  * Commands are identified by strings, which are documented elsewhere.
  * In addition, the list of required and optional parameters for
  * each command, that are passed in via the nsICommandParams, are
  * also documented elsewhere. (Where? Need a good location for this).
  */
- 
- 
-[scriptable, uuid(bb5a1730-d83b-4fa2-831b-35b9d5842e84)]
+
+
+[scriptable, builtinclass, uuid(bb5a1730-d83b-4fa2-831b-35b9d5842e84)]
 interface nsICommandManager : nsISupports
 {
   /*
    * Register an observer on the specified command. The observer's Observe
    * method will get called when the state (enabled/disbaled, or toggled etc)
    * of the command changes.
    *
    * You can register the same observer on multiple commmands by calling this
@@ -73,31 +77,39 @@ interface nsICommandManager : nsISupport
    * aTargetWindow is the source of command controller 
    *      (null means use focus controller)
    * On output: aCommandParams: values set by the caller filled in with
    * state from the command.
    */
   void        getCommandState(in string aCommandName,
                               in mozIDOMWindowProxy aTargetWindow,
                   /* inout */ in nsICommandParams aCommandParams);
-    
+
   /*
    * Execute the specified command.
    * The command will be executed in aTargetWindow if it is specified.
    * If aTargetWindow is null, it will go to the focused window.
    *
    * param: aCommandParams, a list of name-value pairs of command parameters,
    * may be null for parameter-less commands.
    *
    */
   [can_run_script]
   void        doCommand(in string aCommandName,
                         in nsICommandParams aCommandParams,
                         in mozIDOMWindowProxy aTargetWindow);
 
+%{C++
+  /**
+   * In order to avoid circular dependency issues, these methods are defined
+   * in nsCommandManager.h.  Consumers need to #include that header.
+   */
+  inline nsCommandManager* AsCommandManager();
+  inline const nsCommandManager* AsCommandManager() const;
+%}
 };
 
 
 /*
 
 Arguments to observers "Observe" method are as follows:
 
   void Observe(   in nsISupports aSubject,          // The nsICommandManager calling this Observer
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -6,16 +6,17 @@
 
 #include "nsHTMLDocument.h"
 
 #include "nsIContentPolicy.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/dom/HTMLAllCollection.h"
 #include "mozilla/dom/FeaturePolicyUtils.h"
+#include "nsCommandManager.h"
 #include "nsCOMPtr.h"
 #include "nsGlobalWindow.h"
 #include "nsString.h"
 #include "nsPrintfCString.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsGlobalWindowInner.h"
 #include "nsIDocumentLoader.h"
@@ -2222,40 +2223,34 @@ void nsHTMLDocument::SetDesignMode(
   bool editableMode = HasFlag(NODE_IS_EDITABLE);
   if (aDesignMode.LowerCaseEqualsASCII(editableMode ? "off" : "on")) {
     SetEditableFlag(!editableMode);
 
     rv = EditingStateChanged();
   }
 }
 
-nsresult nsHTMLDocument::GetMidasCommandManager(nsICommandManager** aCmdMgr) {
-  // initialize return value
-  NS_ENSURE_ARG_POINTER(aCmdMgr);
-
+nsCommandManager* nsHTMLDocument::GetMidasCommandManager() {
   // check if we have it cached
   if (mMidasCommandManager) {
-    NS_ADDREF(*aCmdMgr = mMidasCommandManager);
-    return NS_OK;
+    return mMidasCommandManager;
   }
 
-  *aCmdMgr = nullptr;
-
   nsPIDOMWindowOuter* window = GetWindow();
-  if (!window) return NS_ERROR_FAILURE;
+  if (!window) {
+    return nullptr;
+  }
 
   nsIDocShell* docshell = window->GetDocShell();
-  if (!docshell) return NS_ERROR_FAILURE;
+  if (!docshell) {
+    return nullptr;
+  }
 
   mMidasCommandManager = docshell->GetCommandManager();
-  if (!mMidasCommandManager) return NS_ERROR_FAILURE;
-
-  NS_ADDREF(*aCmdMgr = mMidasCommandManager);
-
-  return NS_OK;
+  return mMidasCommandManager;
 }
 
 struct MidasCommand {
   const char* incomingCommandString;
   const char* internalCommandString;
   const char* internalParamString;
   bool useNewParam;
   bool convertToBoolean;
@@ -2538,19 +2533,18 @@ bool nsHTMLDocument::ExecCommand(const n
   }
 
   if (isPaste && !nsContentUtils::PrincipalHasPermission(
                      &aSubjectPrincipal, nsGkAtoms::clipboardRead)) {
     return false;
   }
 
   // get command manager and dispatch command to our window if it's acceptable
-  nsCOMPtr<nsICommandManager> cmdMgr;
-  GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  if (!cmdMgr) {
+  RefPtr<nsCommandManager> commandManager = GetMidasCommandManager();
+  if (!commandManager) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow();
   if (!window) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
@@ -2569,24 +2563,22 @@ bool nsHTMLDocument::ExecCommand(const n
       !paramStr.LowerCaseEqualsLiteral("div") &&
       !paramStr.LowerCaseEqualsLiteral("p") &&
       !paramStr.LowerCaseEqualsLiteral("br")) {
     // Invalid value
     return false;
   }
 
   // Return false for disabled commands (bug 760052)
-  bool enabled = false;
-  cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, &enabled);
-  if (!enabled) {
+  if (!commandManager->IsCommandEnabled(cmdToDispatch, window)) {
     return false;
   }
 
   if (!isBool && paramStr.IsEmpty()) {
-    rv = cmdMgr->DoCommand(cmdToDispatch.get(), nullptr, window);
+    rv = commandManager->DoCommand(cmdToDispatch.get(), nullptr, window);
   } else {
     // we have a command that requires a parameter, create params
     RefPtr<nsCommandParams> params = new nsCommandParams();
     if (isBool) {
       rv = params->SetBool("state_attribute", boolVal);
     } else if (cmdToDispatch.EqualsLiteral("cmd_fontFace") ||
                cmdToDispatch.EqualsLiteral("cmd_insertImageNoUI") ||
                cmdToDispatch.EqualsLiteral("cmd_insertLinkNoUI")) {
@@ -2595,17 +2587,17 @@ bool nsHTMLDocument::ExecCommand(const n
                cmdToDispatch.EqualsLiteral("cmd_insertText")) {
       rv = params->SetString("state_data", value);
     } else {
       rv = params->SetCString("state_attribute", paramStr);
     }
     if (rv.Failed()) {
       return false;
     }
-    rv = cmdMgr->DoCommand(cmdToDispatch.get(), params, window);
+    rv = commandManager->DoCommand(cmdToDispatch.get(), params, window);
   }
 
   return !rv.Failed();
 }
 
 bool nsHTMLDocument::QueryCommandEnabled(const nsAString& commandID,
                                          nsIPrincipal& aSubjectPrincipal,
                                          ErrorResult& rv) {
@@ -2628,62 +2620,58 @@ bool nsHTMLDocument::QueryCommandEnabled
   }
 
   // if editing is not on, bail
   if (!IsEditingOnAfterFlush()) {
     return false;
   }
 
   // get command manager and dispatch command to our window if it's acceptable
-  nsCOMPtr<nsICommandManager> cmdMgr;
-  GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  if (!cmdMgr) {
+  RefPtr<nsCommandManager> commandManager = GetMidasCommandManager();
+  if (!commandManager) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   nsPIDOMWindowOuter* window = GetWindow();
   if (!window) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
-  bool retval;
-  rv = cmdMgr->IsCommandEnabled(cmdToDispatch.get(), window, &retval);
-  return retval;
+  return commandManager->IsCommandEnabled(cmdToDispatch, window);
 }
 
 bool nsHTMLDocument::QueryCommandIndeterm(const nsAString& commandID,
                                           ErrorResult& rv) {
   nsAutoCString cmdToDispatch;
   if (!ConvertToMidasInternalCommand(commandID, cmdToDispatch)) {
     return false;
   }
 
   // if editing is not on, bail
   if (!IsEditingOnAfterFlush()) {
     return false;
   }
 
   // get command manager and dispatch command to our window if it's acceptable
-  nsCOMPtr<nsICommandManager> cmdMgr;
-  GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  if (!cmdMgr) {
+  RefPtr<nsCommandManager> commandManager = GetMidasCommandManager();
+  if (!commandManager) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   nsPIDOMWindowOuter* window = GetWindow();
   if (!window) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   RefPtr<nsCommandParams> params = new nsCommandParams();
-  rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, params);
+  rv = commandManager->GetCommandState(cmdToDispatch.get(), window, params);
   if (rv.Failed()) {
     return false;
   }
 
   // If command does not have a state_mixed value, this call fails and sets
   // retval to false.  This is fine -- we want to return false in that case
   // anyway (bug 738385), so we just don't throw regardless.
   return params->GetBool("state_mixed");
@@ -2699,19 +2687,18 @@ bool nsHTMLDocument::QueryCommandState(c
   }
 
   // if editing is not on, bail
   if (!IsEditingOnAfterFlush()) {
     return false;
   }
 
   // get command manager and dispatch command to our window if it's acceptable
-  nsCOMPtr<nsICommandManager> cmdMgr;
-  GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  if (!cmdMgr) {
+  RefPtr<nsCommandManager> commandManager = GetMidasCommandManager();
+  if (!commandManager) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   nsPIDOMWindowOuter* window = GetWindow();
   if (!window) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
@@ -2719,17 +2706,17 @@ bool nsHTMLDocument::QueryCommandState(c
 
   if (commandID.LowerCaseEqualsLiteral("usecss")) {
     // Per spec, state is supported for styleWithCSS but not useCSS, so we just
     // return false always.
     return false;
   }
 
   RefPtr<nsCommandParams> params = new nsCommandParams();
-  rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, params);
+  rv = commandManager->GetCommandState(cmdToDispatch.get(), window, params);
   if (rv.Failed()) {
     return false;
   }
 
   // handle alignment as a special case (possibly other commands too?)
   // Alignment is special because the external api is individual
   // commands but internally we use cmd_align with different
   // parameters.  When getting the state of this command, we need to
@@ -2787,19 +2774,18 @@ void nsHTMLDocument::QueryCommandValue(c
   }
 
   // if editing is not on, bail
   if (!IsEditingOnAfterFlush()) {
     return;
   }
 
   // get command manager and dispatch command to our window if it's acceptable
-  nsCOMPtr<nsICommandManager> cmdMgr;
-  GetMidasCommandManager(getter_AddRefs(cmdMgr));
-  if (!cmdMgr) {
+  RefPtr<nsCommandManager> commandManager = GetMidasCommandManager();
+  if (!commandManager) {
     rv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow();
   if (!window) {
     rv.Throw(NS_ERROR_FAILURE);
     return;
@@ -2812,30 +2798,30 @@ void nsHTMLDocument::QueryCommandValue(c
     rv = params->SetBool("selection_only", true);
     if (rv.Failed()) {
       return;
     }
     rv = params->SetCString("format", NS_LITERAL_CSTRING("text/html"));
     if (rv.Failed()) {
       return;
     }
-    rv = cmdMgr->DoCommand(cmdToDispatch.get(), params, window);
+    rv = commandManager->DoCommand(cmdToDispatch.get(), params, window);
     if (rv.Failed()) {
       return;
     }
     params->GetString("result", aValue);
     return;
   }
 
   rv = params->SetCString("state_attribute", paramStr);
   if (rv.Failed()) {
     return;
   }
 
-  rv = cmdMgr->GetCommandState(cmdToDispatch.get(), window, params);
+  rv = commandManager->GetCommandState(cmdToDispatch.get(), window, params);
   if (rv.Failed()) {
     return;
   }
 
   // If command does not have a state_attribute value, this call fails, and
   // aValue will wind up being the empty string.  This is fine -- we want to
   // return "" in that case anyway (bug 738385), so we just return NS_OK
   // regardless.
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -12,20 +12,20 @@
 #include "nsIHTMLDocument.h"
 #include "nsIHTMLCollection.h"
 #include "nsIScriptElement.h"
 #include "nsTArray.h"
 
 #include "PLDHashTable.h"
 #include "nsIHttpChannel.h"
 #include "nsThreadUtils.h"
-#include "nsICommandManager.h"
 #include "mozilla/dom/HTMLSharedElement.h"
 #include "mozilla/dom/BindingDeclarations.h"
 
+class nsCommandManager;
 class nsIURI;
 class nsIDocShell;
 class nsICachingChannel;
 class nsILoadGroup;
 
 namespace mozilla {
 namespace dom {
 class HTMLAllCollection;
@@ -316,19 +316,19 @@ class nsHTMLDocument : public mozilla::d
 
   bool mTooDeepWriteRecursion;
 
   bool mDisableDocWrite;
 
   bool mWarnedWidthHeight;
 
   /* Midas implementation */
-  nsresult GetMidasCommandManager(nsICommandManager** aCommandManager);
+  nsCommandManager* GetMidasCommandManager();
 
-  nsCOMPtr<nsICommandManager> mMidasCommandManager;
+  RefPtr<nsCommandManager> mMidasCommandManager;
 
   nsresult TurnEditingOff();
   // MOZ_CAN_RUN_SCRIPT_BOUNDARY because this is called from all sorts
   // of places, and I'm pretty sure the exact ExecCommand call it
   // makes cannot actually run script.
   MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult EditingStateChanged();
   void MaybeEditingStateChanged();
 
--- a/editor/composer/ComposerCommandsUpdater.cpp
+++ b/editor/composer/ComposerCommandsUpdater.cpp
@@ -5,27 +5,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ComposerCommandsUpdater.h"
 
 #include "mozilla/mozalloc.h"            // for operator new
 #include "mozilla/TransactionManager.h"  // for TransactionManager
 #include "mozilla/dom/Selection.h"
 #include "nsAString.h"
+#include "nsCommandManager.h"            // for nsCommandManager
 #include "nsComponentManagerUtils.h"     // for do_CreateInstance
 #include "nsDebug.h"                     // for NS_ENSURE_TRUE, etc
 #include "nsError.h"                     // for NS_OK, NS_ERROR_FAILURE, etc
-#include "nsICommandManager.h"           // for nsICommandManager
 #include "nsID.h"                        // for NS_GET_IID, etc
 #include "nsIDOMWindow.h"                // for nsIDOMWindow
 #include "nsIDocShell.h"                 // for nsIDocShell
 #include "nsIInterfaceRequestorUtils.h"  // for do_GetInterface
 #include "nsITransactionManager.h"       // for nsITransactionManager
 #include "nsLiteralString.h"             // for NS_LITERAL_STRING
-#include "nsPICommandUpdater.h"          // for nsPICommandUpdater
 #include "nsPIDOMWindow.h"               // for nsPIDOMWindow
 
 class nsITransaction;
 
 namespace mozilla {
 
 ComposerCommandsUpdater::ComposerCommandsUpdater()
     : mDirtyState(eStateUninitialized),
@@ -320,20 +319,17 @@ bool ComposerCommandsUpdater::SelectionI
   return domSelection->IsCollapsed();
 }
 
 already_AddRefed<nsPICommandUpdater>
 ComposerCommandsUpdater::GetCommandUpdater() {
   if (NS_WARN_IF(!mDocShell)) {
     return nullptr;
   }
-
-  nsCOMPtr<nsICommandManager> manager = mDocShell->GetCommandManager();
-  nsCOMPtr<nsPICommandUpdater> updater = do_QueryInterface(manager);
-  return updater.forget();
+  return do_AddRef(mDocShell->GetCommandManager());
 }
 
 NS_IMETHODIMP
 ComposerCommandsUpdater::GetName(nsACString& aName) {
   aName.AssignLiteral("ComposerCommandsUpdater");
   return NS_OK;
 }
 
--- a/editor/composer/nsEditingSession.cpp
+++ b/editor/composer/nsEditingSession.cpp
@@ -8,23 +8,23 @@
 
 #include "imgIContainer.h"                    // for imgIContainer, etc
 #include "mozilla/ComposerCommandsUpdater.h"  // for ComposerCommandsUpdater
 #include "mozilla/FlushType.h"                // for FlushType::Frames
 #include "mozilla/HTMLEditor.h"               // for HTMLEditor
 #include "mozilla/mozalloc.h"                 // for operator new
 #include "mozilla/PresShell.h"                // for PresShell
 #include "nsAString.h"
+#include "nsCommandManager.h"         // for nsCommandManager
 #include "nsComponentManagerUtils.h"  // for do_CreateInstance
 #include "nsContentUtils.h"
 #include "nsDebug.h"  // for NS_ENSURE_SUCCESS, etc
 #include "nsEditingSession.h"
 #include "nsError.h"               // for NS_ERROR_FAILURE, NS_OK, etc
 #include "nsIChannel.h"            // for nsIChannel
-#include "nsICommandManager.h"     // for nsICommandManager
 #include "nsIContentViewer.h"      // for nsIContentViewer
 #include "nsIController.h"         // for nsIController
 #include "nsIControllerContext.h"  // for nsIControllerContext
 #include "nsIControllers.h"        // for nsIControllers
 #include "nsID.h"                  // for NS_GET_IID, etc
 #include "nsHTMLDocument.h"        // for nsHTMLDocument
 #include "nsIDOMWindow.h"          // for nsIDOMWindow
 #include "nsIDocShell.h"           // for nsIDocShell
@@ -37,17 +37,16 @@
 #include "nsIRefreshURI.h"               // for nsIRefreshURI
 #include "nsIRequest.h"                  // for nsIRequest
 #include "nsITimer.h"                    // for nsITimer, etc
 #include "nsITransactionManager.h"       // for nsITransactionManager
 #include "nsIWeakReference.h"            // for nsISupportsWeakReference, etc
 #include "nsIWebNavigation.h"            // for nsIWebNavigation
 #include "nsIWebProgress.h"              // for nsIWebProgress, etc
 #include "nsLiteralString.h"             // for NS_LITERAL_STRING
-#include "nsPICommandUpdater.h"          // for nsPICommandUpdater
 #include "nsPIDOMWindow.h"               // for nsPIDOMWindow
 #include "nsPresContext.h"               // for nsPresContext
 #include "nsReadableUtils.h"             // for AppendUTF16toUTF8
 #include "nsStringFwd.h"                 // for nsString
 #include "mozilla/dom/Selection.h"       // for AutoHideSelectionChanges, etc
 #include "nsFrameSelection.h"            // for nsFrameSelection
 #include "nsBaseCommandController.h"     // for nsBaseCommandController
 #include "mozilla/dom/LoadURIOptionsBinding.h"
@@ -748,22 +747,18 @@ nsEditingSession::OnLocationChange(nsIWe
 
   doc->SetDocumentURI(aURI);
 
   // Notify the location-changed observer that
   //  the document URL has changed
   nsIDocShell* docShell = piWindow->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsICommandManager> commandManager = docShell->GetCommandManager();
-  nsCOMPtr<nsPICommandUpdater> commandUpdater =
-      do_QueryInterface(commandManager);
-  NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
-
-  return commandUpdater->CommandStatusChanged("obs_documentLocationChanged");
+  RefPtr<nsCommandManager> commandManager = docShell->GetCommandManager();
+  return commandManager->CommandStatusChanged("obs_documentLocationChanged");
 }
 
 /*---------------------------------------------------------------------------
 
   OnStatusChange
 
 ----------------------------------------------------------------------------*/
 NS_IMETHODIMP
--- a/editor/libeditor/HTMLEditorDocumentCommands.cpp
+++ b/editor/libeditor/HTMLEditorDocumentCommands.cpp
@@ -410,36 +410,33 @@ SetDocumentStateCommand::GetCommandState
  *    "obs_documentCreated"
  *    "obs_documentWillBeDestroyed"
  *    "obs_documentLocationChanged"
  *  Note that you can use the same command class, nsDocumentStateCommand
  *    for these or future observer commands.
  *    We check the input command param for different behavior
  *
  *  How to use:
- *  1. Get the nsICommandManager for the current editor
+ *  1. Get the nsCommandManager for the current editor
  *  2. Implement an nsIObserve object, e.g:
  *
  *    void Observe(
- *        in nsISupports aSubject, // The nsICommandManager calling this
+ *        in nsISupports aSubject, // The nsCommandManager calling this
  *                                 // Observer
  *        in string      aTopic,   // command name, e.g.:"obs_documentCreated"
  *                                 //    or "obs_documentWillBeDestroyed"
           in wstring     aData );  // ignored (set to "command_status_changed")
  *
  *  3. Add the observer by:
  *       commandManager.addObserver(observeobject, obs_documentCreated);
  *  4. In the appropriate location in editorSession, editor, or commands code,
  *     trigger the notification of this observer by something like:
  *
- *  nsCOMPtr<nsICommandManager> commandManager = mDocShell->GetCommandManager();
- *  nsCOMPtr<nsPICommandUpdater> commandUpdater =
- *    do_QueryInterface(commandManager);
- *  NS_ENSURE_TRUE(commandUpdater, NS_ERROR_FAILURE);
- *    commandUpdater->CommandStatusChanged(obs_documentCreated);
+ *  RefPtr<nsCommandManager> commandManager = mDocShell->GetCommandManager();
+ *  commandManager->CommandStatusChanged(obs_documentCreated);
  *
  *  5. Use GetCommandStateParams() to obtain state information
  *     e.g., any creation state codes when creating an editor are
  *     supplied for "obs_documentCreated" command in the
  *     "state_data" param's value
  *
  */