Bug 1546839 - part 4: Make all editor command classes use Command instead of command name r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 30 Apr 2019 04:24:49 +0000
changeset 530697 1e0e71568ab6fd65275cd079acd26d6e05a75ac7
parent 530696 1970145268164e7308c02934865393d62f42a383
child 530698 8551820a482fd3cadd64b498514020480ff0e275
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1546839
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 1546839 - part 4: Make all editor command classes use Command instead of command name r=smaug `strcmp` may be slow due to checking null character. Therefore, internal methods of them should use command as far as possible. This patch makes them take/use `Command` instead of `const char*`. Differential Revision: https://phabricator.services.mozilla.com/D29174
editor/libeditor/EditorCommands.cpp
editor/libeditor/EditorCommands.h
editor/libeditor/HTMLEditorCommands.cpp
editor/libeditor/HTMLEditorDocumentCommands.cpp
--- a/editor/libeditor/EditorCommands.cpp
+++ b/editor/libeditor/EditorCommands.cpp
@@ -36,31 +36,33 @@ NS_IMETHODIMP
 EditorCommand::IsCommandEnabled(const char* aCommandName,
                                 nsISupports* aCommandRefCon, bool* aIsEnabled) {
   if (NS_WARN_IF(!aCommandName) || NS_WARN_IF(!aIsEnabled)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
   TextEditor* textEditor = editor ? editor->AsTextEditor() : nullptr;
-  *aIsEnabled = IsCommandEnabled(aCommandName, MOZ_KnownLive(textEditor));
+  *aIsEnabled = IsCommandEnabled(GetInternalCommand(aCommandName),
+                                 MOZ_KnownLive(textEditor));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 EditorCommand::DoCommand(const char* aCommandName,
                          nsISupports* aCommandRefCon) {
   if (NS_WARN_IF(!aCommandName) || NS_WARN_IF(!aCommandRefCon)) {
     return NS_ERROR_INVALID_ARG;
   }
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
   if (NS_WARN_IF(!editor)) {
     return NS_ERROR_INVALID_ARG;
   }
-  nsresult rv = DoCommand(aCommandName, MOZ_KnownLive(*editor->AsTextEditor()));
+  nsresult rv = DoCommand(GetInternalCommand(aCommandName),
+                          MOZ_KnownLive(*editor->AsTextEditor()));
   NS_WARNING_ASSERTION(
       NS_SUCCEEDED(rv),
       "Failed to do command from nsIControllerCommand::DoCommand()");
   return rv;
 }
 
 NS_IMETHODIMP
 EditorCommand::DoCommandParams(const char* aCommandName,
@@ -68,316 +70,323 @@ EditorCommand::DoCommandParams(const cha
                                nsISupports* aCommandRefCon) {
   if (NS_WARN_IF(!aCommandName) || NS_WARN_IF(!aCommandRefCon)) {
     return NS_ERROR_INVALID_ARG;
   }
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
   if (NS_WARN_IF(!editor)) {
     return NS_ERROR_INVALID_ARG;
   }
-  nsresult rv =
-      DoCommandParams(aCommandName, MOZ_KnownLive(aParams->AsCommandParams()),
-                      MOZ_KnownLive(*editor->AsTextEditor()));
+  Command command;
+  nsCommandParams* params = aParams->AsCommandParams();
+  if (params) {
+    nsAutoString value;
+    params->GetString(aCommandName, value);
+    command = GetInternalCommand(aCommandName, value);
+  } else {
+    command = GetInternalCommand(aCommandName);
+  }
+  nsresult rv = DoCommandParams(command, MOZ_KnownLive(params),
+                                MOZ_KnownLive(*editor->AsTextEditor()));
   NS_WARNING_ASSERTION(
       NS_SUCCEEDED(rv),
       "Failed to do command from nsIControllerCommand::DoCommandParams()");
   return rv;
 }
 
 NS_IMETHODIMP
 EditorCommand::GetCommandStateParams(const char* aCommandName,
                                      nsICommandParams* aParams,
                                      nsISupports* aCommandRefCon) {
   if (NS_WARN_IF(!aCommandName) || NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
   if (editor) {
-    return GetCommandStateParams(
-        aCommandName, MOZ_KnownLive(*aParams->AsCommandParams()),
-        MOZ_KnownLive(editor->AsTextEditor()), nullptr);
+    return GetCommandStateParams(GetInternalCommand(aCommandName),
+                                 MOZ_KnownLive(*aParams->AsCommandParams()),
+                                 MOZ_KnownLive(editor->AsTextEditor()),
+                                 nullptr);
   }
   nsCOMPtr<nsIEditingSession> editingSession =
       do_QueryInterface(aCommandRefCon);
   if (editingSession) {
-    return GetCommandStateParams(aCommandName,
+    return GetCommandStateParams(GetInternalCommand(aCommandName),
                                  MOZ_KnownLive(*aParams->AsCommandParams()),
                                  nullptr, editingSession);
   }
-  return GetCommandStateParams(aCommandName,
+  return GetCommandStateParams(GetInternalCommand(aCommandName),
                                MOZ_KnownLive(*aParams->AsCommandParams()),
                                nullptr, nullptr);
 }
 
 /******************************************************************************
  * mozilla::UndoCommand
  ******************************************************************************/
 
 StaticRefPtr<UndoCommand> UndoCommand::sInstance;
 
-bool UndoCommand::IsCommandEnabled(const char* aCommandName,
+bool UndoCommand::IsCommandEnabled(Command aCommand,
                                    TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable() && aTextEditor->CanUndo();
 }
 
-nsresult UndoCommand::DoCommand(const char* aCommandName,
+nsresult UndoCommand::DoCommand(Command aCommand,
                                 TextEditor& aTextEditor) const {
   return aTextEditor.Undo(1);
 }
 
-nsresult UndoCommand::DoCommandParams(const char* aCommandName,
+nsresult UndoCommand::DoCommandParams(Command aCommand,
                                       nsCommandParams* aParams,
                                       TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult UndoCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::RedoCommand
  ******************************************************************************/
 
 StaticRefPtr<RedoCommand> RedoCommand::sInstance;
 
-bool RedoCommand::IsCommandEnabled(const char* aCommandName,
+bool RedoCommand::IsCommandEnabled(Command aCommand,
                                    TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable() && aTextEditor->CanRedo();
 }
 
-nsresult RedoCommand::DoCommand(const char* aCommandName,
+nsresult RedoCommand::DoCommand(Command aCommand,
                                 TextEditor& aTextEditor) const {
   return aTextEditor.Redo(1);
 }
 
-nsresult RedoCommand::DoCommandParams(const char* aCommandName,
+nsresult RedoCommand::DoCommandParams(Command aCommand,
                                       nsCommandParams* aParams,
                                       TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult RedoCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::CutCommand
  ******************************************************************************/
 
 StaticRefPtr<CutCommand> CutCommand::sInstance;
 
-bool CutCommand::IsCommandEnabled(const char* aCommandName,
+bool CutCommand::IsCommandEnabled(Command aCommand,
                                   TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable() && aTextEditor->CanCut();
 }
 
-nsresult CutCommand::DoCommand(const char* aCommandName,
+nsresult CutCommand::DoCommand(Command aCommand,
                                TextEditor& aTextEditor) const {
   return aTextEditor.Cut();
 }
 
-nsresult CutCommand::DoCommandParams(const char* aCommandName,
-                                     nsCommandParams* aParams,
+nsresult CutCommand::DoCommandParams(Command aCommand, nsCommandParams* aParams,
                                      TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult CutCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::CutOrDeleteCommand
  ******************************************************************************/
 
 StaticRefPtr<CutOrDeleteCommand> CutOrDeleteCommand::sInstance;
 
-bool CutOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
+bool CutOrDeleteCommand::IsCommandEnabled(Command aCommand,
                                           TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult CutOrDeleteCommand::DoCommand(const char* aCommandName,
+nsresult CutOrDeleteCommand::DoCommand(Command aCommand,
                                        TextEditor& aTextEditor) const {
   dom::Selection* selection = aTextEditor.GetSelection();
   if (selection && selection->IsCollapsed()) {
     nsresult rv = aTextEditor.DeleteSelectionAsAction(nsIEditor::eNext,
                                                       nsIEditor::eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
   return aTextEditor.Cut();
 }
 
-nsresult CutOrDeleteCommand::DoCommandParams(const char* aCommandName,
+nsresult CutOrDeleteCommand::DoCommandParams(Command aCommand,
                                              nsCommandParams* aParams,
                                              TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult CutOrDeleteCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::CopyCommand
  ******************************************************************************/
 
 StaticRefPtr<CopyCommand> CopyCommand::sInstance;
 
-bool CopyCommand::IsCommandEnabled(const char* aCommandName,
+bool CopyCommand::IsCommandEnabled(Command aCommand,
                                    TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->CanCopy();
 }
 
-nsresult CopyCommand::DoCommand(const char* aCommandName,
+nsresult CopyCommand::DoCommand(Command aCommand,
                                 TextEditor& aTextEditor) const {
   return aTextEditor.Copy();
 }
 
-nsresult CopyCommand::DoCommandParams(const char* aCommandName,
+nsresult CopyCommand::DoCommandParams(Command aCommand,
                                       nsCommandParams* aParams,
                                       TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult CopyCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::CopyOrDeleteCommand
  ******************************************************************************/
 
 StaticRefPtr<CopyOrDeleteCommand> CopyOrDeleteCommand::sInstance;
 
-bool CopyOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
+bool CopyOrDeleteCommand::IsCommandEnabled(Command aCommand,
                                            TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult CopyOrDeleteCommand::DoCommand(const char* aCommandName,
+nsresult CopyOrDeleteCommand::DoCommand(Command aCommand,
                                         TextEditor& aTextEditor) const {
   dom::Selection* selection = aTextEditor.GetSelection();
   if (selection && selection->IsCollapsed()) {
     nsresult rv = aTextEditor.DeleteSelectionAsAction(nsIEditor::eNextWord,
                                                       nsIEditor::eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
   return aTextEditor.Copy();
 }
 
-nsresult CopyOrDeleteCommand::DoCommandParams(const char* aCommandName,
+nsresult CopyOrDeleteCommand::DoCommandParams(Command aCommand,
                                               nsCommandParams* aParams,
                                               TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult CopyOrDeleteCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::PasteCommand
  ******************************************************************************/
 
 StaticRefPtr<PasteCommand> PasteCommand::sInstance;
 
-bool PasteCommand::IsCommandEnabled(const char* aCommandName,
+bool PasteCommand::IsCommandEnabled(Command aCommand,
                                     TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable() &&
          aTextEditor->CanPaste(nsIClipboard::kGlobalClipboard);
 }
 
-nsresult PasteCommand::DoCommand(const char* aCommandName,
+nsresult PasteCommand::DoCommand(Command aCommand,
                                  TextEditor& aTextEditor) const {
   return aTextEditor.PasteAsAction(nsIClipboard::kGlobalClipboard, true);
 }
 
-nsresult PasteCommand::DoCommandParams(const char* aCommandName,
+nsresult PasteCommand::DoCommandParams(Command aCommand,
                                        nsCommandParams* aParams,
                                        TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult PasteCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::PasteTransferableCommand
  ******************************************************************************/
 
 StaticRefPtr<PasteTransferableCommand> PasteTransferableCommand::sInstance;
 
-bool PasteTransferableCommand::IsCommandEnabled(const char* aCommandName,
+bool PasteTransferableCommand::IsCommandEnabled(Command aCommand,
                                                 TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable() &&
          aTextEditor->CanPasteTransferable(nullptr);
 }
 
-nsresult PasteTransferableCommand::DoCommand(const char* aCommandName,
+nsresult PasteTransferableCommand::DoCommand(Command aCommand,
                                              TextEditor& aTextEditor) const {
   return NS_ERROR_FAILURE;
 }
 
 nsresult PasteTransferableCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
   if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsCOMPtr<nsISupports> supports = aParams->GetISupports("transferable");
   if (NS_WARN_IF(!supports)) {
     return NS_ERROR_FAILURE;
   }
@@ -392,17 +401,17 @@ nsresult PasteTransferableCommand::DoCom
   nsresult rv = aTextEditor.PasteTransferable(trans);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult PasteTransferableCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   if (NS_WARN_IF(!aTextEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsCOMPtr<nsISupports> supports = aParams.GetISupports("transferable");
   if (NS_WARN_IF(!supports)) {
     return NS_ERROR_FAILURE;
@@ -420,209 +429,221 @@ nsresult PasteTransferableCommand::GetCo
 
 /******************************************************************************
  * mozilla::SwitchTextDirectionCommand
  ******************************************************************************/
 
 StaticRefPtr<SwitchTextDirectionCommand> SwitchTextDirectionCommand::sInstance;
 
 bool SwitchTextDirectionCommand::IsCommandEnabled(
-    const char* aCommandName, TextEditor* aTextEditor) const {
+    Command aCommand, TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult SwitchTextDirectionCommand::DoCommand(const char* aCommandName,
+nsresult SwitchTextDirectionCommand::DoCommand(Command aCommand,
                                                TextEditor& aTextEditor) const {
   return aTextEditor.ToggleTextDirection();
 }
 
 nsresult SwitchTextDirectionCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult SwitchTextDirectionCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::DeleteCommand
  ******************************************************************************/
 
 StaticRefPtr<DeleteCommand> DeleteCommand::sInstance;
 
-bool DeleteCommand::IsCommandEnabled(const char* aCommandName,
+bool DeleteCommand::IsCommandEnabled(Command aCommand,
                                      TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   // We can generally delete whenever the selection is editable.  However,
   // cmd_delete doesn't make sense if the selection is collapsed because it's
   // directionless, which is the same condition under which we can't cut.
   bool isEnabled = aTextEditor->IsSelectionEditable();
 
-  if (!nsCRT::strcmp("cmd_delete", aCommandName) && isEnabled) {
+  if (aCommand == Command::Delete && isEnabled) {
     return aTextEditor->CanDelete();
   }
   return isEnabled;
 }
 
-nsresult DeleteCommand::DoCommand(const char* aCommandName,
+nsresult DeleteCommand::DoCommand(Command aCommand,
                                   TextEditor& aTextEditor) const {
   nsIEditor::EDirection deleteDir = nsIEditor::eNone;
-  if (!strcmp("cmd_delete", aCommandName)) {
-    // Really this should probably be eNone, but it only makes a difference if
-    // the selection is collapsed, and then this command is disabled.  So let's
-    // keep it as it always was to avoid breaking things.
-    deleteDir = nsIEditor::ePrevious;
-  } else if (!strcmp("cmd_deleteCharForward", aCommandName)) {
-    deleteDir = nsIEditor::eNext;
-  } else if (!strcmp("cmd_deleteCharBackward", aCommandName)) {
-    deleteDir = nsIEditor::ePrevious;
-  } else if (!strcmp("cmd_deleteWordBackward", aCommandName)) {
-    deleteDir = nsIEditor::ePreviousWord;
-  } else if (!strcmp("cmd_deleteWordForward", aCommandName)) {
-    deleteDir = nsIEditor::eNextWord;
-  } else if (!strcmp("cmd_deleteToBeginningOfLine", aCommandName)) {
-    deleteDir = nsIEditor::eToBeginningOfLine;
-  } else if (!strcmp("cmd_deleteToEndOfLine", aCommandName)) {
-    deleteDir = nsIEditor::eToEndOfLine;
-  } else {
-    MOZ_CRASH("Unrecognized nsDeleteCommand");
+  switch (aCommand) {
+    case Command::Delete:
+      // Really this should probably be eNone, but it only makes a difference
+      // if the selection is collapsed, and then this command is disabled.  So
+      // let's keep it as it always was to avoid breaking things.
+      deleteDir = nsIEditor::ePrevious;
+      break;
+    case Command::DeleteCharForward:
+      deleteDir = nsIEditor::eNext;
+      break;
+    case Command::DeleteCharBackward:
+      deleteDir = nsIEditor::ePrevious;
+      break;
+    case Command::DeleteWordBackward:
+      deleteDir = nsIEditor::ePreviousWord;
+      break;
+    case Command::DeleteWordForward:
+      deleteDir = nsIEditor::eNextWord;
+      break;
+    case Command::DeleteToBeginningOfLine:
+      deleteDir = nsIEditor::eToBeginningOfLine;
+      break;
+    case Command::DeleteToEndOfLine:
+      deleteDir = nsIEditor::eToEndOfLine;
+      break;
+    default:
+      MOZ_CRASH("Unrecognized nsDeleteCommand");
   }
   nsresult rv =
       aTextEditor.DeleteSelectionAsAction(deleteDir, nsIEditor::eStrip);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-nsresult DeleteCommand::DoCommandParams(const char* aCommandName,
+nsresult DeleteCommand::DoCommandParams(Command aCommand,
                                         nsCommandParams* aParams,
                                         TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult DeleteCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::SelectAllCommand
  ******************************************************************************/
 
 StaticRefPtr<SelectAllCommand> SelectAllCommand::sInstance;
 
-bool SelectAllCommand::IsCommandEnabled(const char* aCommandName,
+bool SelectAllCommand::IsCommandEnabled(Command aCommand,
                                         TextEditor* aTextEditor) const {
   // You can always select all, unless the selection is editable,
   // and the editable region is empty!
   if (!aTextEditor) {
     return true;
   }
 
   // You can select all if there is an editor which is non-empty
   bool isEmpty = false;
   if (NS_WARN_IF(NS_FAILED(aTextEditor->IsEmpty(&isEmpty)))) {
     return false;
   }
   return !isEmpty;
 }
 
-nsresult SelectAllCommand::DoCommand(const char* aCommandName,
+nsresult SelectAllCommand::DoCommand(Command aCommand,
                                      TextEditor& aTextEditor) const {
   return aTextEditor.SelectAll();
 }
 
-nsresult SelectAllCommand::DoCommandParams(const char* aCommandName,
+nsresult SelectAllCommand::DoCommandParams(Command aCommand,
                                            nsCommandParams* aParams,
                                            TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult SelectAllCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::SelectionMoveCommands
  ******************************************************************************/
 
 StaticRefPtr<SelectionMoveCommands> SelectionMoveCommands::sInstance;
 
-bool SelectionMoveCommands::IsCommandEnabled(const char* aCommandName,
+bool SelectionMoveCommands::IsCommandEnabled(Command aCommand,
                                              TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
 static const struct ScrollCommand {
-  const char* reverseScroll;
-  const char* forwardScroll;
+  Command mReverseScroll;
+  Command mForwardScroll;
   nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
-} scrollCommands[] = {{"cmd_scrollTop", "cmd_scrollBottom",
+} scrollCommands[] = {{Command::ScrollTop, Command::ScrollBottom,
                        &nsISelectionController::CompleteScroll},
-                      {"cmd_scrollPageUp", "cmd_scrollPageDown",
+                      {Command::ScrollPageUp, Command::ScrollPageDown,
                        &nsISelectionController::ScrollPage},
-                      {"cmd_scrollLineUp", "cmd_scrollLineDown",
+                      {Command::ScrollLineUp, Command::ScrollLineDown,
                        &nsISelectionController::ScrollLine}};
 
 static const struct MoveCommand {
-  const char* reverseMove;
-  const char* forwardMove;
-  const char* reverseSelect;
-  const char* forwardSelect;
+  Command mReverseMove;
+  Command mForwardMove;
+  Command mReverseSelect;
+  Command mForwardSelect;
   nsresult (NS_STDCALL nsISelectionController::*move)(bool, bool);
 } moveCommands[] = {
-    {"cmd_charPrevious", "cmd_charNext", "cmd_selectCharPrevious",
-     "cmd_selectCharNext", &nsISelectionController::CharacterMove},
-    {"cmd_linePrevious", "cmd_lineNext", "cmd_selectLinePrevious",
-     "cmd_selectLineNext", &nsISelectionController::LineMove},
-    {"cmd_wordPrevious", "cmd_wordNext", "cmd_selectWordPrevious",
-     "cmd_selectWordNext", &nsISelectionController::WordMove},
-    {"cmd_beginLine", "cmd_endLine", "cmd_selectBeginLine", "cmd_selectEndLine",
-     &nsISelectionController::IntraLineMove},
-    {"cmd_movePageUp", "cmd_movePageDown", "cmd_selectPageUp",
-     "cmd_selectPageDown", &nsISelectionController::PageMove},
-    {"cmd_moveTop", "cmd_moveBottom", "cmd_selectTop", "cmd_selectBottom",
-     &nsISelectionController::CompleteMove}};
+    {Command::CharPrevious, Command::CharNext, Command::SelectCharPrevious,
+     Command::SelectCharNext, &nsISelectionController::CharacterMove},
+    {Command::LinePrevious, Command::LineNext, Command::SelectLinePrevious,
+     Command::SelectLineNext, &nsISelectionController::LineMove},
+    {Command::WordPrevious, Command::WordNext, Command::SelectWordPrevious,
+     Command::SelectWordNext, &nsISelectionController::WordMove},
+    {Command::BeginLine, Command::EndLine, Command::SelectBeginLine,
+     Command::SelectEndLine, &nsISelectionController::IntraLineMove},
+    {Command::MovePageUp, Command::MovePageDown, Command::SelectPageUp,
+     Command::SelectPageDown, &nsISelectionController::PageMove},
+    {Command::MoveTop, Command::MoveBottom, Command::SelectTop,
+     Command::SelectBottom, &nsISelectionController::CompleteMove}};
 
 static const struct PhysicalCommand {
-  const char* move;
-  const char* select;
+  Command mMove;
+  Command mSelect;
   int16_t direction;
   int16_t amount;
 } physicalCommands[] = {
-    {"cmd_moveLeft", "cmd_selectLeft", nsISelectionController::MOVE_LEFT, 0},
-    {"cmd_moveRight", "cmd_selectRight", nsISelectionController::MOVE_RIGHT, 0},
-    {"cmd_moveUp", "cmd_selectUp", nsISelectionController::MOVE_UP, 0},
-    {"cmd_moveDown", "cmd_selectDown", nsISelectionController::MOVE_DOWN, 0},
-    {"cmd_moveLeft2", "cmd_selectLeft2", nsISelectionController::MOVE_LEFT, 1},
-    {"cmd_moveRight2", "cmd_selectRight2", nsISelectionController::MOVE_RIGHT,
-     1},
-    {"cmd_moveUp2", "cmd_selectUp2", nsISelectionController::MOVE_UP, 1},
-    {"cmd_moveDown2", "cmd_selectDown2", nsISelectionController::MOVE_DOWN, 1}};
+    {Command::MoveLeft, Command::SelectLeft, nsISelectionController::MOVE_LEFT,
+     0},
+    {Command::MoveRight, Command::SelectRight,
+     nsISelectionController::MOVE_RIGHT, 0},
+    {Command::MoveUp, Command::SelectUp, nsISelectionController::MOVE_UP, 0},
+    {Command::MoveDown, Command::SelectDown, nsISelectionController::MOVE_DOWN,
+     0},
+    {Command::MoveLeft2, Command::SelectLeft2,
+     nsISelectionController::MOVE_LEFT, 1},
+    {Command::MoveRight2, Command::SelectRight2,
+     nsISelectionController::MOVE_RIGHT, 1},
+    {Command::MoveUp2, Command::SelectUp2, nsISelectionController::MOVE_UP, 1},
+    {Command::MoveDown2, Command::SelectDown2,
+     nsISelectionController::MOVE_DOWN, 1}};
 
-nsresult SelectionMoveCommands::DoCommand(const char* aCommandName,
+nsresult SelectionMoveCommands::DoCommand(Command aCommand,
                                           TextEditor& aTextEditor) const {
   RefPtr<Document> document = aTextEditor.GetDocument();
   if (document) {
     // Most of the commands below (possibly all of them) need layout to
     // be up to date.
     document->FlushPendingNotifications(FlushType::Layout);
   }
 
@@ -630,94 +651,98 @@ nsresult SelectionMoveCommands::DoComman
       aTextEditor.GetSelectionController();
   if (NS_WARN_IF(!selectionController)) {
     return NS_ERROR_FAILURE;
   }
 
   // scroll commands
   for (size_t i = 0; i < ArrayLength(scrollCommands); i++) {
     const ScrollCommand& cmd = scrollCommands[i];
-    if (!strcmp(aCommandName, cmd.reverseScroll)) {
+    if (aCommand == cmd.mReverseScroll) {
       return (selectionController->*(cmd.scroll))(false);
-    } else if (!strcmp(aCommandName, cmd.forwardScroll)) {
+    }
+    if (aCommand == cmd.mForwardScroll) {
       return (selectionController->*(cmd.scroll))(true);
     }
   }
 
   // caret movement/selection commands
   for (size_t i = 0; i < ArrayLength(moveCommands); i++) {
     const MoveCommand& cmd = moveCommands[i];
-    if (!strcmp(aCommandName, cmd.reverseMove)) {
+    if (aCommand == cmd.mReverseMove) {
       return (selectionController->*(cmd.move))(false, false);
-    } else if (!strcmp(aCommandName, cmd.forwardMove)) {
+    }
+    if (aCommand == cmd.mForwardMove) {
       return (selectionController->*(cmd.move))(true, false);
-    } else if (!strcmp(aCommandName, cmd.reverseSelect)) {
+    }
+    if (aCommand == cmd.mReverseSelect) {
       return (selectionController->*(cmd.move))(false, true);
-    } else if (!strcmp(aCommandName, cmd.forwardSelect)) {
+    }
+    if (aCommand == cmd.mForwardSelect) {
       return (selectionController->*(cmd.move))(true, true);
     }
   }
 
   // physical-direction movement/selection
   for (size_t i = 0; i < ArrayLength(physicalCommands); i++) {
     const PhysicalCommand& cmd = physicalCommands[i];
-    if (!strcmp(aCommandName, cmd.move)) {
+    if (aCommand == cmd.mMove) {
       return selectionController->PhysicalMove(cmd.direction, cmd.amount,
                                                false);
-    } else if (!strcmp(aCommandName, cmd.select)) {
+    }
+    if (aCommand == cmd.mSelect) {
       return selectionController->PhysicalMove(cmd.direction, cmd.amount, true);
     }
   }
 
   return NS_ERROR_FAILURE;
 }
 
-nsresult SelectionMoveCommands::DoCommandParams(const char* aCommandName,
+nsresult SelectionMoveCommands::DoCommandParams(Command aCommand,
                                                 nsCommandParams* aParams,
                                                 TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult SelectionMoveCommands::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::InsertPlaintextCommand
  ******************************************************************************/
 
 StaticRefPtr<InsertPlaintextCommand> InsertPlaintextCommand::sInstance;
 
-bool InsertPlaintextCommand::IsCommandEnabled(const char* aCommandName,
+bool InsertPlaintextCommand::IsCommandEnabled(Command aCommand,
                                               TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult InsertPlaintextCommand::DoCommand(const char* aCommandName,
+nsresult InsertPlaintextCommand::DoCommand(Command aCommand,
                                            TextEditor& aTextEditor) const {
   // XXX InsertTextAsAction() is not same as OnInputText().  However, other
   //     commands to insert line break or paragraph separator use OnInput*().
   //     According to the semantics of those methods, using *AsAction() is
   //     better, however, this may not cause two or more placeholder
   //     transactions to the top transaction since its name may not be
   //     nsGkAtoms::TypingTxnName.
   DebugOnly<nsresult> rv = aTextEditor.InsertTextAsAction(EmptyString());
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert empty string");
   return NS_OK;
 }
 
 nsresult InsertPlaintextCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
   if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // Get text to insert from command params
   nsAutoString text;
   nsresult rv = aParams->GetString(STATE_DATA, text);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -731,127 +756,125 @@ nsresult InsertPlaintextCommand::DoComma
   //     transactions to the top transaction since its name may not be
   //     nsGkAtoms::TypingTxnName.
   rv = aTextEditor.InsertTextAsAction(text);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert the text");
   return NS_OK;
 }
 
 nsresult InsertPlaintextCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::InsertParagraphCommand
  ******************************************************************************/
 
 StaticRefPtr<InsertParagraphCommand> InsertParagraphCommand::sInstance;
 
-bool InsertParagraphCommand::IsCommandEnabled(const char* aCommandName,
+bool InsertParagraphCommand::IsCommandEnabled(Command aCommand,
                                               TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult InsertParagraphCommand::DoCommand(const char* aCommandName,
+nsresult InsertParagraphCommand::DoCommand(Command aCommand,
                                            TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;  // Do nothing for now.
   }
   return htmlEditor->InsertParagraphSeparatorAsAction();
 }
 
 nsresult InsertParagraphCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult InsertParagraphCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::InsertLineBreakCommand
  ******************************************************************************/
 
 StaticRefPtr<InsertLineBreakCommand> InsertLineBreakCommand::sInstance;
 
-bool InsertLineBreakCommand::IsCommandEnabled(const char* aCommandName,
+bool InsertLineBreakCommand::IsCommandEnabled(Command aCommand,
                                               TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult InsertLineBreakCommand::DoCommand(const char* aCommandName,
+nsresult InsertLineBreakCommand::DoCommand(Command aCommand,
                                            TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_ERROR_FAILURE;
   }
   return htmlEditor->InsertLineBreakAsAction();
 }
 
 nsresult InsertLineBreakCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult InsertLineBreakCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::PasteQuotationCommand
  ******************************************************************************/
 
 StaticRefPtr<PasteQuotationCommand> PasteQuotationCommand::sInstance;
 
-bool PasteQuotationCommand::IsCommandEnabled(const char* aCommandName,
+bool PasteQuotationCommand::IsCommandEnabled(Command aCommand,
                                              TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return !aTextEditor->IsSingleLineEditor() &&
          aTextEditor->CanPaste(nsIClipboard::kGlobalClipboard);
 }
 
-nsresult PasteQuotationCommand::DoCommand(const char* aCommandName,
+nsresult PasteQuotationCommand::DoCommand(Command aCommand,
                                           TextEditor& aTextEditor) const {
   nsresult rv = aTextEditor.PasteAsQuotationAsAction(
       nsIClipboard::kGlobalClipboard, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-nsresult PasteQuotationCommand::DoCommandParams(const char* aCommandName,
+nsresult PasteQuotationCommand::DoCommandParams(Command aCommand,
                                                 nsCommandParams* aParams,
                                                 TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult PasteQuotationCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   if (!aTextEditor) {
     return NS_OK;
   }
   aParams.SetBool(STATE_ENABLED,
                   aTextEditor->CanPaste(nsIClipboard::kGlobalClipboard));
   return NS_OK;
 }
--- a/editor/libeditor/EditorCommands.h
+++ b/editor/libeditor/EditorCommands.h
@@ -46,63 +46,60 @@ class EditorCommand : public nsIControll
                              nsICommandParams* aParams,
                              nsISupports* aCommandRefCon) final;
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   NS_IMETHOD GetCommandStateParams(const char* aCommandName,
                                    nsICommandParams* aParams,
                                    nsISupports* aCommandRefCon) final;
 
   MOZ_CAN_RUN_SCRIPT
-  virtual bool IsCommandEnabled(const char* aCommandName,
+  virtual bool IsCommandEnabled(Command aCommand,
                                 TextEditor* aTextEditor) const = 0;
   MOZ_CAN_RUN_SCRIPT
-  virtual nsresult DoCommand(const char* aCommandName,
+  virtual nsresult DoCommand(Command aCommand,
                              TextEditor& aTextEditor) const = 0;
   MOZ_CAN_RUN_SCRIPT
-  virtual nsresult DoCommandParams(const char* aCommandName,
-                                   nsCommandParams* aParams,
+  virtual nsresult DoCommandParams(Command aCommand, nsCommandParams* aParams,
                                    TextEditor& aTextEditor) const = 0;
   /**
    * @param aTextEditor         If the context is an editor, should be set to
    *                            it.  Otherwise, nullptr.
    * @param aEditingSession     If the context is an editing session, should be
    *                            set to it.  This usually occurs if editor has
    *                            not been created yet during initialization.
    *                            Otherwise, nullptr.
    */
   MOZ_CAN_RUN_SCRIPT
   virtual nsresult GetCommandStateParams(
-      const char* aCommandName, nsCommandParams& aParams,
-      TextEditor* aTextEditor, nsIEditingSession* aEditingSession) const = 0;
+      Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
+      nsIEditingSession* aEditingSession) const = 0;
 
  protected:
   EditorCommand() = default;
   virtual ~EditorCommand() = default;
 };
 
-#define NS_DECL_EDITOR_COMMAND_METHODS(_cmd)                             \
- public:                                                                 \
-  MOZ_CAN_RUN_SCRIPT                                                     \
-  virtual bool IsCommandEnabled(const char* aCommandName,                \
-                                TextEditor* aTextEditor) const final;    \
-  using EditorCommand::IsCommandEnabled;                                 \
-  MOZ_CAN_RUN_SCRIPT                                                     \
-  virtual nsresult DoCommand(const char* aCommandName,                   \
-                             TextEditor& aTextEditor) const final;       \
-  using EditorCommand::DoCommand;                                        \
-  MOZ_CAN_RUN_SCRIPT                                                     \
-  virtual nsresult DoCommandParams(const char* aCommandName,             \
-                                   nsCommandParams* aParams,             \
-                                   TextEditor& aTextEditor) const final; \
-  using EditorCommand::DoCommandParams;                                  \
-  MOZ_CAN_RUN_SCRIPT                                                     \
-  virtual nsresult GetCommandStateParams(                                \
-      const char* aCommandName, nsCommandParams& aParams,                \
-      TextEditor* aTextEditor, nsIEditingSession* aEditingSession)       \
-      const final;                                                       \
+#define NS_DECL_EDITOR_COMMAND_METHODS(_cmd)                                   \
+ public:                                                                       \
+  MOZ_CAN_RUN_SCRIPT                                                           \
+  virtual bool IsCommandEnabled(Command aCommand, TextEditor* aTextEditor)     \
+      const final;                                                             \
+  using EditorCommand::IsCommandEnabled;                                       \
+  MOZ_CAN_RUN_SCRIPT                                                           \
+  virtual nsresult DoCommand(Command aCommand, TextEditor& aTextEditor)        \
+      const final;                                                             \
+  using EditorCommand::DoCommand;                                              \
+  MOZ_CAN_RUN_SCRIPT                                                           \
+  virtual nsresult DoCommandParams(Command aCommand, nsCommandParams* aParams, \
+                                   TextEditor& aTextEditor) const final;       \
+  using EditorCommand::DoCommandParams;                                        \
+  MOZ_CAN_RUN_SCRIPT                                                           \
+  virtual nsresult GetCommandStateParams(                                      \
+      Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,     \
+      nsIEditingSession* aEditingSession) const final;                         \
   using EditorCommand::GetCommandStateParams;
 
 #define NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(_cmd) \
  public:                                                   \
   static _cmd* GetInstance() {                             \
     if (!sInstance) {                                      \
       sInstance = new _cmd();                              \
     }                                                      \
@@ -155,63 +152,79 @@ NS_DECL_EDITOR_COMMAND(PasteQuotationCom
 class StateUpdatingCommandBase : public EditorCommand {
  public:
   NS_INLINE_DECL_REFCOUNTING_INHERITED(StateUpdatingCommandBase, EditorCommand)
 
   NS_DECL_EDITOR_COMMAND_METHODS(StateUpdatingCommandBase)
 
  protected:
   StateUpdatingCommandBase() = default;
-  virtual ~StateUpdatingCommandBase() { sTagNameTable.Clear(); }
+  virtual ~StateUpdatingCommandBase() = default;
 
   // get the current state (on or off) for this style or block format
   MOZ_CAN_RUN_SCRIPT
   virtual nsresult GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
                                    nsCommandParams& aParams) const = 0;
 
   // add/remove the style
   MOZ_CAN_RUN_SCRIPT
   virtual nsresult ToggleState(nsAtom* aTagName,
                                HTMLEditor* aHTMLEditor) const = 0;
 
-  static already_AddRefed<nsAtom> TagName(const char* aCommandName) {
-    MOZ_DIAGNOSTIC_ASSERT(aCommandName);
-    if (NS_WARN_IF(!aCommandName)) {
-      return nullptr;
+  static nsAtom* GetTagName(Command aCommand) {
+    switch (aCommand) {
+      case Command::FormatBold:
+        return nsGkAtoms::b;
+      case Command::FormatItalic:
+        return nsGkAtoms::i;
+      case Command::FormatUnderline:
+        return nsGkAtoms::u;
+      case Command::FormatTeletypeText:
+        return nsGkAtoms::tt;
+      case Command::FormatStrikeThrough:
+        return nsGkAtoms::strike;
+      case Command::FormatSuperscript:
+        return nsGkAtoms::sup;
+      case Command::FormatSubscript:
+        return nsGkAtoms::sub;
+      case Command::FormatNoBreak:
+        return nsGkAtoms::nobr;
+      case Command::FormatEmphasis:
+        return nsGkAtoms::em;
+      case Command::FormatStrong:
+        return nsGkAtoms::strong;
+      case Command::FormatCitation:
+        return nsGkAtoms::cite;
+      case Command::FormatAbbreviation:
+        return nsGkAtoms::abbr;
+      case Command::FormatAcronym:
+        return nsGkAtoms::acronym;
+      case Command::FormatCode:
+        return nsGkAtoms::code;
+      case Command::FormatSample:
+        return nsGkAtoms::samp;
+      case Command::FormatVariable:
+        return nsGkAtoms::var;
+      case Command::FormatRemoveLink:
+        return nsGkAtoms::href;
+      case Command::InsertOrderedList:
+        return nsGkAtoms::ol;
+      case Command::InsertUnorderedList:
+        return nsGkAtoms::ul;
+      case Command::InsertDefinitionTerm:
+        return nsGkAtoms::dt;
+      case Command::InsertDefinitionDetails:
+        return nsGkAtoms::dd;
+      case Command::FormatAbsolutePosition:
+        return nsGkAtoms::_empty;
+      default:
+        return nullptr;
     }
-    if (!sTagNameTable.Count()) {
-      sTagNameTable.Put("cmd_bold", nsGkAtoms::b);
-      sTagNameTable.Put("cmd_italic", nsGkAtoms::i);
-      sTagNameTable.Put("cmd_underline", nsGkAtoms::u);
-      sTagNameTable.Put("cmd_tt", nsGkAtoms::tt);
-      sTagNameTable.Put("cmd_strikethrough", nsGkAtoms::strike);
-      sTagNameTable.Put("cmd_superscript", nsGkAtoms::sup);
-      sTagNameTable.Put("cmd_subscript", nsGkAtoms::sub);
-      sTagNameTable.Put("cmd_nobreak", nsGkAtoms::nobr);
-      sTagNameTable.Put("cmd_em", nsGkAtoms::em);
-      sTagNameTable.Put("cmd_strong", nsGkAtoms::strong);
-      sTagNameTable.Put("cmd_cite", nsGkAtoms::cite);
-      sTagNameTable.Put("cmd_abbr", nsGkAtoms::abbr);
-      sTagNameTable.Put("cmd_acronym", nsGkAtoms::acronym);
-      sTagNameTable.Put("cmd_code", nsGkAtoms::code);
-      sTagNameTable.Put("cmd_samp", nsGkAtoms::samp);
-      sTagNameTable.Put("cmd_var", nsGkAtoms::var);
-      sTagNameTable.Put("cmd_removeLinks", nsGkAtoms::href);
-      sTagNameTable.Put("cmd_ol", nsGkAtoms::ol);
-      sTagNameTable.Put("cmd_ul", nsGkAtoms::ul);
-      sTagNameTable.Put("cmd_dt", nsGkAtoms::dt);
-      sTagNameTable.Put("cmd_dd", nsGkAtoms::dd);
-      sTagNameTable.Put("cmd_absPos", nsGkAtoms::_empty);
-    }
-    RefPtr<nsAtom> tagName = sTagNameTable.Get(aCommandName);
-    MOZ_DIAGNOSTIC_ASSERT(tagName);
-    return tagName.forget();
   }
-
-  static nsRefPtrHashtable<nsCharPtrHashKey, nsAtom> sTagNameTable;
+  friend class InsertTagCommand;  // for allowing it to access GetTagName()
 };
 
 // Shared class for the various style updating commands like bold, italics etc.
 // Suitable for commands whose state is either 'on' or 'off'.
 class StyleUpdatingCommand final : public StateUpdatingCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(StyleUpdatingCommand)
 
@@ -233,34 +246,30 @@ class InsertTagCommand final : public Ed
  public:
   NS_INLINE_DECL_REFCOUNTING_INHERITED(InsertTagCommand, EditorCommand)
 
   NS_DECL_EDITOR_COMMAND_METHODS(InsertTagCommand)
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(InsertTagCommand)
 
  protected:
   InsertTagCommand() = default;
-  virtual ~InsertTagCommand() { sTagNameTable.Clear(); }
+  virtual ~InsertTagCommand() = default;
 
-  static already_AddRefed<nsAtom> TagName(const char* aCommandName) {
-    MOZ_DIAGNOSTIC_ASSERT(aCommandName);
-    if (NS_WARN_IF(!aCommandName)) {
-      return nullptr;
+  static nsAtom* GetTagName(Command aCommand) {
+    switch (aCommand) {
+      case Command::InsertLink:
+        return nsGkAtoms::a;
+      case Command::InsertImage:
+        return nsGkAtoms::img;
+      case Command::InsertHorizontalRule:
+        return nsGkAtoms::hr;
+      default:
+        return StateUpdatingCommandBase::GetTagName(aCommand);
     }
-    if (!sTagNameTable.Count()) {
-      sTagNameTable.Put("cmd_insertLinkNoUI", nsGkAtoms::a);
-      sTagNameTable.Put("cmd_insertImageNoUI", nsGkAtoms::img);
-      sTagNameTable.Put("cmd_insertHR", nsGkAtoms::hr);
-    }
-    RefPtr<nsAtom> tagName = sTagNameTable.Get(aCommandName);
-    MOZ_DIAGNOSTIC_ASSERT(tagName);
-    return tagName.forget();
   }
-
-  static nsRefPtrHashtable<nsCharPtrHashKey, nsAtom> sTagNameTable;
 };
 
 class ListCommand final : public StateUpdatingCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(ListCommand)
 
  protected:
   ListCommand() = default;
--- a/editor/libeditor/HTMLEditorCommands.cpp
+++ b/editor/libeditor/HTMLEditorCommands.cpp
@@ -6,20 +6,20 @@
 #include "mozilla/EditorCommands.h"
 
 #include "mozilla/Assertions.h"  // for MOZ_ASSERT, etc
 #include "mozilla/EditorBase.h"  // for EditorBase
 #include "mozilla/ErrorResult.h"
 #include "mozilla/HTMLEditor.h"  // for HTMLEditor
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
+#include "nsAtom.h"                   // for nsAtom, nsStaticAtom, etc
 #include "nsCommandParams.h"          // for nsCommandParams, etc
 #include "nsComponentManagerUtils.h"  // for do_CreateInstance
 #include "nsGkAtoms.h"                // for nsGkAtoms, nsGkAtoms::font, etc
-#include "nsAtom.h"                   // for nsAtom, etc
 #include "nsIClipboard.h"             // for nsIClipboard, etc
 #include "nsIEditingSession.h"
 #include "nsLiteralString.h"  // for NS_LITERAL_STRING
 #include "nsReadableUtils.h"  // for EmptyString
 #include "nsString.h"         // for nsAutoString, nsString, etc
 #include "nsStringFwd.h"      // for nsString
 
 class nsISupports;
@@ -41,114 +41,110 @@ static nsresult GetListState(HTMLEditor*
 #define STATE_END "state_end"
 #define STATE_ATTRIBUTE "state_attribute"
 #define STATE_DATA "state_data"
 
 /*****************************************************************************
  * mozilla::StateUpdatingCommandBase
  *****************************************************************************/
 
-nsRefPtrHashtable<nsCharPtrHashKey, nsAtom>
-    StateUpdatingCommandBase::sTagNameTable;
-
-bool StateUpdatingCommandBase::IsCommandEnabled(const char* aCommandName,
+bool StateUpdatingCommandBase::IsCommandEnabled(Command aCommand,
                                                 TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   if (!aTextEditor->IsSelectionEditable()) {
     return false;
   }
-  if (!strcmp(aCommandName, "cmd_absPos")) {
+  if (aCommand == Command::FormatAbsolutePosition) {
     HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
     return htmlEditor && htmlEditor->IsAbsolutePositionEditorEnabled();
   }
   return true;
 }
 
-nsresult StateUpdatingCommandBase::DoCommand(const char* aCommandName,
+nsresult StateUpdatingCommandBase::DoCommand(Command aCommand,
                                              TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
-  RefPtr<nsAtom> tagName = TagName(aCommandName);
+  nsAtom* tagName = GetTagName(aCommand);
   if (NS_WARN_IF(!tagName)) {
     return NS_ERROR_UNEXPECTED;
   }
-  return ToggleState(tagName, MOZ_KnownLive(htmlEditor));
+  return ToggleState(MOZ_KnownLive(tagName), MOZ_KnownLive(htmlEditor));
 }
 
 nsresult StateUpdatingCommandBase::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult StateUpdatingCommandBase::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   if (!aTextEditor) {
     return NS_OK;
   }
   HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
-  RefPtr<nsAtom> tagName = TagName(aCommandName);
+  nsAtom* tagName = GetTagName(aCommand);
   if (NS_WARN_IF(!tagName)) {
     return NS_ERROR_UNEXPECTED;
   }
-  return GetCurrentState(tagName, MOZ_KnownLive(htmlEditor), aParams);
+  return GetCurrentState(MOZ_KnownLive(tagName), MOZ_KnownLive(htmlEditor),
+                         aParams);
 }
 
 /*****************************************************************************
  * mozilla::PasteNoFormattingCommand
  *****************************************************************************/
 
 StaticRefPtr<PasteNoFormattingCommand> PasteNoFormattingCommand::sInstance;
 
-bool PasteNoFormattingCommand::IsCommandEnabled(const char* aCommandName,
+bool PasteNoFormattingCommand::IsCommandEnabled(Command aCommand,
                                                 TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
 
   // This command is only implemented by nsIHTMLEditor, since
   //  pasting in a plaintext editor automatically only supplies
   //  "unformatted" text
   HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
   if (!htmlEditor) {
     return false;
   }
   return htmlEditor->CanPaste(nsIClipboard::kGlobalClipboard);
 }
 
-nsresult PasteNoFormattingCommand::DoCommand(const char* aCommandName,
+nsresult PasteNoFormattingCommand::DoCommand(Command aCommand,
                                              TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   // Known live because we hold a ref above in "editor"
   return MOZ_KnownLive(htmlEditor)
       ->PasteNoFormatting(nsIClipboard::kGlobalClipboard);
 }
 
 nsresult PasteNoFormattingCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult PasteNoFormattingCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::StyleUpdatingCommand
  *****************************************************************************/
 
 StaticRefPtr<StyleUpdatingCommand> StyleUpdatingCommand::sInstance;
 
@@ -367,17 +363,17 @@ nsresult ListItemCommand::ToggleState(ns
 }
 
 /*****************************************************************************
  * mozilla::RemoveListCommand
  *****************************************************************************/
 
 StaticRefPtr<RemoveListCommand> RemoveListCommand::sInstance;
 
-bool RemoveListCommand::IsCommandEnabled(const char* aCommandName,
+bool RemoveListCommand::IsCommandEnabled(Command aCommand,
                                          TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
 
   if (!aTextEditor->IsSelectionEditable()) {
     return false;
   }
@@ -392,140 +388,140 @@ bool RemoveListCommand::IsCommandEnabled
   nsAutoString localName;
   nsresult rv = GetListState(MOZ_KnownLive(htmlEditor), &bMixed, localName);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
   return bMixed || !localName.IsEmpty();
 }
 
-nsresult RemoveListCommand::DoCommand(const char* aCommandName,
+nsresult RemoveListCommand::DoCommand(Command aCommand,
                                       TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   // This removes any list type
   return htmlEditor->RemoveList(EmptyString());
 }
 
-nsresult RemoveListCommand::DoCommandParams(const char* aCommandName,
+nsresult RemoveListCommand::DoCommandParams(Command aCommand,
                                             nsCommandParams* aParams,
                                             TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult RemoveListCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::IndentCommand
  *****************************************************************************/
 
 StaticRefPtr<IndentCommand> IndentCommand::sInstance;
 
-bool IndentCommand::IsCommandEnabled(const char* aCommandName,
+bool IndentCommand::IsCommandEnabled(Command aCommand,
                                      TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult IndentCommand::DoCommand(const char* aCommandName,
+nsresult IndentCommand::DoCommand(Command aCommand,
                                   TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   nsresult rv = htmlEditor->IndentAsAction();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-nsresult IndentCommand::DoCommandParams(const char* aCommandName,
+nsresult IndentCommand::DoCommandParams(Command aCommand,
                                         nsCommandParams* aParams,
                                         TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult IndentCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::OutdentCommand
  *****************************************************************************/
 
 StaticRefPtr<OutdentCommand> OutdentCommand::sInstance;
 
-bool OutdentCommand::IsCommandEnabled(const char* aCommandName,
+bool OutdentCommand::IsCommandEnabled(Command aCommand,
                                       TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult OutdentCommand::DoCommand(const char* aCommandName,
+nsresult OutdentCommand::DoCommand(Command aCommand,
                                    TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   nsresult rv = htmlEditor->OutdentAsAction();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-nsresult OutdentCommand::DoCommandParams(const char* aCommandName,
+nsresult OutdentCommand::DoCommandParams(Command aCommand,
                                          nsCommandParams* aParams,
                                          TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult OutdentCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::MultiStateCommandBase
  *****************************************************************************/
 
-bool MultiStateCommandBase::IsCommandEnabled(const char* aCommandName,
+bool MultiStateCommandBase::IsCommandEnabled(Command aCommand,
                                              TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   // should be disabled sometimes, like if the current selection is an image
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult MultiStateCommandBase::DoCommand(const char* aCommandName,
+nsresult MultiStateCommandBase::DoCommand(Command aCommand,
                                           TextEditor& aTextEditor) const {
   NS_WARNING(
       "who is calling MultiStateCommandBase::DoCommand (no implementation)?");
   return NS_OK;
 }
 
-nsresult MultiStateCommandBase::DoCommandParams(const char* aCommandName,
+nsresult MultiStateCommandBase::DoCommandParams(Command aCommand,
                                                 nsCommandParams* aParams,
                                                 TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   nsAutoString attribute;
@@ -537,17 +533,17 @@ nsresult MultiStateCommandBase::DoComman
     } else {
       aParams->GetString(STATE_ATTRIBUTE, attribute);
     }
   }
   return SetState(MOZ_KnownLive(htmlEditor), attribute);
 }
 
 nsresult MultiStateCommandBase::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   if (!aTextEditor) {
     return NS_OK;
   }
   HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
@@ -945,17 +941,17 @@ nsresult AbsolutePositioningCommand::Tog
 }
 
 /*****************************************************************************
  * mozilla::DecreaseZIndexCommand
  *****************************************************************************/
 
 StaticRefPtr<DecreaseZIndexCommand> DecreaseZIndexCommand::sInstance;
 
-bool DecreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
+bool DecreaseZIndexCommand::IsCommandEnabled(Command aCommand,
                                              TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
   if (!htmlEditor) {
     return false;
   }
@@ -964,220 +960,218 @@ bool DecreaseZIndexCommand::IsCommandEna
   }
   RefPtr<Element> positionedElement = htmlEditor->GetPositionedElement();
   if (!positionedElement) {
     return false;
   }
   return htmlEditor->GetZIndex(*positionedElement) > 0;
 }
 
-nsresult DecreaseZIndexCommand::DoCommand(const char* aCommandName,
+nsresult DecreaseZIndexCommand::DoCommand(Command aCommand,
                                           TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   return htmlEditor->AddZIndex(-1);
 }
 
-nsresult DecreaseZIndexCommand::DoCommandParams(const char* aCommandName,
+nsresult DecreaseZIndexCommand::DoCommandParams(Command aCommand,
                                                 nsCommandParams* aParams,
                                                 TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult DecreaseZIndexCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::IncreaseZIndexCommand
  *****************************************************************************/
 
 StaticRefPtr<IncreaseZIndexCommand> IncreaseZIndexCommand::sInstance;
 
-bool IncreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
+bool IncreaseZIndexCommand::IsCommandEnabled(Command aCommand,
                                              TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
   if (!htmlEditor) {
     return false;
   }
   if (!htmlEditor->IsAbsolutePositionEditorEnabled()) {
     return false;
   }
   return !!htmlEditor->GetPositionedElement();
 }
 
-nsresult IncreaseZIndexCommand::DoCommand(const char* aCommandName,
+nsresult IncreaseZIndexCommand::DoCommand(Command aCommand,
                                           TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   return htmlEditor->AddZIndex(1);
 }
 
-nsresult IncreaseZIndexCommand::DoCommandParams(const char* aCommandName,
+nsresult IncreaseZIndexCommand::DoCommandParams(Command aCommand,
                                                 nsCommandParams* aParams,
                                                 TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult IncreaseZIndexCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::RemoveStylesCommand
  *****************************************************************************/
 
 StaticRefPtr<RemoveStylesCommand> RemoveStylesCommand::sInstance;
 
-bool RemoveStylesCommand::IsCommandEnabled(const char* aCommandName,
+bool RemoveStylesCommand::IsCommandEnabled(Command aCommand,
                                            TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   // test if we have any styles?
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult RemoveStylesCommand::DoCommand(const char* aCommandName,
+nsresult RemoveStylesCommand::DoCommand(Command aCommand,
                                         TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   return MOZ_KnownLive(htmlEditor)->RemoveAllInlineProperties();
 }
 
-nsresult RemoveStylesCommand::DoCommandParams(const char* aCommandName,
+nsresult RemoveStylesCommand::DoCommandParams(Command aCommand,
                                               nsCommandParams* aParams,
                                               TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult RemoveStylesCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::IncreaseFontSizeCommand
  *****************************************************************************/
 
 StaticRefPtr<IncreaseFontSizeCommand> IncreaseFontSizeCommand::sInstance;
 
-bool IncreaseFontSizeCommand::IsCommandEnabled(const char* aCommandName,
+bool IncreaseFontSizeCommand::IsCommandEnabled(Command aCommand,
                                                TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   // test if we are at max size?
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult IncreaseFontSizeCommand::DoCommand(const char* aCommandName,
+nsresult IncreaseFontSizeCommand::DoCommand(Command aCommand,
                                             TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   return MOZ_KnownLive(htmlEditor)->IncreaseFontSize();
 }
 
 nsresult IncreaseFontSizeCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult IncreaseFontSizeCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::DecreaseFontSizeCommand
  *****************************************************************************/
 
 StaticRefPtr<DecreaseFontSizeCommand> DecreaseFontSizeCommand::sInstance;
 
-bool DecreaseFontSizeCommand::IsCommandEnabled(const char* aCommandName,
+bool DecreaseFontSizeCommand::IsCommandEnabled(Command aCommand,
                                                TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   // test if we are at min size?
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult DecreaseFontSizeCommand::DoCommand(const char* aCommandName,
+nsresult DecreaseFontSizeCommand::DoCommand(Command aCommand,
                                             TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   return MOZ_KnownLive(htmlEditor)->DecreaseFontSize();
 }
 
 nsresult DecreaseFontSizeCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
-  return DoCommand(aCommandName, aTextEditor);
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
+  return DoCommand(aCommand, aTextEditor);
 }
 
 nsresult DecreaseFontSizeCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::InsertHTMLCommand
  *****************************************************************************/
 
 StaticRefPtr<InsertHTMLCommand> InsertHTMLCommand::sInstance;
 
-bool InsertHTMLCommand::IsCommandEnabled(const char* aCommandName,
+bool InsertHTMLCommand::IsCommandEnabled(Command aCommand,
                                          TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
-nsresult InsertHTMLCommand::DoCommand(const char* aCommandName,
+nsresult InsertHTMLCommand::DoCommand(Command aCommand,
                                       TextEditor& aTextEditor) const {
   // If nsInsertHTMLCommand is called with no parameters, it was probably called
   // with an empty string parameter ''. In this case, it should act the same as
   // the delete command
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   nsAutoString html;
   return MOZ_KnownLive(htmlEditor)->InsertHTML(html);
 }
 
-nsresult InsertHTMLCommand::DoCommandParams(const char* aCommandName,
+nsresult InsertHTMLCommand::DoCommandParams(Command aCommand,
                                             nsCommandParams* aParams,
                                             TextEditor& aTextEditor) const {
   if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
@@ -1189,75 +1183,75 @@ nsresult InsertHTMLCommand::DoCommandPar
   nsresult rv = aParams->GetString(STATE_DATA, html);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return MOZ_KnownLive(htmlEditor)->InsertHTML(html);
 }
 
 nsresult InsertHTMLCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::InsertTagCommand
  *****************************************************************************/
 
 StaticRefPtr<InsertTagCommand> InsertTagCommand::sInstance;
-nsRefPtrHashtable<nsCharPtrHashKey, nsAtom> InsertTagCommand::sTagNameTable;
 
-bool InsertTagCommand::IsCommandEnabled(const char* aCommandName,
+bool InsertTagCommand::IsCommandEnabled(Command aCommand,
                                         TextEditor* aTextEditor) const {
   if (!aTextEditor) {
     return false;
   }
   return aTextEditor->IsSelectionEditable();
 }
 
 // corresponding STATE_ATTRIBUTE is: src (img) and href (a)
-nsresult InsertTagCommand::DoCommand(const char* aCmdName,
+nsresult InsertTagCommand::DoCommand(Command aCommand,
                                      TextEditor& aTextEditor) const {
-  RefPtr<nsAtom> tagName = TagName(aCmdName);
+  nsAtom* tagName = GetTagName(aCommand);
   if (NS_WARN_IF(tagName != nsGkAtoms::hr)) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<Element> newElement =
-      MOZ_KnownLive(htmlEditor)->CreateElementWithDefaults(*tagName);
+      MOZ_KnownLive(htmlEditor)
+          ->CreateElementWithDefaults(MOZ_KnownLive(*tagName));
   if (NS_WARN_IF(!newElement)) {
     return NS_ERROR_FAILURE;
   }
   nsresult rv =
       MOZ_KnownLive(htmlEditor)->InsertElementAtSelection(newElement, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-nsresult InsertTagCommand::DoCommandParams(const char* aCommandName,
+nsresult InsertTagCommand::DoCommandParams(Command aCommand,
                                            nsCommandParams* aParams,
                                            TextEditor& aTextEditor) const {
   // inserting an hr shouldn't have an parameters, just call DoCommand for that
-  if (!strcmp(aCommandName, "cmd_insertHR")) {
-    return DoCommand(aCommandName, aTextEditor);
+  if (aCommand == Command::InsertHorizontalRule) {
+    return DoCommand(aCommand, aTextEditor);
   }
 
   if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
-  RefPtr<nsAtom> tagName = TagName(aCommandName);
+  nsAtom* tagName = GetTagName(aCommand);
   if (NS_WARN_IF(!tagName)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
@@ -1280,17 +1274,18 @@ nsresult InsertTagCommand::DoCommandPara
     attribute = nsGkAtoms::href;
   } else if (tagName == nsGkAtoms::img) {
     attribute = nsGkAtoms::src;
   } else {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   RefPtr<Element> newElement =
-      MOZ_KnownLive(htmlEditor)->CreateElementWithDefaults(*tagName);
+      MOZ_KnownLive(htmlEditor)
+          ->CreateElementWithDefaults(MOZ_KnownLive(*tagName));
   if (NS_WARN_IF(!newElement)) {
     return NS_ERROR_FAILURE;
   }
 
   ErrorResult err;
   newElement->SetAttr(attribute, value, err);
   if (NS_WARN_IF(err.Failed())) {
     return err.StealNSResult();
@@ -1308,20 +1303,20 @@ nsresult InsertTagCommand::DoCommandPara
   rv = MOZ_KnownLive(htmlEditor)->InsertElementAtSelection(newElement, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult InsertTagCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   return aParams.SetBool(STATE_ENABLED,
-                         IsCommandEnabled(aCommandName, aTextEditor));
+                         IsCommandEnabled(aCommand, aTextEditor));
 }
 
 /*****************************************************************************
  * Helper methods
  *****************************************************************************/
 
 static nsresult GetListState(HTMLEditor* aHTMLEditor, bool* aMixed,
                              nsAString& aLocalName)
--- a/editor/libeditor/HTMLEditorDocumentCommands.cpp
+++ b/editor/libeditor/HTMLEditorDocumentCommands.cpp
@@ -32,345 +32,325 @@ namespace mozilla {
  *  As of 11/11/02, this is just "cmd_setDocumentModified"
  *  Note that you can use the same command class, SetDocumentStateCommand,
  *    for more than one of this type of command
  *    We check the input command param for different behavior
  *****************************************************************************/
 
 StaticRefPtr<SetDocumentStateCommand> SetDocumentStateCommand::sInstance;
 
-bool SetDocumentStateCommand::IsCommandEnabled(const char* aCommandName,
+bool SetDocumentStateCommand::IsCommandEnabled(Command aCommand,
                                                TextEditor* aTextEditor) const {
   // These commands are always enabled
   return true;
 }
 
-nsresult SetDocumentStateCommand::DoCommand(const char* aCommandName,
+nsresult SetDocumentStateCommand::DoCommand(Command aCommand,
                                             TextEditor& aTextEditor) const {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 nsresult SetDocumentStateCommand::DoCommandParams(
-    const char* aCommandName, nsCommandParams* aParams,
-    TextEditor& aTextEditor) const {
+    Command aCommand, nsCommandParams* aParams, TextEditor& aTextEditor) const {
   if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (!strcmp(aCommandName, "cmd_setDocumentModified")) {
-    ErrorResult error;
-    bool modified = aParams->GetBool(STATE_ATTRIBUTE, error);
-    // Should we fail if this param wasn't set?
-    // I'm not sure we should be that strict
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-    if (modified) {
-      nsresult rv = aTextEditor.IncrementModificationCount(1);
+  switch (aCommand) {
+    case Command::SetDocumentModified: {
+      ErrorResult error;
+      bool modified = aParams->GetBool(STATE_ATTRIBUTE, error);
+      // Should we fail if this param wasn't set?
+      // I'm not sure we should be that strict
+      if (NS_WARN_IF(error.Failed())) {
+        return error.StealNSResult();
+      }
+      if (modified) {
+        nsresult rv = aTextEditor.IncrementModificationCount(1);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+        return NS_OK;
+      }
+      nsresult rv = aTextEditor.ResetModificationCount();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       return NS_OK;
     }
-    nsresult rv = aTextEditor.ResetModificationCount();
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+    case Command::SetDocumentReadOnly: {
+      ErrorResult error;
+      bool isReadOnly = aParams->GetBool(STATE_ATTRIBUTE, error);
+      if (NS_WARN_IF(error.Failed())) {
+        return error.StealNSResult();
+      }
+      if (isReadOnly) {
+        nsresult rv =
+            aTextEditor.AddFlags(nsIPlaintextEditor::eEditorReadonlyMask);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+        return NS_OK;
+      }
+      nsresult rv =
+          aTextEditor.RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      return NS_OK;
     }
-    return NS_OK;
-  }
-
-  if (!strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
-    ErrorResult error;
-    bool isReadOnly = aParams->GetBool(STATE_ATTRIBUTE, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-    if (isReadOnly) {
-      nsresult rv =
-          aTextEditor.AddFlags(nsIPlaintextEditor::eEditorReadonlyMask);
+    case Command::SetDocumentUseCSS: {
+      HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      ErrorResult error;
+      bool desireCSS = aParams->GetBool(STATE_ATTRIBUTE, error);
+      if (NS_WARN_IF(error.Failed())) {
+        return error.StealNSResult();
+      }
+      nsresult rv = htmlEditor->SetIsCSSEnabled(desireCSS);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       return NS_OK;
     }
-    nsresult rv =
-        aTextEditor.RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
-  }
-
-  if (!strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
-    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    ErrorResult error;
-    bool desireCSS = aParams->GetBool(STATE_ATTRIBUTE, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-    nsresult rv = htmlEditor->SetIsCSSEnabled(desireCSS);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
-  }
-
-  if (!strcmp(aCommandName, "cmd_insertBrOnReturn")) {
-    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    ErrorResult error;
-    bool insertBrOnReturn = aParams->GetBool(STATE_ATTRIBUTE, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-    nsresult rv =
-        htmlEditor->SetReturnInParagraphCreatesNewParagraph(!insertBrOnReturn);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
-  }
-
-  if (!strcmp(aCommandName, "cmd_defaultParagraphSeparator")) {
-    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-
-    nsAutoCString newValue;
-    nsresult rv = aParams->GetCString(STATE_ATTRIBUTE, newValue);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    if (newValue.LowerCaseEqualsLiteral("div")) {
-      htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::div);
+    case Command::SetDocumentInsertBROnEnterKeyPress: {
+      HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      ErrorResult error;
+      bool insertBrOnReturn = aParams->GetBool(STATE_ATTRIBUTE, error);
+      if (NS_WARN_IF(error.Failed())) {
+        return error.StealNSResult();
+      }
+      nsresult rv = htmlEditor->SetReturnInParagraphCreatesNewParagraph(
+          !insertBrOnReturn);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
       return NS_OK;
     }
-    if (newValue.LowerCaseEqualsLiteral("p")) {
-      htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::p);
-      return NS_OK;
+    case Command::SetDocumentDefaultParagraphSeparator: {
+      HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+
+      nsAutoCString newValue;
+      nsresult rv = aParams->GetCString(STATE_ATTRIBUTE, newValue);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      if (newValue.LowerCaseEqualsLiteral("div")) {
+        htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::div);
+        return NS_OK;
+      }
+      if (newValue.LowerCaseEqualsLiteral("p")) {
+        htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::p);
+        return NS_OK;
+      }
+      if (newValue.LowerCaseEqualsLiteral("br")) {
+        // Mozilla extension for backwards compatibility
+        htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::br);
+        return NS_OK;
+      }
+
+      // This should not be reachable from nsHTMLDocument::ExecCommand
+      NS_WARNING("Invalid default paragraph separator");
+      return NS_ERROR_UNEXPECTED;
     }
-    if (newValue.LowerCaseEqualsLiteral("br")) {
-      // Mozilla extension for backwards compatibility
-      htmlEditor->SetDefaultParagraphSeparator(ParagraphSeparator::br);
+    case Command::ToggleObjectResizers: {
+      HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      ErrorResult error;
+      bool enabled = aParams->GetBool(STATE_ATTRIBUTE, error);
+      if (NS_WARN_IF(error.Failed())) {
+        return error.StealNSResult();
+      }
+      htmlEditor->EnableObjectResizer(enabled);
       return NS_OK;
     }
-
-    // This should not be reachable from nsHTMLDocument::ExecCommand
-    NS_WARNING("Invalid default paragraph separator");
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  if (!strcmp(aCommandName, "cmd_enableObjectResizing")) {
-    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    ErrorResult error;
-    bool enabled = aParams->GetBool(STATE_ATTRIBUTE, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-    htmlEditor->EnableObjectResizer(enabled);
-    return NS_OK;
-  }
-
-  if (!strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
-    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
+    case Command::ToggleInlineTableEditor: {
+      HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      ErrorResult error;
+      bool enabled = aParams->GetBool(STATE_ATTRIBUTE, error);
+      if (NS_WARN_IF(error.Failed())) {
+        return error.StealNSResult();
+      }
+      htmlEditor->EnableInlineTableEditor(enabled);
+      return NS_OK;
     }
-    ErrorResult error;
-    bool enabled = aParams->GetBool(STATE_ATTRIBUTE, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
+    case Command::ToggleAbsolutePositionEditor: {
+      HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      ErrorResult error;
+      bool enabled = aParams->GetBool(STATE_ATTRIBUTE, error);
+      if (NS_WARN_IF(error.Failed())) {
+        return error.StealNSResult();
+      }
+      htmlEditor->EnableAbsolutePositionEditor(enabled);
+      return NS_OK;
     }
-    htmlEditor->EnableInlineTableEditor(enabled);
-    return NS_OK;
+    default:
+      return NS_ERROR_NOT_IMPLEMENTED;
   }
-
-  if (!strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
-    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    ErrorResult error;
-    bool enabled = aParams->GetBool(STATE_ATTRIBUTE, error);
-    if (NS_WARN_IF(error.Failed())) {
-      return error.StealNSResult();
-    }
-    htmlEditor->EnableAbsolutePositionEditor(enabled);
-    return NS_OK;
-  }
-
-  return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 nsresult SetDocumentStateCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   // If the result is set to STATE_ALL as bool value, queryCommandState()
   // returns the bool value.
   // If the result is set to STATE_ATTRIBUTE as CString value,
   // queryCommandValue() returns the string value.
   // Otherwise, ignored.
 
   // The base editor owns most state info
   if (NS_WARN_IF(!aTextEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
   // Always get the enabled state
-  nsresult rv = aParams.SetBool(STATE_ENABLED,
-                                IsCommandEnabled(aCommandName, aTextEditor));
+  nsresult rv =
+      aParams.SetBool(STATE_ENABLED, IsCommandEnabled(aCommand, aTextEditor));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  // cmd_setDocumentModified is an internal command.
-  if (!strcmp(aCommandName, "cmd_setDocumentModified")) {
-    bool modified;
-    rv = aTextEditor->GetDocumentModified(&modified);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    // XXX Nobody refers this result due to wrong type.
-    rv = aParams.SetBool(STATE_ATTRIBUTE, modified);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+  switch (aCommand) {
+    case Command::SetDocumentModified: {
+      bool modified;
+      rv = aTextEditor->GetDocumentModified(&modified);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      // XXX Nobody refers this result due to wrong type.
+      rv = aParams.SetBool(STATE_ATTRIBUTE, modified);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      return NS_OK;
     }
-    return NS_OK;
-  }
-
-  // cmd_setDocumentReadOnly is a Gecko specific command, "contentReadOnly".
-  if (!strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
-    // XXX Nobody refers this result due to wrong type.
-    rv = aParams.SetBool(STATE_ATTRIBUTE, aTextEditor->IsReadonly());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
-  }
-
-  // cmd_setDocumentUseCSS is a common command, "styleWithCSS".
-  if (!strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
-    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
+    case Command::SetDocumentReadOnly: {
+      // XXX Nobody refers this result due to wrong type.
+      rv = aParams.SetBool(STATE_ATTRIBUTE, aTextEditor->IsReadonly());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      return NS_OK;
     }
-    rv = aParams.SetBool(STATE_ALL, htmlEditor->IsCSSEnabled());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
-  }
-
-  // cmd_insertBrOnReturn is a Gecko specific command, "insertBrOrReturn".
-  if (!strcmp(aCommandName, "cmd_insertBrOnReturn")) {
-    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
+    case Command::SetDocumentUseCSS: {
+      HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      rv = aParams.SetBool(STATE_ALL, htmlEditor->IsCSSEnabled());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      return NS_OK;
     }
-    bool createPOnReturn;
-    htmlEditor->GetReturnInParagraphCreatesNewParagraph(&createPOnReturn);
-    // XXX Nobody refers this result due to wrong type.
-    rv = aParams.SetBool(STATE_ATTRIBUTE, !createPOnReturn);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+    case Command::SetDocumentInsertBROnEnterKeyPress: {
+      HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      bool createPOnReturn;
+      htmlEditor->GetReturnInParagraphCreatesNewParagraph(&createPOnReturn);
+      // XXX Nobody refers this result due to wrong type.
+      rv = aParams.SetBool(STATE_ATTRIBUTE, !createPOnReturn);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      return NS_OK;
     }
-    return NS_OK;
-  }
-
-  // cmd_defaultParagraphSeparator is a common command,
-  // "defaultParagraphSeparator".
-  if (!strcmp(aCommandName, "cmd_defaultParagraphSeparator")) {
-    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
-    }
+    case Command::SetDocumentDefaultParagraphSeparator: {
+      HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
 
-    switch (htmlEditor->GetDefaultParagraphSeparator()) {
-      case ParagraphSeparator::div: {
-        DebugOnly<nsresult> rv =
-            aParams.SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("div"));
-        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
-                             "Failed to set command params to return \"div\"");
-        return NS_OK;
-      }
-      case ParagraphSeparator::p: {
-        DebugOnly<nsresult> rv =
-            aParams.SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("p"));
-        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
-                             "Failed to set command params to return \"p\"");
-        return NS_OK;
+      switch (htmlEditor->GetDefaultParagraphSeparator()) {
+        case ParagraphSeparator::div: {
+          DebugOnly<nsresult> rv =
+              aParams.SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("div"));
+          NS_WARNING_ASSERTION(
+              NS_SUCCEEDED(rv),
+              "Failed to set command params to return \"div\"");
+          return NS_OK;
+        }
+        case ParagraphSeparator::p: {
+          DebugOnly<nsresult> rv =
+              aParams.SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("p"));
+          NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                               "Failed to set command params to return \"p\"");
+          return NS_OK;
+        }
+        case ParagraphSeparator::br: {
+          DebugOnly<nsresult> rv =
+              aParams.SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("br"));
+          NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                               "Failed to set command params to return \"br\"");
+          return NS_OK;
+        }
+        default:
+          MOZ_ASSERT_UNREACHABLE("Invalid paragraph separator value");
+          return NS_ERROR_UNEXPECTED;
       }
-      case ParagraphSeparator::br: {
-        DebugOnly<nsresult> rv =
-            aParams.SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("br"));
-        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
-                             "Failed to set command params to return \"br\"");
-        return NS_OK;
-      }
-      default:
-        MOZ_ASSERT_UNREACHABLE("Invalid paragraph separator value");
-        return NS_ERROR_UNEXPECTED;
-    }
-  }
-
-  // cmd_enableObjectResizing is a Gecko specific command,
-  // "enableObjectResizing".
-  if (!strcmp(aCommandName, "cmd_enableObjectResizing")) {
-    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
     }
-    // We returned the result as STATE_ATTRIBUTE with bool value 60 or earlier.
-    // So, the result was ignored by both nsHTMLDocument::QueryCommandValue()
-    // and nsHTMLDocument::QueryCommandState().
-    rv = aParams.SetBool(STATE_ALL, htmlEditor->IsObjectResizerEnabled());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
-  }
-
-  // cmd_enableInlineTableEditing is a Gecko specific command,
-  // "enableInlineTableEditing".
-  if (!strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
-    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
+    case Command::ToggleObjectResizers: {
+      HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      // We returned the result as STATE_ATTRIBUTE with bool value 60 or
+      // earlier. So, the result was ignored by both
+      // nsHTMLDocument::QueryCommandValue() and
+      // nsHTMLDocument::QueryCommandState().
+      rv = aParams.SetBool(STATE_ALL, htmlEditor->IsObjectResizerEnabled());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      return NS_OK;
     }
-    // We returned the result as STATE_ATTRIBUTE with bool value 60 or earlier.
-    // So, the result was ignored by both nsHTMLDocument::QueryCommandValue()
-    // and nsHTMLDocument::QueryCommandState().
-    rv = aParams.SetBool(STATE_ALL, htmlEditor->IsInlineTableEditorEnabled());
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+    case Command::ToggleInlineTableEditor: {
+      HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      // We returned the result as STATE_ATTRIBUTE with bool value 60 or
+      // earlier. So, the result was ignored by both
+      // nsHTMLDocument::QueryCommandValue() and
+      // nsHTMLDocument::QueryCommandState().
+      rv = aParams.SetBool(STATE_ALL, htmlEditor->IsInlineTableEditorEnabled());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      return NS_OK;
     }
-    return NS_OK;
+    case Command::ToggleAbsolutePositionEditor: {
+      HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+      if (NS_WARN_IF(!htmlEditor)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+      return aParams.SetBool(STATE_ALL,
+                             htmlEditor->IsAbsolutePositionEditorEnabled());
+    }
+    default:
+      return NS_ERROR_NOT_IMPLEMENTED;
   }
-
-  // cmd_enableAbsolutePositionEditing is a Gecko specific command,
-  // "cenableAbsolutePositionEditing".
-  if (!strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
-    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
-    if (NS_WARN_IF(!htmlEditor)) {
-      return NS_ERROR_INVALID_ARG;
-    }
-    return aParams.SetBool(STATE_ALL,
-                           htmlEditor->IsAbsolutePositionEditorEnabled());
-  }
-
-  return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /*****************************************************************************
  * mozilla::DocumentStateCommand
  *
  * Commands just for state notification
  *  As of 11/21/02, possible commands are:
  *    "obs_documentCreated"
@@ -402,74 +382,75 @@ nsresult SetDocumentStateCommand::GetCom
  *  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
  *****************************************************************************/
 
 StaticRefPtr<DocumentStateCommand> DocumentStateCommand::sInstance;
 
-bool DocumentStateCommand::IsCommandEnabled(const char* aCommandName,
+bool DocumentStateCommand::IsCommandEnabled(Command aCommand,
                                             TextEditor* aTextEditor) const {
   // Always return false to discourage callers from using DoCommand()
   return false;
 }
 
-nsresult DocumentStateCommand::DoCommand(const char* aCommandName,
+nsresult DocumentStateCommand::DoCommand(Command aCommand,
                                          TextEditor& aTextEditor) const {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-nsresult DocumentStateCommand::DoCommandParams(const char* aCommandName,
+nsresult DocumentStateCommand::DoCommandParams(Command aCommand,
                                                nsCommandParams* aParams,
                                                TextEditor& aTextEditor) const {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 nsresult DocumentStateCommand::GetCommandStateParams(
-    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
-  if (!strcmp(aCommandName, "obs_documentCreated")) {
-    uint32_t editorStatus = nsIEditingSession::eEditorErrorUnknown;
-    if (aEditingSession) {
-      // Current context is initially set to nsIEditingSession until editor is
-      // successfully created and source doc is loaded.  Embedder gets error
-      // status if this fails.  If called before startup is finished,
-      // status will be eEditorCreationInProgress.
-      nsresult rv = aEditingSession->GetEditorStatus(&editorStatus);
+  switch (aCommand) {
+    case Command::EditorObserverDocumentCreated: {
+      uint32_t editorStatus = nsIEditingSession::eEditorErrorUnknown;
+      if (aEditingSession) {
+        // Current context is initially set to nsIEditingSession until editor is
+        // successfully created and source doc is loaded.  Embedder gets error
+        // status if this fails.  If called before startup is finished,
+        // status will be eEditorCreationInProgress.
+        nsresult rv = aEditingSession->GetEditorStatus(&editorStatus);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+      } else if (aTextEditor) {
+        // If current context is an editor, then everything started up OK!
+        editorStatus = nsIEditingSession::eEditorOK;
+      }
+
+      // Note that if refCon is not-null, but is neither
+      // an nsIEditingSession or nsIEditor, we return "eEditorErrorUnknown"
+      DebugOnly<nsresult> rv = aParams.SetInt(STATE_DATA, editorStatus);
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to set editor status");
+      return NS_OK;
+    }
+    case Command::EditorObserverDocumentLocationChanged: {
+      if (!aTextEditor) {
+        return NS_OK;
+      }
+      Document* document = aTextEditor->GetDocument();
+      if (NS_WARN_IF(!document)) {
+        return NS_ERROR_FAILURE;
+      }
+      nsIURI* uri = document->GetDocumentURI();
+      if (NS_WARN_IF(!uri)) {
+        return NS_ERROR_FAILURE;
+      }
+      nsresult rv = aParams.SetISupports(STATE_DATA, uri);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
-    } else if (aTextEditor) {
-      // If current context is an editor, then everything started up OK!
-      editorStatus = nsIEditingSession::eEditorOK;
-    }
-
-    // Note that if refCon is not-null, but is neither
-    // an nsIEditingSession or nsIEditor, we return "eEditorErrorUnknown"
-    DebugOnly<nsresult> rv = aParams.SetInt(STATE_DATA, editorStatus);
-    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to set editor status");
-    return NS_OK;
-  }
-
-  if (!strcmp(aCommandName, "obs_documentLocationChanged")) {
-    if (!aTextEditor) {
       return NS_OK;
     }
-    Document* document = aTextEditor->GetDocument();
-    if (NS_WARN_IF(!document)) {
-      return NS_ERROR_FAILURE;
-    }
-    nsIURI* uri = document->GetDocumentURI();
-    if (NS_WARN_IF(!uri)) {
-      return NS_ERROR_FAILURE;
-    }
-    nsresult rv = aParams.SetISupports(STATE_DATA, uri);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
+    default:
+      return NS_ERROR_NOT_IMPLEMENTED;
   }
-
-  return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 }  // namespace mozilla