Bug 1540963 - Make nsIControllerCommandTable builtinclass and make its users use nsControllerCommandTable directly r=bzbarsky
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 03 Apr 2019 12:52:14 +0000
changeset 467761 d2d7393a6a90a61ce6b575005827dc9f28519245
parent 467760 b8484c4d2e849ddabf314bc425407570b219b503
child 467762 9ac99f71070b10676d5dbeda45c322f192977425
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
bugs1540963
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 1540963 - Make nsIControllerCommandTable builtinclass and make its users use nsControllerCommandTable directly r=bzbarsky `nsIControllerCommandTable` isn't implemented with JS even in comm-central nor BlueGriffon. Therefore, we can make it a builtinclass. Additionally, it's inherited only by nsControllerCommandTable. So, all users in C++ can treat the concrete class directly. Differential Revision: https://phabricator.services.mozilla.com/D25727
dom/base/nsGlobalWindowCommands.cpp
dom/base/nsGlobalWindowCommands.h
dom/base/nsGlobalWindowOuter.cpp
dom/commandhandler/nsBaseCommandController.cpp
dom/commandhandler/nsBaseCommandController.h
dom/commandhandler/nsControllerCommandTable.cpp
dom/commandhandler/nsControllerCommandTable.h
dom/commandhandler/nsIControllerCommandTable.idl
dom/html/HTMLInputElement.cpp
dom/html/HTMLTextAreaElement.cpp
editor/composer/nsEditingSession.cpp
editor/composer/nsEditingSession.h
editor/libeditor/EditorController.cpp
editor/libeditor/EditorController.h
editor/libeditor/HTMLEditorController.cpp
editor/libeditor/HTMLEditorController.h
--- a/dom/base/nsGlobalWindowCommands.cpp
+++ b/dom/base/nsGlobalWindowCommands.cpp
@@ -10,18 +10,18 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsCommandParams.h"
 #include "nsCRT.h"
 #include "nsString.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Preferences.h"
 
-#include "nsIControllerCommandTable.h"
-#include "nsICommandParams.h"
+#include "nsControllerCommandTable.h"
+#include "nsCommandParams.h"
 
 #include "nsPIDOMWindow.h"
 #include "nsIPresShell.h"
 #include "nsIDocShell.h"
 #include "nsISelectionController.h"
 #include "nsIWebNavigation.h"
 #include "nsIContentViewerEdit.h"
 #include "nsIContentViewer.h"
@@ -1018,38 +1018,38 @@ nsLookUpDictionaryCommand::DoCommandPara
 
   RegisterWindowCommands
 
 ----------------------------------------------------------------------------*/
 
 #define NS_REGISTER_ONE_COMMAND(_cmdClass, _cmdName)            \
   {                                                             \
     _cmdClass *theCmd = new _cmdClass();                        \
-    rv = inCommandTable->RegisterCommand(                       \
+    rv = aCommandTable->RegisterCommand(                        \
         _cmdName, static_cast<nsIControllerCommand *>(theCmd)); \
   }
 
 #define NS_REGISTER_FIRST_COMMAND(_cmdClass, _cmdName) \
   {                                                    \
     _cmdClass *theCmd = new _cmdClass();               \
-    rv = inCommandTable->RegisterCommand(              \
+    rv = aCommandTable->RegisterCommand(               \
         _cmdName, static_cast<nsIControllerCommand *>(theCmd));
 
 #define NS_REGISTER_NEXT_COMMAND(_cmdClass, _cmdName) \
-  rv = inCommandTable->RegisterCommand(               \
+  rv = aCommandTable->RegisterCommand(                \
       _cmdName, static_cast<nsIControllerCommand *>(theCmd));
 
 #define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName)         \
-  rv = inCommandTable->RegisterCommand(                       \
+  rv = aCommandTable->RegisterCommand(                        \
       _cmdName, static_cast<nsIControllerCommand *>(theCmd)); \
   }
 
 // static
 nsresult nsWindowCommandRegistration::RegisterWindowCommands(
-    nsIControllerCommandTable *inCommandTable) {
+    nsControllerCommandTable *aCommandTable) {
   nsresult rv;
 
   // XXX rework the macros to use a loop is possible, reducing code size
 
   // this set of commands is affected by the 'browse with caret' setting
   NS_REGISTER_FIRST_COMMAND(nsSelectMoveScrollCommand, sScrollTopString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollBottomString);
   NS_REGISTER_NEXT_COMMAND(nsSelectMoveScrollCommand, sScrollPageUpString);
--- a/dom/base/nsGlobalWindowCommands.h
+++ b/dom/base/nsGlobalWindowCommands.h
@@ -10,21 +10,22 @@
 #include "nscore.h"
 
 namespace mozilla {
 namespace layers {
 struct KeyboardScrollAction;
 }  // namespace layers
 }  // namespace mozilla
 
-class nsIControllerCommandTable;
+class nsControllerCommandTable;
 
 class nsWindowCommandRegistration {
  public:
-  static nsresult RegisterWindowCommands(nsIControllerCommandTable* ccm);
+  static nsresult RegisterWindowCommands(
+      nsControllerCommandTable* aCommandTable);
 };
 
 class nsGlobalWindowCommands {
  public:
   typedef mozilla::layers::KeyboardScrollAction KeyboardScrollAction;
 
   /**
    * Search through nsGlobalWindowCommands to find the keyboard scrolling action
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -38,30 +38,30 @@
 #include "mozilla/dom/Timeout.h"
 #include "mozilla/dom/TimeoutHandler.h"
 #include "mozilla/dom/TimeoutManager.h"
 #include "mozilla/dom/WindowProxyHolder.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #if defined(MOZ_WIDGET_ANDROID)
 #  include "mozilla/dom/WindowOrientationObserver.h"
 #endif
+#include "nsBaseCommandController.h"
 #include "nsError.h"
 #include "nsISizeOfEventTarget.h"
 #include "nsDOMJSUtils.h"
 #include "nsArrayUtils.h"
 #include "nsDOMWindowList.h"
 #include "mozilla/dom/WakeLock.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPermissionManager.h"
 #include "nsIScriptContext.h"
 #include "nsIScriptTimeoutHandler.h"
 #include "nsITimeoutHandler.h"
-#include "nsIController.h"
 #include "nsISlowScriptDebug.h"
 #include "nsWindowMemoryReporter.h"
 #include "nsWindowSizes.h"
 #include "WindowNamedPropertiesHandler.h"
 #include "nsFrameSelection.h"
 #include "nsNetUtil.h"
 #include "nsVariant.h"
 #include "nsPrintfCString.h"
@@ -140,17 +140,16 @@
 #include "nsComputedDOMStyle.h"
 #include "nsDOMCID.h"
 #include "nsDOMWindowUtils.h"
 #include "nsIWindowWatcher.h"
 #include "nsPIWindowWatcher.h"
 #include "nsIContentViewer.h"
 #include "nsIScriptError.h"
 #include "nsIControllers.h"
-#include "nsIControllerContext.h"
 #include "nsGlobalWindowCommands.h"
 #include "nsQueryObject.h"
 #include "nsContentUtils.h"
 #include "nsCSSProps.h"
 #include "nsIURIFixup.h"
 #include "nsIURIMutator.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStateManager.h"
@@ -3190,32 +3189,25 @@ nsIControllers* nsGlobalWindowOuter::Get
   if (!mControllers) {
     mControllers = new nsXULControllers();
     if (!mControllers) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
     // Add in the default controller
-    nsCOMPtr<nsIController> controller =
+    RefPtr<nsBaseCommandController> commandController =
         nsBaseCommandController::CreateWindowController();
-    if (!controller) {
+    if (!commandController) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
-    mControllers->InsertControllerAt(0, controller);
-    nsCOMPtr<nsIControllerContext> controllerContext =
-        do_QueryInterface(controller);
-    if (!controllerContext) {
-      aError.Throw(NS_ERROR_FAILURE);
-      return nullptr;
-    }
-
-    controllerContext->SetCommandContext(static_cast<nsIDOMWindow*>(this));
+    mControllers->InsertControllerAt(0, commandController);
+    commandController->SetCommandContext(static_cast<nsIDOMWindow*>(this));
   }
 
   return mControllers;
 }
 
 nsresult nsGlobalWindowOuter::GetControllers(nsIControllers** aResult) {
   FORWARD_TO_INNER(GetControllers, (aResult), NS_ERROR_UNEXPECTED);
 }
--- a/dom/commandhandler/nsBaseCommandController.cpp
+++ b/dom/commandhandler/nsBaseCommandController.cpp
@@ -24,17 +24,17 @@ NS_INTERFACE_MAP_END
 nsBaseCommandController::nsBaseCommandController()
     : mCommandContextRawPtr(nullptr) {}
 
 nsBaseCommandController::~nsBaseCommandController() {}
 
 NS_IMETHODIMP
 nsBaseCommandController::Init(nsIControllerCommandTable* aCommandTable) {
   if (aCommandTable) {
-    mCommandTable = aCommandTable;
+    mCommandTable = aCommandTable->AsControllerCommandTable();
   } else {
     mCommandTable = new nsControllerCommandTable();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -62,17 +62,20 @@ nsBaseCommandController::GetInterface(co
   NS_ENSURE_ARG_POINTER(aResult);
 
   if (NS_SUCCEEDED(QueryInterface(aIID, aResult))) {
     return NS_OK;
   }
 
   if (aIID.Equals(NS_GET_IID(nsIControllerCommandTable))) {
     if (mCommandTable) {
-      return mCommandTable->QueryInterface(aIID, aResult);
+      *aResult =
+          do_AddRef(static_cast<nsIControllerCommandTable*>(mCommandTable))
+              .take();
+      return NS_OK;
     }
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   return NS_NOINTERFACE;
 }
 
 /* =======================================================================
@@ -113,31 +116,31 @@ NS_IMETHODIMP
 nsBaseCommandController::DoCommand(const char* aCommand) {
   NS_ENSURE_ARG_POINTER(aCommand);
   NS_ENSURE_STATE(mCommandTable);
 
   nsCOMPtr<nsISupports> context = mCommandContextRawPtr;
   if (!context) {
     context = do_QueryReferent(mCommandContextWeakPtr);
   }
-  nsCOMPtr<nsIControllerCommandTable> commandTable(mCommandTable);
+  RefPtr<nsControllerCommandTable> commandTable(mCommandTable);
   return commandTable->DoCommand(aCommand, context);
 }
 
 NS_IMETHODIMP
 nsBaseCommandController::DoCommandWithParams(const char* aCommand,
                                              nsICommandParams* aParams) {
   NS_ENSURE_ARG_POINTER(aCommand);
   NS_ENSURE_STATE(mCommandTable);
 
   nsCOMPtr<nsISupports> context = mCommandContextRawPtr;
   if (!context) {
     context = do_QueryReferent(mCommandContextWeakPtr);
   }
-  nsCOMPtr<nsIControllerCommandTable> commandTable(mCommandTable);
+  RefPtr<nsControllerCommandTable> commandTable(mCommandTable);
   return commandTable->DoCommandParams(aCommand, aParams, context);
 }
 
 NS_IMETHODIMP
 nsBaseCommandController::GetCommandStateWithParams(const char* aCommand,
                                                    nsICommandParams* aParams) {
   NS_ENSURE_ARG_POINTER(aCommand);
   NS_ENSURE_STATE(mCommandTable);
@@ -159,60 +162,60 @@ nsBaseCommandController::OnEvent(const c
 
 NS_IMETHODIMP
 nsBaseCommandController::GetSupportedCommands(uint32_t* aCount,
                                               char*** aCommands) {
   NS_ENSURE_STATE(mCommandTable);
   return mCommandTable->GetSupportedCommands(aCount, aCommands);
 }
 
-typedef already_AddRefed<nsIControllerCommandTable> (*CommandTableCreatorFn)();
+typedef already_AddRefed<nsControllerCommandTable> (*CommandTableCreatorFn)();
 
-static already_AddRefed<nsIController>
+static already_AddRefed<nsBaseCommandController>
 CreateControllerWithSingletonCommandTable(CommandTableCreatorFn aCreatorFn) {
-  nsCOMPtr<nsIController> controller = new nsBaseCommandController();
+  RefPtr<nsBaseCommandController> commandController =
+      new nsBaseCommandController();
 
-  nsCOMPtr<nsIControllerCommandTable> commandTable = aCreatorFn();
-  if (!commandTable) return nullptr;
+  RefPtr<nsControllerCommandTable> commandTable = aCreatorFn();
+  if (!commandTable) {
+    return nullptr;
+  }
 
   // this is a singleton; make it immutable
   commandTable->MakeImmutable();
 
-  nsresult rv;
-  nsCOMPtr<nsIControllerContext> controllerContext =
-      do_QueryInterface(controller, &rv);
-  if (NS_FAILED(rv)) return nullptr;
+  nsresult rv = commandController->Init(commandTable);
+  if (NS_FAILED(rv)) {
+    return nullptr;
+  }
 
-  rv = controllerContext->Init(commandTable);
-  if (NS_FAILED(rv)) return nullptr;
-
-  return controller.forget();
+  return commandController.forget();
 }
 
-already_AddRefed<nsIController>
+already_AddRefed<nsBaseCommandController>
 nsBaseCommandController::CreateWindowController() {
   return CreateControllerWithSingletonCommandTable(
       nsControllerCommandTable::CreateWindowCommandTable);
 }
 
-already_AddRefed<nsIController>
+already_AddRefed<nsBaseCommandController>
 nsBaseCommandController::CreateEditorController() {
   return CreateControllerWithSingletonCommandTable(
       nsControllerCommandTable::CreateEditorCommandTable);
 }
 
-already_AddRefed<nsIController>
+already_AddRefed<nsBaseCommandController>
 nsBaseCommandController::CreateEditingController() {
   return CreateControllerWithSingletonCommandTable(
       nsControllerCommandTable::CreateEditingCommandTable);
 }
 
-already_AddRefed<nsIController>
+already_AddRefed<nsBaseCommandController>
 nsBaseCommandController::CreateHTMLEditorController() {
   return CreateControllerWithSingletonCommandTable(
       nsControllerCommandTable::CreateHTMLEditorCommandTable);
 }
 
-already_AddRefed<nsIController>
+already_AddRefed<nsBaseCommandController>
 nsBaseCommandController::CreateHTMLEditorDocStateController() {
   return CreateControllerWithSingletonCommandTable(
       nsControllerCommandTable::CreateHTMLEditorDocStateCommandTable);
 }
--- a/dom/commandhandler/nsBaseCommandController.h
+++ b/dom/commandhandler/nsBaseCommandController.h
@@ -4,45 +4,47 @@
  * 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 nsBaseCommandController_h__
 #define nsBaseCommandController_h__
 
 #include "nsIController.h"
 #include "nsIControllerContext.h"
-#include "nsIControllerCommandTable.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIWeakReferenceUtils.h"
 
+class nsControllerCommandTable;
+
 // The base editor controller is used for both text widgets, and all other text
 // and html editing
 class nsBaseCommandController : public nsIController,
                                 public nsIControllerContext,
                                 public nsIInterfaceRequestor,
                                 public nsICommandController {
  public:
   nsBaseCommandController();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTROLLER
   NS_DECL_NSICOMMANDCONTROLLER
   NS_DECL_NSICONTROLLERCONTEXT
   NS_DECL_NSIINTERFACEREQUESTOR
 
-  static already_AddRefed<nsIController> CreateWindowController();
-  static already_AddRefed<nsIController> CreateEditorController();
-  static already_AddRefed<nsIController> CreateEditingController();
-  static already_AddRefed<nsIController> CreateHTMLEditorController();
-  static already_AddRefed<nsIController> CreateHTMLEditorDocStateController();
+  static already_AddRefed<nsBaseCommandController> CreateWindowController();
+  static already_AddRefed<nsBaseCommandController> CreateEditorController();
+  static already_AddRefed<nsBaseCommandController> CreateEditingController();
+  static already_AddRefed<nsBaseCommandController> CreateHTMLEditorController();
+  static already_AddRefed<nsBaseCommandController>
+  CreateHTMLEditorDocStateController();
 
  protected:
   virtual ~nsBaseCommandController();
 
  private:
   nsWeakPtr mCommandContextWeakPtr;
   nsISupports* mCommandContextRawPtr;
 
   // Our reference to the command manager
-  nsCOMPtr<nsIControllerCommandTable> mCommandTable;
+  RefPtr<nsControllerCommandTable> mCommandTable;
 };
 
 #endif /* nsBaseCommandController_h_ */
--- a/dom/commandhandler/nsControllerCommandTable.cpp
+++ b/dom/commandhandler/nsControllerCommandTable.cpp
@@ -6,18 +6,16 @@
 
 #include "nsString.h"
 #include "nsIControllerCommand.h"
 #include "nsControllerCommandTable.h"
 #include "nsGlobalWindowCommands.h"
 #include "mozilla/EditorController.h"
 #include "mozilla/HTMLEditorController.h"
 
-nsresult NS_NewControllerCommandTable(nsIControllerCommandTable** aResult);
-
 // this value is used to size the hash table. Just a sensible upper bound
 #define NUM_COMMANDS_LENGTH 32
 
 nsControllerCommandTable::nsControllerCommandTable()
     : mCommandsTable(NUM_COMMANDS_LENGTH), mMutable(true) {}
 
 nsControllerCommandTable::~nsControllerCommandTable() {}
 
@@ -181,70 +179,58 @@ nsControllerCommandTable::GetSupportedCo
 
   for (auto iter = mCommandsTable.Iter(); !iter.Done(); iter.Next()) {
     *commands = ToNewCString(iter.Key());
     commands++;
   }
   return NS_OK;
 }
 
-typedef nsresult (*CommandTableRegistrar)(nsIControllerCommandTable*);
+typedef nsresult (*CommandTableRegistrar)(nsControllerCommandTable*);
 
-static already_AddRefed<nsIControllerCommandTable>
+static already_AddRefed<nsControllerCommandTable>
 CreateCommandTableWithCommands(CommandTableRegistrar aRegistrar) {
-  nsCOMPtr<nsIControllerCommandTable> commandTable =
+  RefPtr<nsControllerCommandTable> commandTable =
       new nsControllerCommandTable();
 
   nsresult rv = aRegistrar(commandTable);
   if (NS_FAILED(rv)) return nullptr;
 
   // we don't know here whether we're being created as an instance,
   // or a service, so we can't become immutable
 
   return commandTable.forget();
 }
 
 // static
-already_AddRefed<nsIControllerCommandTable>
+already_AddRefed<nsControllerCommandTable>
 nsControllerCommandTable::CreateEditorCommandTable() {
   return CreateCommandTableWithCommands(
       EditorController::RegisterEditorCommands);
 }
 
 // static
-already_AddRefed<nsIControllerCommandTable>
+already_AddRefed<nsControllerCommandTable>
 nsControllerCommandTable::CreateEditingCommandTable() {
   return CreateCommandTableWithCommands(
       EditorController::RegisterEditingCommands);
 }
 
 // static
-already_AddRefed<nsIControllerCommandTable>
+already_AddRefed<nsControllerCommandTable>
 nsControllerCommandTable::CreateHTMLEditorCommandTable() {
   return CreateCommandTableWithCommands(
       HTMLEditorController::RegisterHTMLEditorCommands);
 }
 
 // static
-already_AddRefed<nsIControllerCommandTable>
+already_AddRefed<nsControllerCommandTable>
 nsControllerCommandTable::CreateHTMLEditorDocStateCommandTable() {
   return CreateCommandTableWithCommands(
       HTMLEditorController::RegisterEditorDocStateCommands);
 }
 
 // static
-already_AddRefed<nsIControllerCommandTable>
+already_AddRefed<nsControllerCommandTable>
 nsControllerCommandTable::CreateWindowCommandTable() {
   return CreateCommandTableWithCommands(
       nsWindowCommandRegistration::RegisterWindowCommands);
 }
-
-nsresult NS_NewControllerCommandTable(nsIControllerCommandTable** aResult) {
-  MOZ_ASSERT(aResult != nullptr, "null ptr");
-  if (!aResult) {
-    return NS_ERROR_NULL_POINTER;
-  }
-
-  nsControllerCommandTable* newCommandTable = new nsControllerCommandTable();
-  NS_ADDREF(newCommandTable);
-  *aResult = newCommandTable;
-  return NS_OK;
-}
--- a/dom/commandhandler/nsControllerCommandTable.h
+++ b/dom/commandhandler/nsControllerCommandTable.h
@@ -16,28 +16,37 @@ class nsIControllerCommand;
 class nsControllerCommandTable final : public nsIControllerCommandTable,
                                        public nsSupportsWeakReference {
  public:
   nsControllerCommandTable();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSICONTROLLERCOMMANDTABLE
 
-  static already_AddRefed<nsIControllerCommandTable> CreateEditorCommandTable();
-  static already_AddRefed<nsIControllerCommandTable>
-  CreateEditingCommandTable();
-  static already_AddRefed<nsIControllerCommandTable>
+  static already_AddRefed<nsControllerCommandTable> CreateEditorCommandTable();
+  static already_AddRefed<nsControllerCommandTable> CreateEditingCommandTable();
+  static already_AddRefed<nsControllerCommandTable>
   CreateHTMLEditorCommandTable();
-  static already_AddRefed<nsIControllerCommandTable>
+  static already_AddRefed<nsControllerCommandTable>
   CreateHTMLEditorDocStateCommandTable();
-  static already_AddRefed<nsIControllerCommandTable> CreateWindowCommandTable();
+  static already_AddRefed<nsControllerCommandTable> CreateWindowCommandTable();
 
  protected:
   virtual ~nsControllerCommandTable();
 
   // Hash table of nsIControllerCommands, keyed by command name.
   nsInterfaceHashtable<nsCStringHashKey, nsIControllerCommand> mCommandsTable;
 
   // Are we mutable?
   bool mMutable;
 };
 
+nsControllerCommandTable*
+nsIControllerCommandTable::AsControllerCommandTable() {
+  return static_cast<nsControllerCommandTable*>(this);
+}
+
+const nsControllerCommandTable*
+nsIControllerCommandTable::AsControllerCommandTable() const {
+  return static_cast<const nsControllerCommandTable*>(this);
+}
+
 #endif  // nsControllerCommandTable_h_
--- a/dom/commandhandler/nsIControllerCommandTable.idl
+++ b/dom/commandhandler/nsIControllerCommandTable.idl
@@ -1,29 +1,33 @@
 /* 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 "nsISupports.idl"
 #include "nsIControllerCommand.idl"
 #include "nsICommandParams.idl"
 
+%{C++
+class nsControllerCommandTable;
+%}
+
 /**
  * nsIControllerCommandTable
  * 
  * An interface via which a controller can maintain a series of commands,
  * and efficiently dispatch commands to their respective handlers.
  *
  * Controllers that use an nsIControllerCommandTable should support
  * nsIInterfaceRequestor, and be able to return an interface to their
  * controller command table via getInterface().
  * 
  */
 
-[scriptable, uuid(c847f90e-b8f3-49db-a4df-8867831f2800)]
+[scriptable, builtinclass, uuid(c847f90e-b8f3-49db-a4df-8867831f2800)]
 interface nsIControllerCommandTable : nsISupports
 {
   /**
    * Make this command table immutable, so that commands cannot
    * be registered or unregistered. Some command tables are made
    * mutable after command registration so that they can be 
    * used as singletons.
    */
@@ -82,10 +86,19 @@ interface nsIControllerCommandTable : ns
 
   [can_run_script]
 	void    doCommandParams(in string aCommandName, in nsICommandParams aParam, in nsISupports aCommandRefCon);
 
 	void    getCommandState(in string aCommandName, in nsICommandParams aParam, in nsISupports aCommandRefCon);
 
   void getSupportedCommands(out unsigned long count,
                             [array, size_is(count), retval] out string commands);
+
+%{C++
+  /**
+   * In order to avoid circular dependency issues, these methods are defined
+   * in nsControllerCommandTable.h.  Consumers need to #include that header.
+   */
+  inline nsControllerCommandTable* AsControllerCommandTable();
+  inline const nsControllerCommandTable* AsControllerCommandTable() const;
+%}
 };
 
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -23,17 +23,17 @@
 #include "nsQueryObject.h"
 
 #include "nsITextControlElement.h"
 #include "nsIRadioVisitor.h"
 #include "InputType.h"
 
 #include "HTMLFormSubmissionConstants.h"
 #include "mozilla/Telemetry.h"
-#include "nsIControllers.h"
+#include "nsBaseCommandController.h"
 #include "nsIStringBundle.h"
 #include "nsFocusManager.h"
 #include "nsColorControlFrame.h"
 #include "nsNumberControlFrame.h"
 #include "nsPIDOMWindow.h"
 #include "nsRepeatService.h"
 #include "nsContentCID.h"
 #include "nsIComponentManager.h"
@@ -104,17 +104,16 @@
 
 #include "nsIIDNService.h"
 
 #include <limits>
 
 #include "nsIColorPicker.h"
 #include "nsIStringEnumerator.h"
 #include "HTMLSplitOnSpacesTokenizer.h"
-#include "nsIController.h"
 #include "nsIMIMEInfo.h"
 #include "nsFrameSelection.h"
 #include "nsBaseCommandController.h"
 #include "nsXULControllers.h"
 
 // input type=date
 #include "js/Date.h"
 
@@ -5443,32 +5442,32 @@ nsIControllers* HTMLInputElement::GetCon
   if (IsSingleLineTextControl(false)) {
     if (!mControllers) {
       mControllers = new nsXULControllers();
       if (!mControllers) {
         aRv.Throw(NS_ERROR_FAILURE);
         return nullptr;
       }
 
-      nsCOMPtr<nsIController> controller =
+      RefPtr<nsBaseCommandController> commandController =
           nsBaseCommandController::CreateEditorController();
-      if (!controller) {
+      if (!commandController) {
         aRv.Throw(NS_ERROR_FAILURE);
         return nullptr;
       }
 
-      mControllers->AppendController(controller);
-
-      controller = nsBaseCommandController::CreateEditingController();
-      if (!controller) {
+      mControllers->AppendController(commandController);
+
+      commandController = nsBaseCommandController::CreateEditingController();
+      if (!commandController) {
         aRv.Throw(NS_ERROR_FAILURE);
         return nullptr;
       }
 
-      mControllers->AppendController(controller);
+      mControllers->AppendController(commandController);
     }
   }
 
   return mControllers;
 }
 
 nsresult HTMLInputElement::GetControllers(nsIControllers** aResult) {
   NS_ENSURE_ARG_POINTER(aResult);
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -11,16 +11,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/HTMLFormSubmission.h"
 #include "mozilla/dom/HTMLTextAreaElementBinding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/MappedDeclarations.h"
 #include "mozilla/MouseEvents.h"
 #include "nsAttrValueInlines.h"
+#include "nsBaseCommandController.h"
 #include "nsContentCID.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsError.h"
 #include "nsFocusManager.h"
 #include "nsIComponentManager.h"
 #include "nsIConstraintValidation.h"
 #include "nsIControllers.h"
 #include "mozilla/dom/Document.h"
@@ -34,17 +35,16 @@
 #include "nsLinebreakConverter.h"
 #include "nsMappedAttributes.h"
 #include "nsPIDOMWindow.h"
 #include "nsPresContext.h"
 #include "mozilla/PresState.h"
 #include "nsReadableUtils.h"
 #include "nsStyleConsts.h"
 #include "nsTextEditorState.h"
-#include "nsIController.h"
 #include "nsBaseCommandController.h"
 #include "nsXULControllers.h"
 
 #define NS_NO_CONTENT_DISPATCH (1 << 0)
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(TextArea)
 
 namespace mozilla {
@@ -553,32 +553,32 @@ bool HTMLTextAreaElement::IsDoneAddingCh
 nsIControllers* HTMLTextAreaElement::GetControllers(ErrorResult& aError) {
   if (!mControllers) {
     mControllers = new nsXULControllers();
     if (!mControllers) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
-    nsCOMPtr<nsIController> controller =
+    RefPtr<nsBaseCommandController> commandController =
         nsBaseCommandController::CreateEditorController();
-    if (!controller) {
+    if (!commandController) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
-    mControllers->AppendController(controller);
+    mControllers->AppendController(commandController);
 
-    controller = nsBaseCommandController::CreateEditingController();
-    if (!controller) {
+    commandController = nsBaseCommandController::CreateEditingController();
+    if (!commandController) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
     }
 
-    mControllers->AppendController(controller);
+    mControllers->AppendController(commandController);
   }
 
   return mControllers;
 }
 
 nsresult HTMLTextAreaElement::GetControllers(nsIControllers** aResult) {
   NS_ENSURE_ARG_POINTER(aResult);
 
--- a/editor/composer/nsEditingSession.cpp
+++ b/editor/composer/nsEditingSession.cpp
@@ -8,26 +8,25 @@
 
 #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 "nsBaseCommandController.h"  // for nsBaseCommandController
 #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 "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
 #include "mozilla/dom/Document.h"  // for Document
 #include "nsIDocumentStateListener.h"
 #include "nsIEditor.h"                   // for nsIEditor
@@ -1066,27 +1065,27 @@ nsresult nsEditingSession::SetupEditorCo
 
   nsCOMPtr<nsIControllers> controllers;
   nsresult rv = piWindow->GetControllers(getter_AddRefs(controllers));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // We only have to create each singleton controller once
   // We know this has happened once we have a controllerId value
   if (!*aControllerId) {
-    nsCOMPtr<nsIController> controller = aControllerCreatorFn();
-    NS_ENSURE_TRUE(controller, NS_ERROR_FAILURE);
+    RefPtr<nsBaseCommandController> commandController = aControllerCreatorFn();
+    NS_ENSURE_TRUE(commandController, NS_ERROR_FAILURE);
 
     // We must insert at head of the list to be sure our
     //   controller is found before other implementations
     //   (e.g., not-implemented versions by browser)
-    rv = controllers->InsertControllerAt(0, controller);
+    rv = controllers->InsertControllerAt(0, commandController);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Remember the ID for the controller
-    rv = controllers->GetControllerId(controller, aControllerId);
+    rv = controllers->GetControllerId(commandController, aControllerId);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Set the context
   return SetContextOnControllerById(controllers, aContext, *aControllerId);
 }
 
 /*---------------------------------------------------------------------------
--- a/editor/composer/nsEditingSession.h
+++ b/editor/composer/nsEditingSession.h
@@ -18,16 +18,17 @@
 
 #ifndef __gen_nsIEditingSession_h__
 #  include "nsIEditingSession.h"  // for NS_DECL_NSIEDITINGSESSION, etc
 #endif
 
 #include "nsString.h"  // for nsCString
 
 class mozIDOMWindowProxy;
+class nsBaseCommandController;
 class nsIDOMWindow;
 class nsISupports;
 class nsITimer;
 class nsIChannel;
 class nsIControllers;
 class nsIDocShell;
 class nsIEditor;
 class nsIWebProgress;
@@ -50,17 +51,17 @@ class nsEditingSession final : public ns
   NS_DECL_NSIWEBPROGRESSLISTENER
 
   // nsIEditingSession
   NS_DECL_NSIEDITINGSESSION
 
  protected:
   virtual ~nsEditingSession();
 
-  typedef already_AddRefed<nsIController> (*ControllerCreatorFn)();
+  typedef already_AddRefed<nsBaseCommandController> (*ControllerCreatorFn)();
 
   nsresult SetupEditorCommandController(
       ControllerCreatorFn aControllerCreatorFn, mozIDOMWindowProxy* aWindow,
       nsISupports* aContext, uint32_t* aControllerId);
 
   nsresult SetContextOnControllerById(nsIControllers* aControllers,
                                       nsISupports* aContext, uint32_t aID);
 
--- a/editor/libeditor/EditorController.cpp
+++ b/editor/libeditor/EditorController.cpp
@@ -2,19 +2,19 @@
 /* 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/EditorController.h"
 
 #include "EditorCommands.h"
 #include "mozilla/mozalloc.h"
+#include "nsControllerCommandTable.h"
 #include "nsDebug.h"
 #include "nsError.h"
-#include "nsIControllerCommandTable.h"
 
 class nsIControllerCommand;
 
 namespace mozilla {
 
 #define NS_REGISTER_ONE_COMMAND(_cmdClass, _cmdName)           \
   {                                                            \
     _cmdClass* theCmd = new _cmdClass();                       \
@@ -36,17 +36,17 @@ namespace mozilla {
 
 #define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName)                         \
   aCommandTable->RegisterCommand(_cmdName,                                    \
                                  static_cast<nsIControllerCommand*>(theCmd)); \
   }
 
 // static
 nsresult EditorController::RegisterEditingCommands(
-    nsIControllerCommandTable* aCommandTable) {
+    nsControllerCommandTable* aCommandTable) {
   // now register all our commands
   // These are commands that will be used in text widgets, and in composer
 
   NS_REGISTER_ONE_COMMAND(UndoCommand, "cmd_undo");
   NS_REGISTER_ONE_COMMAND(RedoCommand, "cmd_redo");
 
   NS_REGISTER_ONE_COMMAND(CutCommand, "cmd_cut");
   NS_REGISTER_ONE_COMMAND(CutOrDeleteCommand, "cmd_cutOrDelete");
@@ -74,17 +74,17 @@ nsresult EditorController::RegisterEditi
   NS_REGISTER_ONE_COMMAND(InsertLineBreakCommand, "cmd_insertLineBreak");
   NS_REGISTER_ONE_COMMAND(PasteQuotationCommand, "cmd_pasteQuote");
 
   return NS_OK;
 }
 
 // static
 nsresult EditorController::RegisterEditorCommands(
-    nsIControllerCommandTable* aCommandTable) {
+    nsControllerCommandTable* aCommandTable) {
   // These are commands that will be used in text widgets only.
 
   NS_REGISTER_FIRST_COMMAND(SelectionMoveCommands, "cmd_scrollTop");
   NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_scrollBottom");
   NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveTop");
   NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_moveBottom");
   NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectTop");
   NS_REGISTER_NEXT_COMMAND(SelectionMoveCommands, "cmd_selectBottom");
--- a/editor/libeditor/EditorController.h
+++ b/editor/libeditor/EditorController.h
@@ -3,27 +3,27 @@
  * 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_EditorController_h
 #define mozilla_EditorController_h
 
 #include "nscore.h"
 
-class nsIControllerCommandTable;
+class nsControllerCommandTable;
 
 namespace mozilla {
 
 // the editor controller is used for both text widgets, and basic text editing
 // commands in composer. The refCon that gets passed to its commands is an
 // nsIEditor.
 
 class EditorController final {
  public:
   static nsresult RegisterEditorCommands(
-      nsIControllerCommandTable* aCommandTable);
+      nsControllerCommandTable* aCommandTable);
   static nsresult RegisterEditingCommands(
-      nsIControllerCommandTable* aCommandTable);
+      nsControllerCommandTable* aCommandTable);
 };
 
 }  // namespace mozilla
 
 #endif  // #ifndef mozilla_EditorController_h
--- a/editor/libeditor/HTMLEditorController.cpp
+++ b/editor/libeditor/HTMLEditorController.cpp
@@ -2,63 +2,61 @@
 /* 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/HTMLEditorController.h"
 
 #include "mozilla/HTMLEditorCommands.h"  // for StyleUpdatingCommand, etc
 #include "mozilla/mozalloc.h"            // for operator new
+#include "nsControllerCommandTable.h"    // for nsControllerCommandTable
 #include "nsError.h"                     // for NS_OK
 #include "nsGkAtoms.h"                   // for nsGkAtoms, nsGkAtoms::a, etc
-#include "nsIControllerCommandTable.h"   // for nsIControllerCommandTable
-
-class nsIControllerCommand;
 
 namespace mozilla {
 
 #define NS_REGISTER_ONE_COMMAND(_cmdClass, _cmdName)            \
   {                                                             \
     _cmdClass *theCmd = new _cmdClass();                        \
-    inCommandTable->RegisterCommand(                            \
+    aCommandTable->RegisterCommand(                             \
         _cmdName, static_cast<nsIControllerCommand *>(theCmd)); \
   }
 
 #define NS_REGISTER_FIRST_COMMAND(_cmdClass, _cmdName) \
   {                                                    \
     _cmdClass *theCmd = new _cmdClass();               \
-    inCommandTable->RegisterCommand(                   \
+    aCommandTable->RegisterCommand(                    \
         _cmdName, static_cast<nsIControllerCommand *>(theCmd));
 
 #define NS_REGISTER_NEXT_COMMAND(_cmdClass, _cmdName) \
-  inCommandTable->RegisterCommand(                    \
-      _cmdName, static_cast<nsIControllerCommand *>(theCmd));
+  aCommandTable->RegisterCommand(_cmdName,            \
+                                 static_cast<nsIControllerCommand *>(theCmd));
 
-#define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName)         \
-  inCommandTable->RegisterCommand(                            \
-      _cmdName, static_cast<nsIControllerCommand *>(theCmd)); \
+#define NS_REGISTER_LAST_COMMAND(_cmdClass, _cmdName)                          \
+  aCommandTable->RegisterCommand(_cmdName,                                     \
+                                 static_cast<nsIControllerCommand *>(theCmd)); \
   }
 
 #define NS_REGISTER_STYLE_COMMAND(_cmdClass, _cmdName, _styleTag) \
   {                                                               \
     _cmdClass *theCmd = new _cmdClass(_styleTag);                 \
-    inCommandTable->RegisterCommand(                              \
+    aCommandTable->RegisterCommand(                               \
         _cmdName, static_cast<nsIControllerCommand *>(theCmd));   \
   }
 
 #define NS_REGISTER_TAG_COMMAND(_cmdClass, _cmdName, _tagName)  \
   {                                                             \
     _cmdClass *theCmd = new _cmdClass(_tagName);                \
-    inCommandTable->RegisterCommand(                            \
+    aCommandTable->RegisterCommand(                             \
         _cmdName, static_cast<nsIControllerCommand *>(theCmd)); \
   }
 
 // static
 nsresult HTMLEditorController::RegisterEditorDocStateCommands(
-    nsIControllerCommandTable *inCommandTable) {
+    nsControllerCommandTable *aCommandTable) {
   // observer commands for document state
   NS_REGISTER_FIRST_COMMAND(DocumentStateCommand, "obs_documentCreated")
   NS_REGISTER_NEXT_COMMAND(DocumentStateCommand, "obs_documentWillBeDestroyed")
   NS_REGISTER_LAST_COMMAND(DocumentStateCommand, "obs_documentLocationChanged")
 
   // commands that may get or change state
   NS_REGISTER_FIRST_COMMAND(SetDocumentStateCommand, "cmd_setDocumentModified")
   NS_REGISTER_NEXT_COMMAND(SetDocumentStateCommand, "cmd_setDocumentUseCSS")
@@ -72,17 +70,17 @@ nsresult HTMLEditorController::RegisterE
   NS_REGISTER_LAST_COMMAND(SetDocumentStateCommand,
                            "cmd_enableAbsolutePositionEditing")
 
   return NS_OK;
 }
 
 // static
 nsresult HTMLEditorController::RegisterHTMLEditorCommands(
-    nsIControllerCommandTable *inCommandTable) {
+    nsControllerCommandTable *aCommandTable) {
   // Edit menu
   NS_REGISTER_ONE_COMMAND(PasteNoFormattingCommand, "cmd_pasteNoFormatting");
 
   // indent/outdent
   NS_REGISTER_ONE_COMMAND(IndentCommand, "cmd_indent");
   NS_REGISTER_ONE_COMMAND(OutdentCommand, "cmd_outdent");
 
   // Styles
--- a/editor/libeditor/HTMLEditorController.h
+++ b/editor/libeditor/HTMLEditorController.h
@@ -3,23 +3,23 @@
  * 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_HTMLEditorController_h__
 #define mozilla_HTMLEditorController_h__
 
 #include "nscore.h"  // for nsresult
 
-class nsIControllerCommandTable;
+class nsControllerCommandTable;
 
 namespace mozilla {
 
 class HTMLEditorController final {
  public:
   static nsresult RegisterEditorDocStateCommands(
-      nsIControllerCommandTable* inCommandTable);
+      nsControllerCommandTable* aCommandTable);
   static nsresult RegisterHTMLEditorCommands(
-      nsIControllerCommandTable* inCommandTable);
+      nsControllerCommandTable* aCommandTable);
 };
 
 }  // namespace mozilla
 
 #endif /* mozllla_HTMLEditorController_h__ */