Bug 1549661 - part 5: Make commands for `MultiStateCommandBase` take both `CString` and `String` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 21 May 2019 07:47:47 +0000
changeset 474682 ed3667be6075fb724afc34a3294285ec8d484e52
parent 474681 c3c796dd6070d4011e0f4f9a474c2134761ea419
child 474683 bd77dd67175d25744b092e18f4a074bb15971fe4
push id36044
push userrmaries@mozilla.com
push dateTue, 21 May 2019 15:45:34 +0000
treeherdermozilla-central@78571bb1f20e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1549661
milestone69.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 1549661 - part 5: Make commands for `MultiStateCommandBase` take both `CString` and `String` r=m_kato Only `MultiStateCommandBase::DoCommandParams()` allows `CString` param and `String` param (the former is preferred). This patch makes `EditorCommand::DoCommandParams()` aware of this case. Differential Revision: https://phabricator.services.mozilla.com/D30499
editor/libeditor/EditorCommands.cpp
editor/libeditor/EditorCommands.h
editor/libeditor/HTMLEditorCommands.cpp
widget/CommandList.h
--- a/editor/libeditor/EditorCommands.cpp
+++ b/editor/libeditor/EditorCommands.cpp
@@ -116,16 +116,56 @@ EditorCommand::DoCommandParams(const cha
           NS_SUCCEEDED(rv),
           "Failed to do command from nsIControllerCommand::DoCommandParams()");
       return rv;
     }
     MOZ_ASSERT_UNREACHABLE("Unexpected state for bool");
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
+  // Special case for MultiStateCommandBase.  It allows both CString and String
+  // in STATE_ATTRIBUTE and CString is preferred.
+  if (Any(paramType & EditorCommandParamType::CString) &&
+      Any(paramType & EditorCommandParamType::String)) {
+    if (!params) {
+      nsresult rv = DoCommandParam(command, VoidString(),
+                                   MOZ_KnownLive(*editor->AsTextEditor()));
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                           "Failed to do command from "
+                           "nsIControllerCommand::DoCommandParams()");
+      return rv;
+    }
+    if (Any(paramType & EditorCommandParamType::StateAttribute)) {
+      nsCString cStringParam;
+      nsresult rv = params->GetCString(STATE_ATTRIBUTE, cStringParam);
+      if (NS_SUCCEEDED(rv)) {
+        NS_ConvertUTF8toUTF16 stringParam(cStringParam);
+        nsresult rv = DoCommandParam(command, stringParam,
+                                     MOZ_KnownLive(*editor->AsTextEditor()));
+        NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                             "Failed to do command from "
+                             "nsIControllerCommand::DoCommandParams()");
+        return rv;
+      }
+      nsString stringParam;
+      DebugOnly<nsresult> rvIgnored =
+          params->GetString(STATE_ATTRIBUTE, stringParam);
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
+                           "Failed to get string from STATE_ATTRIBUTE");
+      rv = DoCommandParam(command, stringParam,
+                          MOZ_KnownLive(*editor->AsTextEditor()));
+      NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                           "Failed to do command from "
+                           "nsIControllerCommand::DoCommandParams()");
+      return rv;
+    }
+    MOZ_ASSERT_UNREACHABLE("Unexpected state for CString/String");
+    return NS_ERROR_NOT_IMPLEMENTED;
+  }
+
   if (Any(paramType & EditorCommandParamType::CString)) {
     if (!params) {
       nsresult rv = DoCommandParam(command, VoidCString(),
                                    MOZ_KnownLive(*editor->AsTextEditor()));
       NS_WARNING_ASSERTION(
           NS_SUCCEEDED(rv),
           "Failed to do command from nsIControllerCommand::DoCommandParams()");
       return rv;
--- a/editor/libeditor/EditorCommands.h
+++ b/editor/libeditor/EditorCommands.h
@@ -224,16 +224,54 @@ class EditorCommand : public nsIControll
         return EditorCommandParamType::None;
       // ListItemCommand
       case Command::InsertDefinitionTerm:
       case Command::InsertDefinitionDetails:
         return EditorCommandParamType::None;
       // RemoveListCommand
       case Command::FormatRemoveList:
         return EditorCommandParamType::None;
+      // ParagraphStateCommand
+      case Command::FormatBlock:
+        return EditorCommandParamType::CString |
+               EditorCommandParamType::String |
+               EditorCommandParamType::StateAttribute;
+      // FontFaceStateCommand
+      case Command::FormatFontName:
+        return EditorCommandParamType::CString |
+               EditorCommandParamType::String |
+               EditorCommandParamType::StateAttribute;
+      // FontSizeStateCommand
+      case Command::FormatFontSize:
+        return EditorCommandParamType::CString |
+               EditorCommandParamType::String |
+               EditorCommandParamType::StateAttribute;
+      // FontColorStateCommand
+      case Command::FormatFontColor:
+        return EditorCommandParamType::CString |
+               EditorCommandParamType::String |
+               EditorCommandParamType::StateAttribute;
+      // BackgroundColorStateCommand
+      case Command::FormatDocumentBackgroundColor:
+        return EditorCommandParamType::CString |
+               EditorCommandParamType::String |
+               EditorCommandParamType::StateAttribute;
+      // HighlightColorStateCommand
+      case Command::FormatBackColor:
+        return EditorCommandParamType::CString |
+               EditorCommandParamType::String |
+               EditorCommandParamType::StateAttribute;
+      // AlignCommand:
+      case Command::FormatJustifyLeft:
+      case Command::FormatJustifyRight:
+      case Command::FormatJustifyCenter:
+      case Command::FormatJustifyFull:
+        return EditorCommandParamType::CString |
+               EditorCommandParamType::String |
+               EditorCommandParamType::StateAttribute;
       // RemoveStylesCommand
       case Command::FormatRemove:
         return EditorCommandParamType::None;
       // IncreaseFontSizeCommand
       case Command::FormatIncreaseFontSize:
         return EditorCommandParamType::None;
       // DecreaseFontSizeCommand
       case Command::FormatDecreaseFontSize:
@@ -671,140 +709,140 @@ class ListItemCommand final : public Sta
 };
 
 // Base class for commands whose state consists of a string (e.g. para format)
 class MultiStateCommandBase : public EditorCommand {
  public:
   NS_INLINE_DECL_REFCOUNTING_INHERITED(MultiStateCommandBase, EditorCommand)
 
   NS_DECL_EDITOR_COMMAND_COMMON_METHODS
-  NS_DECL_DO_COMMAND_PARAMS
+  NS_DECL_DO_COMMAND_PARAM_FOR_STRING_PARAM
 
  protected:
   MultiStateCommandBase() = default;
   virtual ~MultiStateCommandBase() = default;
 
   MOZ_CAN_RUN_SCRIPT
   virtual nsresult GetCurrentState(HTMLEditor* aHTMLEditor,
                                    nsCommandParams& aParams) const = 0;
   MOZ_CAN_RUN_SCRIPT
   virtual nsresult SetState(HTMLEditor* aHTMLEditor,
-                            const nsString& newState) const = 0;
+                            const nsAString& aNewState) const = 0;
 };
 
 class ParagraphStateCommand final : public MultiStateCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(ParagraphStateCommand)
 
  protected:
   ParagraphStateCommand() = default;
   virtual ~ParagraphStateCommand() = default;
 
   MOZ_CAN_RUN_SCRIPT
   nsresult GetCurrentState(HTMLEditor* aHTMLEditor,
                            nsCommandParams& aParams) const final;
   MOZ_CAN_RUN_SCRIPT
   nsresult SetState(HTMLEditor* aHTMLEditor,
-                    const nsString& newState) const final;
+                    const nsAString& aNewState) const final;
 };
 
 class FontFaceStateCommand final : public MultiStateCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(FontFaceStateCommand)
 
  protected:
   FontFaceStateCommand() = default;
   virtual ~FontFaceStateCommand() = default;
 
   MOZ_CAN_RUN_SCRIPT
   nsresult GetCurrentState(HTMLEditor* aHTMLEditor,
                            nsCommandParams& aParams) const final;
   MOZ_CAN_RUN_SCRIPT
   nsresult SetState(HTMLEditor* aHTMLEditor,
-                    const nsString& newState) const final;
+                    const nsAString& aNewState) const final;
 };
 
 class FontSizeStateCommand final : public MultiStateCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(FontSizeStateCommand)
 
  protected:
   FontSizeStateCommand() = default;
   virtual ~FontSizeStateCommand() = default;
 
   MOZ_CAN_RUN_SCRIPT
   nsresult GetCurrentState(HTMLEditor* aHTMLEditor,
                            nsCommandParams& aParams) const final;
   MOZ_CAN_RUN_SCRIPT
   nsresult SetState(HTMLEditor* aHTMLEditor,
-                    const nsString& newState) const final;
+                    const nsAString& aNewState) const final;
 };
 
 class HighlightColorStateCommand final : public MultiStateCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(HighlightColorStateCommand)
 
  protected:
   HighlightColorStateCommand() = default;
   virtual ~HighlightColorStateCommand() = default;
 
   MOZ_CAN_RUN_SCRIPT
   nsresult GetCurrentState(HTMLEditor* aHTMLEditor,
                            nsCommandParams& aParams) const final;
   MOZ_CAN_RUN_SCRIPT
   nsresult SetState(HTMLEditor* aHTMLEditor,
-                    const nsString& newState) const final;
+                    const nsAString& aNewState) const final;
 };
 
 class FontColorStateCommand final : public MultiStateCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(FontColorStateCommand)
 
  protected:
   FontColorStateCommand() = default;
   virtual ~FontColorStateCommand() = default;
 
   MOZ_CAN_RUN_SCRIPT
   nsresult GetCurrentState(HTMLEditor* aHTMLEditor,
                            nsCommandParams& aParams) const final;
   MOZ_CAN_RUN_SCRIPT
   nsresult SetState(HTMLEditor* aHTMLEditor,
-                    const nsString& newState) const final;
+                    const nsAString& aNewState) const final;
 };
 
 class AlignCommand final : public MultiStateCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(AlignCommand)
 
  protected:
   AlignCommand() = default;
   virtual ~AlignCommand() = default;
 
   MOZ_CAN_RUN_SCRIPT
   nsresult GetCurrentState(HTMLEditor* aHTMLEditor,
                            nsCommandParams& aParams) const final;
   MOZ_CAN_RUN_SCRIPT
   nsresult SetState(HTMLEditor* aHTMLEditor,
-                    const nsString& newState) const final;
+                    const nsAString& aNewState) const final;
 };
 
 class BackgroundColorStateCommand final : public MultiStateCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(BackgroundColorStateCommand)
 
  protected:
   BackgroundColorStateCommand() = default;
   virtual ~BackgroundColorStateCommand() = default;
 
   MOZ_CAN_RUN_SCRIPT
   nsresult GetCurrentState(HTMLEditor* aHTMLEditor,
                            nsCommandParams& aParams) const final;
   MOZ_CAN_RUN_SCRIPT
   nsresult SetState(HTMLEditor* aHTMLEditor,
-                    const nsString& newState) const final;
+                    const nsAString& aNewState) const final;
 };
 
 class AbsolutePositioningCommand final : public StateUpdatingCommandBase {
  public:
   NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(AbsolutePositioningCommand)
 
  protected:
   AbsolutePositioningCommand() = default;
--- a/editor/libeditor/HTMLEditorCommands.cpp
+++ b/editor/libeditor/HTMLEditorCommands.cpp
@@ -494,35 +494,26 @@ bool MultiStateCommandBase::IsCommandEna
 
 nsresult MultiStateCommandBase::DoCommand(Command aCommand,
                                           TextEditor& aTextEditor) const {
   NS_WARNING(
       "who is calling MultiStateCommandBase::DoCommand (no implementation)?");
   return NS_OK;
 }
 
-nsresult MultiStateCommandBase::DoCommandParams(Command aCommand,
-                                                nsCommandParams* aParams,
-                                                TextEditor& aTextEditor) const {
+nsresult MultiStateCommandBase::DoCommandParam(Command aCommand,
+                                               const nsAString& aStringParam,
+                                               TextEditor& aTextEditor) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
-
-  nsAutoString attribute;
-  if (aParams) {
-    nsAutoCString asciiAttribute;
-    nsresult rv = aParams->GetCString(STATE_ATTRIBUTE, asciiAttribute);
-    if (NS_SUCCEEDED(rv)) {
-      CopyASCIItoUTF16(asciiAttribute, attribute);
-    } else {
-      aParams->GetString(STATE_ATTRIBUTE, attribute);
-    }
-  }
-  return SetState(MOZ_KnownLive(htmlEditor), attribute);
+  nsresult rv = SetState(MOZ_KnownLive(htmlEditor), aStringParam);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetState() failed");
+  return rv;
 }
 
 nsresult MultiStateCommandBase::GetCommandStateParams(
     Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
   if (!aTextEditor) {
     return NS_OK;
   }
@@ -553,21 +544,23 @@ nsresult ParagraphStateCommand::GetCurre
     LossyCopyUTF16toASCII(outStateString, tOutStateString);
     aParams.SetBool(STATE_MIXED, outMixed);
     aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   }
   return rv;
 }
 
 nsresult ParagraphStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                         const nsString& newState) const {
+                                         const nsAString& aNewState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
-  return aHTMLEditor->SetParagraphFormat(newState);
+  nsresult rv = aHTMLEditor->SetParagraphFormat(aNewState);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetParagraphFormat() failed");
+  return rv;
 }
 
 /*****************************************************************************
  * mozilla::FontFaceStateCommand
  *****************************************************************************/
 
 StaticRefPtr<FontFaceStateCommand> FontFaceStateCommand::sInstance;
 
@@ -583,59 +576,55 @@ nsresult FontFaceStateCommand::GetCurren
   if (NS_SUCCEEDED(rv)) {
     aParams.SetBool(STATE_MIXED, outMixed);
     aParams.SetCString(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString));
   }
   return rv;
 }
 
 nsresult FontFaceStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                        const nsString& newState) const {
+                                        const nsAString& aNewState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (newState.EqualsLiteral("tt")) {
+  if (aNewState.EqualsLiteral("tt")) {
     // The old "teletype" attribute
     nsresult rv = aHTMLEditor->SetInlinePropertyAsAction(
         *nsGkAtoms::tt, nullptr, EmptyString());
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     // Clear existing font face
     rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::font,
                                                    nsGkAtoms::face);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                         "RemoveInlinePropertyAsAction() failed");
+    return rv;
   }
 
   // Remove any existing TT nodes
   nsresult rv =
       aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::tt, nullptr);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
+  if (aNewState.IsEmpty() || aNewState.EqualsLiteral("normal")) {
     rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::font,
                                                    nsGkAtoms::face);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                         "RemoveInlinePropertyAsAction() failed");
+    return rv;
   }
 
   rv = aHTMLEditor->SetInlinePropertyAsAction(*nsGkAtoms::font, nsGkAtoms::face,
-                                              newState);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
+                                              aNewState);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetInlinePropertyAsAction() failed");
+  return rv;
 }
 
 /*****************************************************************************
  * mozilla::FontSizeStateCommand
  *****************************************************************************/
 
 StaticRefPtr<FontSizeStateCommand> FontSizeStateCommand::sInstance;
 
@@ -656,35 +645,35 @@ nsresult FontSizeStateCommand::GetCurren
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams.SetBool(STATE_MIXED, anyHas && !allHas);
   aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   aParams.SetBool(STATE_ENABLED, true);
 
   return rv;
 }
 
-// acceptable values for "newState" are:
+// acceptable values for "aNewState" are:
 //   -2
 //   -1
 //    0
 //   +1
 //   +2
 //   +3
 //   medium
 //   normal
 nsresult FontSizeStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                        const nsString& newState) const {
+                                        const nsAString& aNewState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (!newState.IsEmpty() && !newState.EqualsLiteral("normal") &&
-      !newState.EqualsLiteral("medium")) {
+  if (!aNewState.IsEmpty() && !aNewState.EqualsLiteral("normal") &&
+      !aNewState.EqualsLiteral("medium")) {
     nsresult rv = aHTMLEditor->SetInlinePropertyAsAction(
-        *nsGkAtoms::font, nsGkAtoms::size, newState);
+        *nsGkAtoms::font, nsGkAtoms::size, aNewState);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   // remove any existing font size, big or small
   nsresult rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::font,
@@ -694,20 +683,19 @@ nsresult FontSizeStateCommand::SetState(
   }
 
   rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::big, nullptr);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::small, nullptr);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "RemoveInlinePropertyAsAction() failed");
+  return rv;
 }
 
 /*****************************************************************************
  * mozilla::FontColorStateCommand
  *****************************************************************************/
 
 StaticRefPtr<FontColorStateCommand> FontColorStateCommand::sInstance;
 
@@ -727,36 +715,34 @@ nsresult FontColorStateCommand::GetCurre
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams.SetBool(STATE_MIXED, outMixed);
   aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   return NS_OK;
 }
 
 nsresult FontColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                         const nsString& newState) const {
+                                         const nsAString& aNewState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
+  if (aNewState.IsEmpty() || aNewState.EqualsLiteral("normal")) {
     nsresult rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::font,
                                                             nsGkAtoms::color);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   nsresult rv = aHTMLEditor->SetInlinePropertyAsAction(
-      *nsGkAtoms::font, nsGkAtoms::color, newState);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
+      *nsGkAtoms::font, nsGkAtoms::color, aNewState);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetInlinePropertyAsAction() failed");
+  return rv;
 }
 
 /*****************************************************************************
  * mozilla::HighlightColorStateCommand
  *****************************************************************************/
 
 StaticRefPtr<HighlightColorStateCommand> HighlightColorStateCommand::sInstance;
 
@@ -773,37 +759,35 @@ nsresult HighlightColorStateCommand::Get
 
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams.SetBool(STATE_MIXED, outMixed);
   aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   return NS_OK;
 }
 
-nsresult HighlightColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                              const nsString& newState) const {
+nsresult HighlightColorStateCommand::SetState(
+    HTMLEditor* aHTMLEditor, const nsAString& aNewState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
+  if (aNewState.IsEmpty() || aNewState.EqualsLiteral("normal")) {
     nsresult rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::font,
                                                             nsGkAtoms::bgcolor);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   nsresult rv = aHTMLEditor->SetInlinePropertyAsAction(
-      *nsGkAtoms::font, nsGkAtoms::bgcolor, newState);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
+      *nsGkAtoms::font, nsGkAtoms::bgcolor, aNewState);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetInlinePropertyAsAction() failed");
+  return rv;
 }
 
 /*****************************************************************************
  * mozilla::BackgroundColorStateCommand
  *****************************************************************************/
 
 StaticRefPtr<BackgroundColorStateCommand>
     BackgroundColorStateCommand::sInstance;
@@ -821,22 +805,24 @@ nsresult BackgroundColorStateCommand::Ge
 
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams.SetBool(STATE_MIXED, outMixed);
   aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   return NS_OK;
 }
 
-nsresult BackgroundColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                               const nsString& newState) const {
+nsresult BackgroundColorStateCommand::SetState(
+    HTMLEditor* aHTMLEditor, const nsAString& aNewState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
-  return aHTMLEditor->SetBackgroundColor(newState);
+  nsresult rv = aHTMLEditor->SetBackgroundColor(aNewState);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "SetBackgroundColor() failed");
+  return rv;
 }
 
 /*****************************************************************************
  * mozilla::AlignCommand
  *****************************************************************************/
 
 StaticRefPtr<AlignCommand> AlignCommand::sInstance;
 
@@ -874,21 +860,23 @@ nsresult AlignCommand::GetCurrentState(H
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
   aParams.SetBool(STATE_MIXED, outMixed);
   aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   return NS_OK;
 }
 
 nsresult AlignCommand::SetState(HTMLEditor* aHTMLEditor,
-                                const nsString& newState) const {
+                                const nsAString& aNewState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
-  return aHTMLEditor->Align(newState);
+  nsresult rv = aHTMLEditor->Align(aNewState);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Align() failed");
+  return rv;
 }
 
 /*****************************************************************************
  * mozilla::AbsolutePositioningCommand
  *****************************************************************************/
 
 StaticRefPtr<AbsolutePositioningCommand> AbsolutePositioningCommand::sInstance;
 
--- a/widget/CommandList.h
+++ b/widget/CommandList.h
@@ -126,16 +126,17 @@ NS_DEFINE_COMMAND(EditorObserverDocument
 NS_DEFINE_COMMAND(EditorObserverDocumentWillBeDestroyed,
                   obs_documentWillBeDestroyed)
 NS_DEFINE_COMMAND(FormatAbbreviation, cmd_abbr)
 NS_DEFINE_COMMAND(FormatAbsolutePosition, cmd_absPos)
 NS_DEFINE_COMMAND(FormatAcronym, cmd_acronym)
 NS_DEFINE_COMMAND(FormatCitation, cmd_cite)
 NS_DEFINE_COMMAND(FormatCode, cmd_code)
 NS_DEFINE_COMMAND(FormatDecreaseZIndex, cmd_decreaseZIndex)
+NS_DEFINE_COMMAND(FormatDocumentBackgroundColor, cmd_backgroundColor)
 NS_DEFINE_COMMAND(FormatEmphasis, cmd_em)
 NS_DEFINE_COMMAND(FormatIncreaseZIndex, cmd_increaseZIndex)
 NS_DEFINE_COMMAND(FormatNoBreak, cmd_nobreak)
 NS_DEFINE_COMMAND(FormatRemoveList, cmd_removeList)
 NS_DEFINE_COMMAND(FormatSample, cmd_samp)
 NS_DEFINE_COMMAND(FormatSetBlockTextDirection, cmd_switchTextDirection)
 NS_DEFINE_COMMAND(FormatStrong, cmd_strong)
 NS_DEFINE_COMMAND(FormatTeletypeText, cmd_tt)