Merge mozilla-central to mozilla-inbound
authorDorel Luca <dluca@mozilla.com>
Sun, 28 Apr 2019 12:48:29 +0300
changeset 530521 9b351485d6053fd46d4a39ea83a216dca42cecf7
parent 530520 e81669455530c9d127aafd89c1fdce308b183a68 (current diff)
parent 530513 3eb7623b5e63b37823d5e9c562d56e586604c823 (diff)
child 530522 053685dc2ce746e373ec6146621b231bed610874
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)
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
Merge mozilla-central to mozilla-inbound
editor/libeditor/HTMLEditorCommands.h
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -56,16 +56,17 @@
 #include "nsGkAtoms.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsAtom.h"
 #include "nsIBaseWindow.h"
 #include "nsICategoryManager.h"
 #include "nsIContentInlines.h"
 #include "nsIControllers.h"
 #include "mozilla/dom/Document.h"
+#include "mozilla/dom/DocumentInlines.h"
 #include "nsIDOMEventListener.h"
 #include "nsIFrameInlines.h"
 #include "nsILinkHandler.h"
 #include "mozilla/dom/NodeInfo.h"
 #include "mozilla/dom/NodeInfoInlines.h"
 #include "nsIPresShell.h"
 #include "nsIScriptError.h"
 #include "nsIScriptGlobalObject.h"
--- a/dom/websocket/WebSocket.cpp
+++ b/dom/websocket/WebSocket.cpp
@@ -27,16 +27,17 @@
 #include "nsGlobalWindow.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIDOMWindow.h"
 #include "mozilla/dom/Document.h"
 #include "nsXPCOM.h"
 #include "nsIXPConnect.h"
 #include "nsContentUtils.h"
 #include "nsError.h"
+#include "nsICookieSettings.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURL.h"
 #include "nsThreadUtils.h"
 #include "nsIPromptFactory.h"
 #include "nsIWindowWatcher.h"
 #include "nsIPrompt.h"
 #include "nsIStringBundle.h"
 #include "nsIConsoleService.h"
@@ -121,17 +122,18 @@ class WebSocketImpl final : public nsIIn
                 const nsACString& aScriptFile, uint32_t aScriptLine,
                 uint32_t aScriptColumn);
 
   nsresult AsyncOpen(nsIPrincipal* aPrincipal, uint64_t aInnerWindowID,
                      nsITransportProvider* aTransportProvider,
                      const nsACString& aNegotiatedExtensions);
 
   nsresult ParseURL(const nsAString& aURL);
-  nsresult InitializeConnection(nsIPrincipal* aPrincipal);
+  nsresult InitializeConnection(nsIPrincipal* aPrincipal,
+                                nsICookieSettings* aCookieSettings);
 
   // These methods when called can release the WebSocket object
   void FailConnection(uint16_t reasonCode,
                       const nsACString& aReasonString = EmptyCString());
   nsresult CloseConnection(uint16_t reasonCode,
                            const nsACString& aReasonString = EmptyCString());
   void Disconnect();
   void DisconnectInternal();
@@ -1088,27 +1090,28 @@ class ConnectRunnable final : public Web
 
  protected:
   virtual bool InitWithWindow(nsPIDOMWindowInner* aWindow) override {
     Document* doc = aWindow->GetExtantDoc();
     if (!doc) {
       return true;
     }
 
-    mConnectionFailed =
-        NS_FAILED(mImpl->InitializeConnection(doc->NodePrincipal()));
+    mConnectionFailed = NS_FAILED(mImpl->InitializeConnection(
+        doc->NodePrincipal(), mWorkerPrivate->CookieSettings()));
     return true;
   }
 
   virtual bool InitWindowless(WorkerPrivate* aTopLevelWorkerPrivate) override {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(aTopLevelWorkerPrivate && !aTopLevelWorkerPrivate->GetWindow());
 
     mConnectionFailed = NS_FAILED(
-        mImpl->InitializeConnection(aTopLevelWorkerPrivate->GetPrincipal()));
+        mImpl->InitializeConnection(aTopLevelWorkerPrivate->GetPrincipal(),
+                                    mWorkerPrivate->CookieSettings()));
     return true;
   }
 
   // Raw pointer. This worker runnable runs synchronously.
   WebSocketImpl* mImpl;
 
   bool mConnectionFailed;
 };
@@ -1253,21 +1256,23 @@ already_AddRefed<WebSocket> WebSocket::C
     aRv = webSocketImpl->Init(aGlobal.Context(), loadingPrincipal, principal,
                               !!aTransportProvider, aUrl, protocolArray,
                               EmptyCString(), 0, 0);
 
     if (NS_WARN_IF(aRv.Failed())) {
       return nullptr;
     }
 
+    nsCOMPtr<Document> doc = webSocket->GetDocumentIfCurrent();
+
     // the constructor should throw a SYNTAX_ERROR only if it fails to parse the
     // url parameter, so don't throw if InitializeConnection fails, and call
     // onerror/onclose asynchronously
-    connectionFailed =
-        NS_FAILED(webSocketImpl->InitializeConnection(principal));
+    connectionFailed = NS_FAILED(webSocketImpl->InitializeConnection(
+        principal, doc ? doc->CookieSettings() : nullptr));
   } else {
     WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     MOZ_ASSERT(workerPrivate);
 
     unsigned lineno, column;
     JS::AutoFilename file;
     if (!JS::DescribeScriptedCaller(aGlobal.Context(), &file, &lineno,
                                     &column)) {
@@ -1673,17 +1678,18 @@ class nsAutoCloseWS final {
           nsIWebSocketChannel::CLOSE_INTERNAL_ERROR);
     }
   }
 
  private:
   RefPtr<WebSocketImpl> mWebSocketImpl;
 };
 
-nsresult WebSocketImpl::InitializeConnection(nsIPrincipal* aPrincipal) {
+nsresult WebSocketImpl::InitializeConnection(
+    nsIPrincipal* aPrincipal, nsICookieSettings* aCookieSettings) {
   AssertIsOnMainThread();
   MOZ_ASSERT(!mChannel, "mChannel should be null");
 
   nsCOMPtr<nsIWebSocketChannel> wsChannel;
   nsAutoCloseWS autoClose(this);
   nsresult rv;
 
   if (mSecure) {
@@ -1716,20 +1722,20 @@ nsresult WebSocketImpl::InitializeConnec
   // are not thread-safe.
   mOriginDocument = nullptr;
 
   // The TriggeringPrincipal for websockets must always be a script.
   // Let's make sure that the doc's principal (if a doc exists)
   // and aPrincipal are same origin.
   MOZ_ASSERT(!doc || doc->NodePrincipal()->Equals(aPrincipal));
 
-  rv = wsChannel->InitLoadInfo(doc, doc ? doc->NodePrincipal() : aPrincipal,
-                               aPrincipal,
-                               nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
-                               nsIContentPolicy::TYPE_WEBSOCKET);
+  rv = wsChannel->InitLoadInfoNative(
+      doc, doc ? doc->NodePrincipal() : aPrincipal, aPrincipal, aCookieSettings,
+      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+      nsIContentPolicy::TYPE_WEBSOCKET);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 
   if (!mRequestedProtocolList.IsEmpty()) {
     rv = wsChannel->SetProtocol(mRequestedProtocolList);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(wsChannel);
--- a/editor/libeditor/EditorCommands.cpp
+++ b/editor/libeditor/EditorCommands.cpp
@@ -4,763 +4,575 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "EditorCommands.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/FlushType.h"
 #include "mozilla/TextEditor.h"
+#include "mozilla/dom/Document.h"
 #include "mozilla/dom/Selection.h"
 #include "nsCommandParams.h"
-#include "nsCOMPtr.h"
-#include "nsCRT.h"
-#include "nsDebug.h"
-#include "nsError.h"
 #include "nsIClipboard.h"
-#include "nsID.h"
-#include "mozilla/dom/Document.h"
-#include "nsIEditor.h"
+#include "nsIEditingSession.h"
 #include "nsISelectionController.h"
 #include "nsITransferable.h"
 #include "nsString.h"
 #include "nsAString.h"
 
 class nsISupports;
 
 #define STATE_ENABLED "state_enabled"
 #define STATE_DATA "state_data"
 
 namespace mozilla {
 
 /******************************************************************************
- * mozilla::EditorCommandBase
+ * mozilla::EditorCommand
  ******************************************************************************/
 
-EditorCommandBase::EditorCommandBase() {}
+NS_IMPL_ISUPPORTS(EditorCommand, nsIControllerCommand)
+
+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));
+  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()));
+  NS_WARNING_ASSERTION(
+      NS_SUCCEEDED(rv),
+      "Failed to do command from nsIControllerCommand::DoCommand()");
+  return rv;
+}
 
-NS_IMPL_ISUPPORTS(EditorCommandBase, nsIControllerCommand)
+NS_IMETHODIMP
+EditorCommand::DoCommandParams(const char* aCommandName,
+                               nsICommandParams* aParams,
+                               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()));
+  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);
+  }
+  nsCOMPtr<nsIEditingSession> editingSession =
+      do_QueryInterface(aCommandRefCon);
+  if (editingSession) {
+    return GetCommandStateParams(aCommandName,
+                                 MOZ_KnownLive(*aParams->AsCommandParams()),
+                                 nullptr, editingSession);
+  }
+  return GetCommandStateParams(aCommandName,
+                               MOZ_KnownLive(*aParams->AsCommandParams()),
+                               nullptr, nullptr);
+}
 
 /******************************************************************************
  * mozilla::UndoCommand
  ******************************************************************************/
 
 StaticRefPtr<UndoCommand> UndoCommand::sInstance;
 
-NS_IMETHODIMP
-UndoCommand::IsCommandEnabled(const char* aCommandName,
-                              nsISupports* aCommandRefCon, bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool UndoCommand::IsCommandEnabled(const char* aCommandName,
+                                   TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-
-  *aIsEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  if (!textEditor->IsSelectionEditable()) {
-    return NS_OK;
-  }
-  *aIsEnabled = textEditor->CanUndo();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable() && aTextEditor->CanUndo();
 }
 
-NS_IMETHODIMP
-UndoCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  // MOZ_KnownLive because we are holding a stack ref in "editor".
-  return MOZ_KnownLive(textEditor)->Undo(1);
+nsresult UndoCommand::DoCommand(const char* aCommandName,
+                                TextEditor& aTextEditor) const {
+  return aTextEditor.Undo(1);
 }
 
-NS_IMETHODIMP
-UndoCommand::DoCommandParams(const char* aCommandName,
-                             nsICommandParams* aParams,
-                             nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult UndoCommand::DoCommandParams(const char* aCommandName,
+                                      nsCommandParams* aParams,
+                                      TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-UndoCommand::GetCommandStateParams(const char* aCommandName,
-                                   nsICommandParams* aParams,
-                                   nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult UndoCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::RedoCommand
  ******************************************************************************/
 
 StaticRefPtr<RedoCommand> RedoCommand::sInstance;
 
-NS_IMETHODIMP
-RedoCommand::IsCommandEnabled(const char* aCommandName,
-                              nsISupports* aCommandRefCon, bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool RedoCommand::IsCommandEnabled(const char* aCommandName,
+                                   TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-
-  *aIsEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  if (!textEditor->IsSelectionEditable()) {
-    return NS_OK;
-  }
-  *aIsEnabled = textEditor->CanRedo();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable() && aTextEditor->CanRedo();
 }
 
-NS_IMETHODIMP
-RedoCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  // MOZ_KnownLive because we are holding a stack ref in "editor".
-  return MOZ_KnownLive(textEditor)->Redo(1);
+nsresult RedoCommand::DoCommand(const char* aCommandName,
+                                TextEditor& aTextEditor) const {
+  return aTextEditor.Redo(1);
 }
 
-NS_IMETHODIMP
-RedoCommand::DoCommandParams(const char* aCommandName,
-                             nsICommandParams* aParams,
-                             nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult RedoCommand::DoCommandParams(const char* aCommandName,
+                                      nsCommandParams* aParams,
+                                      TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-RedoCommand::GetCommandStateParams(const char* aCommandName,
-                                   nsICommandParams* aParams,
-                                   nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult RedoCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::CutCommand
  ******************************************************************************/
 
 StaticRefPtr<CutCommand> CutCommand::sInstance;
 
-NS_IMETHODIMP
-CutCommand::IsCommandEnabled(const char* aCommandName,
-                             nsISupports* aCommandRefCon, bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool CutCommand::IsCommandEnabled(const char* aCommandName,
+                                  TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-
-  *aIsEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  if (!textEditor->IsSelectionEditable()) {
-    return NS_OK;
-  }
-  *aIsEnabled = textEditor->CanCut();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable() && aTextEditor->CanCut();
 }
 
-NS_IMETHODIMP
-CutCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  return textEditor->Cut();
+nsresult CutCommand::DoCommand(const char* aCommandName,
+                               TextEditor& aTextEditor) const {
+  return aTextEditor.Cut();
 }
 
-NS_IMETHODIMP
-CutCommand::DoCommandParams(const char* aCommandName, nsICommandParams* aParams,
-                            nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult CutCommand::DoCommandParams(const char* aCommandName,
+                                     nsCommandParams* aParams,
+                                     TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-CutCommand::GetCommandStateParams(const char* aCommandName,
-                                  nsICommandParams* aParams,
-                                  nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult CutCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::CutOrDeleteCommand
  ******************************************************************************/
 
 StaticRefPtr<CutOrDeleteCommand> CutOrDeleteCommand::sInstance;
 
-NS_IMETHODIMP
-CutOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
-                                     nsISupports* aCommandRefCon,
-                                     bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool CutOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
+                                          TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    *aIsEnabled = false;
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  *aIsEnabled = textEditor->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-CutOrDeleteCommand::DoCommand(const char* aCommandName,
-                              nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  dom::Selection* selection = textEditor->GetSelection();
+nsresult CutOrDeleteCommand::DoCommand(const char* aCommandName,
+                                       TextEditor& aTextEditor) const {
+  dom::Selection* selection = aTextEditor.GetSelection();
   if (selection && selection->IsCollapsed()) {
-    nsresult rv = textEditor->DeleteSelectionAsAction(nsIEditor::eNext,
+    nsresult rv = aTextEditor.DeleteSelectionAsAction(nsIEditor::eNext,
                                                       nsIEditor::eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
-  return textEditor->Cut();
+  return aTextEditor.Cut();
 }
 
-NS_IMETHODIMP
-CutOrDeleteCommand::DoCommandParams(const char* aCommandName,
-                                    nsICommandParams* aParams,
-                                    nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult CutOrDeleteCommand::DoCommandParams(const char* aCommandName,
+                                             nsCommandParams* aParams,
+                                             TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-CutOrDeleteCommand::GetCommandStateParams(const char* aCommandName,
-                                          nsICommandParams* aParams,
-                                          nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult CutOrDeleteCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::CopyCommand
  ******************************************************************************/
 
 StaticRefPtr<CopyCommand> CopyCommand::sInstance;
 
-NS_IMETHODIMP
-CopyCommand::IsCommandEnabled(const char* aCommandName,
-                              nsISupports* aCommandRefCon, bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool CopyCommand::IsCommandEnabled(const char* aCommandName,
+                                   TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    *aIsEnabled = false;
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  *aIsEnabled = textEditor->CanCopy();
-  return NS_OK;
+  return aTextEditor->CanCopy();
 }
 
-NS_IMETHODIMP
-CopyCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  return textEditor->Copy();
+nsresult CopyCommand::DoCommand(const char* aCommandName,
+                                TextEditor& aTextEditor) const {
+  return aTextEditor.Copy();
 }
 
-NS_IMETHODIMP
-CopyCommand::DoCommandParams(const char* aCommandName,
-                             nsICommandParams* aParams,
-                             nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult CopyCommand::DoCommandParams(const char* aCommandName,
+                                      nsCommandParams* aParams,
+                                      TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-CopyCommand::GetCommandStateParams(const char* aCommandName,
-                                   nsICommandParams* aParams,
-                                   nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult CopyCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::CopyOrDeleteCommand
  ******************************************************************************/
 
 StaticRefPtr<CopyOrDeleteCommand> CopyOrDeleteCommand::sInstance;
 
-NS_IMETHODIMP
-CopyOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
-                                      nsISupports* aCommandRefCon,
-                                      bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool CopyOrDeleteCommand::IsCommandEnabled(const char* aCommandName,
+                                           TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    *aIsEnabled = false;
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  *aIsEnabled = textEditor->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-CopyOrDeleteCommand::DoCommand(const char* aCommandName,
-                               nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  dom::Selection* selection = textEditor->GetSelection();
+nsresult CopyOrDeleteCommand::DoCommand(const char* aCommandName,
+                                        TextEditor& aTextEditor) const {
+  dom::Selection* selection = aTextEditor.GetSelection();
   if (selection && selection->IsCollapsed()) {
-    nsresult rv = textEditor->DeleteSelectionAsAction(nsIEditor::eNextWord,
+    nsresult rv = aTextEditor.DeleteSelectionAsAction(nsIEditor::eNextWord,
                                                       nsIEditor::eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
-  return textEditor->Copy();
+  return aTextEditor.Copy();
 }
 
-NS_IMETHODIMP
-CopyOrDeleteCommand::DoCommandParams(const char* aCommandName,
-                                     nsICommandParams* aParams,
-                                     nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult CopyOrDeleteCommand::DoCommandParams(const char* aCommandName,
+                                              nsCommandParams* aParams,
+                                              TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-CopyOrDeleteCommand::GetCommandStateParams(const char* aCommandName,
-                                           nsICommandParams* aParams,
-                                           nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult CopyOrDeleteCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::PasteCommand
  ******************************************************************************/
 
 StaticRefPtr<PasteCommand> PasteCommand::sInstance;
 
-NS_IMETHODIMP
-PasteCommand::IsCommandEnabled(const char* aCommandName,
-                               nsISupports* aCommandRefCon, bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool PasteCommand::IsCommandEnabled(const char* aCommandName,
+                                    TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-
-  *aIsEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  if (!textEditor->IsSelectionEditable()) {
-    return NS_OK;
-  }
-  *aIsEnabled = textEditor->CanPaste(nsIClipboard::kGlobalClipboard);
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable() &&
+         aTextEditor->CanPaste(nsIClipboard::kGlobalClipboard);
 }
 
-NS_IMETHODIMP
-PasteCommand::DoCommand(const char* aCommandName, nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  // MOZ_KnownLive because we are holding a stack ref in "editor".
-  return MOZ_KnownLive(textEditor)
-      ->PasteAsAction(nsIClipboard::kGlobalClipboard, true);
+nsresult PasteCommand::DoCommand(const char* aCommandName,
+                                 TextEditor& aTextEditor) const {
+  return aTextEditor.PasteAsAction(nsIClipboard::kGlobalClipboard, true);
 }
 
-NS_IMETHODIMP
-PasteCommand::DoCommandParams(const char* aCommandName,
-                              nsICommandParams* aParams,
-                              nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult PasteCommand::DoCommandParams(const char* aCommandName,
+                                       nsCommandParams* aParams,
+                                       TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-PasteCommand::GetCommandStateParams(const char* aCommandName,
-                                    nsICommandParams* aParams,
-                                    nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult PasteCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::PasteTransferableCommand
  ******************************************************************************/
 
 StaticRefPtr<PasteTransferableCommand> PasteTransferableCommand::sInstance;
 
-NS_IMETHODIMP
-PasteTransferableCommand::IsCommandEnabled(const char* aCommandName,
-                                           nsISupports* aCommandRefCon,
-                                           bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
+bool PasteTransferableCommand::IsCommandEnabled(const char* aCommandName,
+                                                TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
+  }
+  return aTextEditor->IsSelectionEditable() &&
+         aTextEditor->CanPasteTransferable(nullptr);
+}
+
+nsresult PasteTransferableCommand::DoCommand(const char* aCommandName,
+                                             TextEditor& aTextEditor) const {
+  return NS_ERROR_FAILURE;
+}
+
+nsresult PasteTransferableCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
+  if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  *aIsEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  if (!textEditor->IsSelectionEditable()) {
-    return NS_OK;
-  }
-  *aIsEnabled = textEditor->CanPasteTransferable(nullptr);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-PasteTransferableCommand::DoCommand(const char* aCommandName,
-                                    nsISupports* aCommandRefCon) {
-  return NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
-PasteTransferableCommand::DoCommandParams(const char* aCommandName,
-                                          nsICommandParams* aParams,
-                                          nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsISupports> supports =
-      aParams->AsCommandParams()->GetISupports("transferable");
+  nsCOMPtr<nsISupports> supports = aParams->GetISupports("transferable");
   if (NS_WARN_IF(!supports)) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsITransferable> trans = do_QueryInterface(supports);
   if (NS_WARN_IF(!trans)) {
     return NS_ERROR_FAILURE;
   }
 
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
   // We know textEditor is known-live here because we are holding a ref to it
   // via "editor".
-  nsresult rv = MOZ_KnownLive(textEditor)->PasteTransferable(trans);
+  nsresult rv = aTextEditor.PasteTransferable(trans);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-PasteTransferableCommand::GetCommandStateParams(const char* aCommandName,
-                                                nsICommandParams* aParams,
-                                                nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
+nsresult PasteTransferableCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  if (NS_WARN_IF(!aTextEditor)) {
+    return NS_ERROR_INVALID_ARG;
   }
 
-  nsCOMPtr<nsISupports> supports =
-      aParams->AsCommandParams()->GetISupports("transferable");
+  nsCOMPtr<nsISupports> supports = aParams.GetISupports("transferable");
   if (NS_WARN_IF(!supports)) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsITransferable> trans;
   trans = do_QueryInterface(supports);
   if (NS_WARN_IF(!trans)) {
     return NS_ERROR_FAILURE;
   }
 
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-
-  return aParams->AsCommandParams()->SetBool(
-      STATE_ENABLED, textEditor->CanPasteTransferable(trans));
+  return aParams.SetBool(STATE_ENABLED,
+                         aTextEditor->CanPasteTransferable(trans));
 }
 
 /******************************************************************************
  * mozilla::SwitchTextDirectionCommand
  ******************************************************************************/
 
 StaticRefPtr<SwitchTextDirectionCommand> SwitchTextDirectionCommand::sInstance;
 
-NS_IMETHODIMP
-SwitchTextDirectionCommand::IsCommandEnabled(const char* aCommandName,
-                                             nsISupports* aCommandRefCon,
-                                             bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool SwitchTextDirectionCommand::IsCommandEnabled(
+    const char* aCommandName, TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    *aIsEnabled = false;
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  *aIsEnabled = textEditor->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-SwitchTextDirectionCommand::DoCommand(const char* aCommandName,
-                                      nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  // MOZ_KnownLive because we are holding a stack ref in "editor".
-  return MOZ_KnownLive(textEditor)->ToggleTextDirection();
+nsresult SwitchTextDirectionCommand::DoCommand(const char* aCommandName,
+                                               TextEditor& aTextEditor) const {
+  return aTextEditor.ToggleTextDirection();
 }
 
-NS_IMETHODIMP
-SwitchTextDirectionCommand::DoCommandParams(const char* aCommandName,
-                                            nsICommandParams* aParams,
-                                            nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult SwitchTextDirectionCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-SwitchTextDirectionCommand::GetCommandStateParams(const char* aCommandName,
-                                                  nsICommandParams* aParams,
-                                                  nsISupports* aCommandRefCon) {
-  bool canSwitchTextDirection = true;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canSwitchTextDirection);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED,
-                                             canSwitchTextDirection);
+nsresult SwitchTextDirectionCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::DeleteCommand
  ******************************************************************************/
 
 StaticRefPtr<DeleteCommand> DeleteCommand::sInstance;
 
-NS_IMETHODIMP
-DeleteCommand::IsCommandEnabled(const char* aCommandName,
-                                nsISupports* aCommandRefCon, bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool DeleteCommand::IsCommandEnabled(const char* aCommandName,
+                                     TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-
-  *aIsEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
-  }
-
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-
   // 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.
-  *aIsEnabled = textEditor->IsSelectionEditable();
+  bool isEnabled = aTextEditor->IsSelectionEditable();
 
-  if (!nsCRT::strcmp("cmd_delete", aCommandName) && *aIsEnabled) {
-    *aIsEnabled = textEditor->CanDelete();
+  if (!nsCRT::strcmp("cmd_delete", aCommandName) && isEnabled) {
+    return aTextEditor->CanDelete();
   }
-  return NS_OK;
+  return isEnabled;
 }
 
-NS_IMETHODIMP
-DeleteCommand::DoCommand(const char* aCommandName,
-                         nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-
+nsresult DeleteCommand::DoCommand(const char* aCommandName,
+                                  TextEditor& aTextEditor) const {
   nsIEditor::EDirection deleteDir = nsIEditor::eNone;
-
-  if (!nsCRT::strcmp("cmd_delete", aCommandName)) {
+  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 (!nsCRT::strcmp("cmd_deleteCharForward", aCommandName)) {
+  } else if (!strcmp("cmd_deleteCharForward", aCommandName)) {
     deleteDir = nsIEditor::eNext;
-  } else if (!nsCRT::strcmp("cmd_deleteCharBackward", aCommandName)) {
+  } else if (!strcmp("cmd_deleteCharBackward", aCommandName)) {
     deleteDir = nsIEditor::ePrevious;
-  } else if (!nsCRT::strcmp("cmd_deleteWordBackward", aCommandName)) {
+  } else if (!strcmp("cmd_deleteWordBackward", aCommandName)) {
     deleteDir = nsIEditor::ePreviousWord;
-  } else if (!nsCRT::strcmp("cmd_deleteWordForward", aCommandName)) {
+  } else if (!strcmp("cmd_deleteWordForward", aCommandName)) {
     deleteDir = nsIEditor::eNextWord;
-  } else if (!nsCRT::strcmp("cmd_deleteToBeginningOfLine", aCommandName)) {
+  } else if (!strcmp("cmd_deleteToBeginningOfLine", aCommandName)) {
     deleteDir = nsIEditor::eToBeginningOfLine;
-  } else if (!nsCRT::strcmp("cmd_deleteToEndOfLine", aCommandName)) {
+  } else if (!strcmp("cmd_deleteToEndOfLine", aCommandName)) {
     deleteDir = nsIEditor::eToEndOfLine;
   } else {
     MOZ_CRASH("Unrecognized nsDeleteCommand");
   }
-
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
   nsresult rv =
-      textEditor->DeleteSelectionAsAction(deleteDir, nsIEditor::eStrip);
+      aTextEditor.DeleteSelectionAsAction(deleteDir, nsIEditor::eStrip);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-DeleteCommand::DoCommandParams(const char* aCommandName,
-                               nsICommandParams* aParams,
-                               nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult DeleteCommand::DoCommandParams(const char* aCommandName,
+                                        nsCommandParams* aParams,
+                                        TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-DeleteCommand::GetCommandStateParams(const char* aCommandName,
-                                     nsICommandParams* aParams,
-                                     nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult DeleteCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::SelectAllCommand
  ******************************************************************************/
 
 StaticRefPtr<SelectAllCommand> SelectAllCommand::sInstance;
 
-NS_IMETHODIMP
-SelectAllCommand::IsCommandEnabled(const char* aCommandName,
-                                   nsISupports* aCommandRefCon,
-                                   bool* aIsEnabled) {
-  NS_ENSURE_ARG_POINTER(aIsEnabled);
-
-  nsresult rv = NS_OK;
+bool SelectAllCommand::IsCommandEnabled(const char* aCommandName,
+                                        TextEditor* aTextEditor) const {
   // You can always select all, unless the selection is editable,
   // and the editable region is empty!
-  *aIsEnabled = true;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
+  if (!aTextEditor) {
+    return true;
   }
 
   // You can select all if there is an editor which is non-empty
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
   bool isEmpty = false;
-  rv = textEditor->IsEmpty(&isEmpty);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
+  if (NS_WARN_IF(NS_FAILED(aTextEditor->IsEmpty(&isEmpty)))) {
+    return false;
   }
-  *aIsEnabled = !isEmpty;
-  return NS_OK;
+  return !isEmpty;
+}
+
+nsresult SelectAllCommand::DoCommand(const char* aCommandName,
+                                     TextEditor& aTextEditor) const {
+  return aTextEditor.SelectAll();
 }
 
-NS_IMETHODIMP
-SelectAllCommand::DoCommand(const char* aCommandName,
-                            nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  return MOZ_KnownLive(textEditor)->SelectAll();
+nsresult SelectAllCommand::DoCommandParams(const char* aCommandName,
+                                           nsCommandParams* aParams,
+                                           TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-SelectAllCommand::DoCommandParams(const char* aCommandName,
-                                  nsICommandParams* aParams,
-                                  nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
-}
-
-NS_IMETHODIMP
-SelectAllCommand::GetCommandStateParams(const char* aCommandName,
-                                        nsICommandParams* aParams,
-                                        nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult SelectAllCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::SelectionMoveCommands
  ******************************************************************************/
 
 StaticRefPtr<SelectionMoveCommands> SelectionMoveCommands::sInstance;
 
-NS_IMETHODIMP
-SelectionMoveCommands::IsCommandEnabled(const char* aCommandName,
-                                        nsISupports* aCommandRefCon,
-                                        bool* aIsEnabled) {
-  NS_ENSURE_ARG_POINTER(aIsEnabled);
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    *aIsEnabled = false;
-    return NS_OK;
+bool SelectionMoveCommands::IsCommandEnabled(const char* aCommandName,
+                                             TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  *aIsEnabled = textEditor->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
 static const struct ScrollCommand {
   const char* reverseScroll;
   const char* forwardScroll;
   nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
 } scrollCommands[] = {{"cmd_scrollTop", "cmd_scrollBottom",
                        &nsISelectionController::CompleteScroll},
@@ -800,380 +612,248 @@ static const struct PhysicalCommand {
     {"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}};
 
-NS_IMETHODIMP
-SelectionMoveCommands::DoCommand(const char* aCommandName,
-                                 nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  RefPtr<Document> doc = textEditor->GetDocument();
-  if (doc) {
+nsresult SelectionMoveCommands::DoCommand(const char* aCommandName,
+                                          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.
-    doc->FlushPendingNotifications(FlushType::Layout);
+    document->FlushPendingNotifications(FlushType::Layout);
   }
 
   nsCOMPtr<nsISelectionController> selectionController =
-      textEditor->GetSelectionController();
+      aTextEditor.GetSelectionController();
   if (NS_WARN_IF(!selectionController)) {
     return NS_ERROR_FAILURE;
   }
 
   // scroll commands
-  for (size_t i = 0; i < mozilla::ArrayLength(scrollCommands); i++) {
+  for (size_t i = 0; i < ArrayLength(scrollCommands); i++) {
     const ScrollCommand& cmd = scrollCommands[i];
-    if (!nsCRT::strcmp(aCommandName, cmd.reverseScroll)) {
+    if (!strcmp(aCommandName, cmd.reverseScroll)) {
       return (selectionController->*(cmd.scroll))(false);
-    } else if (!nsCRT::strcmp(aCommandName, cmd.forwardScroll)) {
+    } else if (!strcmp(aCommandName, cmd.forwardScroll)) {
       return (selectionController->*(cmd.scroll))(true);
     }
   }
 
   // caret movement/selection commands
-  for (size_t i = 0; i < mozilla::ArrayLength(moveCommands); i++) {
+  for (size_t i = 0; i < ArrayLength(moveCommands); i++) {
     const MoveCommand& cmd = moveCommands[i];
-    if (!nsCRT::strcmp(aCommandName, cmd.reverseMove)) {
+    if (!strcmp(aCommandName, cmd.reverseMove)) {
       return (selectionController->*(cmd.move))(false, false);
-    } else if (!nsCRT::strcmp(aCommandName, cmd.forwardMove)) {
+    } else if (!strcmp(aCommandName, cmd.forwardMove)) {
       return (selectionController->*(cmd.move))(true, false);
-    } else if (!nsCRT::strcmp(aCommandName, cmd.reverseSelect)) {
+    } else if (!strcmp(aCommandName, cmd.reverseSelect)) {
       return (selectionController->*(cmd.move))(false, true);
-    } else if (!nsCRT::strcmp(aCommandName, cmd.forwardSelect)) {
+    } else if (!strcmp(aCommandName, cmd.forwardSelect)) {
       return (selectionController->*(cmd.move))(true, true);
     }
   }
 
   // physical-direction movement/selection
-  for (size_t i = 0; i < mozilla::ArrayLength(physicalCommands); i++) {
+  for (size_t i = 0; i < ArrayLength(physicalCommands); i++) {
     const PhysicalCommand& cmd = physicalCommands[i];
-    if (!nsCRT::strcmp(aCommandName, cmd.move)) {
+    if (!strcmp(aCommandName, cmd.move)) {
       return selectionController->PhysicalMove(cmd.direction, cmd.amount,
                                                false);
-    } else if (!nsCRT::strcmp(aCommandName, cmd.select)) {
+    } else if (!strcmp(aCommandName, cmd.select)) {
       return selectionController->PhysicalMove(cmd.direction, cmd.amount, true);
     }
   }
 
   return NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP
-SelectionMoveCommands::DoCommandParams(const char* aCommandName,
-                                       nsICommandParams* aParams,
-                                       nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult SelectionMoveCommands::DoCommandParams(const char* aCommandName,
+                                                nsCommandParams* aParams,
+                                                TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-SelectionMoveCommands::GetCommandStateParams(const char* aCommandName,
-                                             nsICommandParams* aParams,
-                                             nsISupports* aCommandRefCon) {
-  bool canUndo;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &canUndo);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, canUndo);
+nsresult SelectionMoveCommands::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::InsertPlaintextCommand
  ******************************************************************************/
 
 StaticRefPtr<InsertPlaintextCommand> InsertPlaintextCommand::sInstance;
 
-NS_IMETHODIMP
-InsertPlaintextCommand::IsCommandEnabled(const char* aCommandName,
-                                         nsISupports* aCommandRefCon,
-                                         bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool InsertPlaintextCommand::IsCommandEnabled(const char* aCommandName,
+                                              TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    *aIsEnabled = false;
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  *aIsEnabled = textEditor->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-InsertPlaintextCommand::DoCommand(const char* aCommandName,
-                                  nsISupports* aCommandRefCon) {
-  // No value is equivalent to empty string
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
+nsresult InsertPlaintextCommand::DoCommand(const char* aCommandName,
+                                           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 = textEditor->InsertTextAsAction(EmptyString());
+  DebugOnly<nsresult> rv = aTextEditor.InsertTextAsAction(EmptyString());
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert empty string");
   return NS_OK;
 }
 
-NS_IMETHODIMP
-InsertPlaintextCommand::DoCommandParams(const char* aCommandName,
-                                        nsICommandParams* aParams,
-                                        nsISupports* aCommandRefCon) {
+nsresult InsertPlaintextCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
   if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-
   // Get text to insert from command params
   nsAutoString text;
-  nsresult rv = aParams->AsCommandParams()->GetString(STATE_DATA, text);
+  nsresult rv = aParams->GetString(STATE_DATA, text);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
   // 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.
-  rv = textEditor->InsertTextAsAction(text);
+  rv = aTextEditor.InsertTextAsAction(text);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert the text");
   return NS_OK;
 }
 
-NS_IMETHODIMP
-InsertPlaintextCommand::GetCommandStateParams(const char* aCommandName,
-                                              nsICommandParams* aParams,
-                                              nsISupports* aCommandRefCon) {
-  if (NS_WARN_IF(!aParams)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  bool aIsEnabled = false;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, aIsEnabled);
+nsresult InsertPlaintextCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::InsertParagraphCommand
  ******************************************************************************/
 
 StaticRefPtr<InsertParagraphCommand> InsertParagraphCommand::sInstance;
 
-NS_IMETHODIMP
-InsertParagraphCommand::IsCommandEnabled(const char* aCommandName,
-                                         nsISupports* aCommandRefCon,
-                                         bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool InsertParagraphCommand::IsCommandEnabled(const char* aCommandName,
+                                              TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    *aIsEnabled = false;
-    return NS_ERROR_FAILURE;
-  }
-
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  *aIsEnabled = textEditor->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-InsertParagraphCommand::DoCommand(const char* aCommandName,
-                                  nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult InsertParagraphCommand::DoCommand(const char* aCommandName,
+                                           TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;  // Do nothing for now.
   }
   return htmlEditor->InsertParagraphSeparatorAsAction();
 }
 
-NS_IMETHODIMP
-InsertParagraphCommand::DoCommandParams(const char* aCommandName,
-                                        nsICommandParams* aParams,
-                                        nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult InsertParagraphCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-InsertParagraphCommand::GetCommandStateParams(const char* aCommandName,
-                                              nsICommandParams* aParams,
-                                              nsISupports* aCommandRefCon) {
-  if (NS_WARN_IF(!aParams)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  bool aIsEnabled = false;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, aIsEnabled);
+nsresult InsertParagraphCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::InsertLineBreakCommand
  ******************************************************************************/
 
 StaticRefPtr<InsertLineBreakCommand> InsertLineBreakCommand::sInstance;
 
-NS_IMETHODIMP
-InsertLineBreakCommand::IsCommandEnabled(const char* aCommandName,
-                                         nsISupports* aCommandRefCon,
-                                         bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool InsertLineBreakCommand::IsCommandEnabled(const char* aCommandName,
+                                              TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    *aIsEnabled = false;
-    return NS_ERROR_FAILURE;
-  }
-
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  *aIsEnabled = textEditor->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-InsertLineBreakCommand::DoCommand(const char* aCommandName,
-                                  nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult InsertLineBreakCommand::DoCommand(const char* aCommandName,
+                                           TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_ERROR_FAILURE;
   }
   return htmlEditor->InsertLineBreakAsAction();
 }
 
-NS_IMETHODIMP
-InsertLineBreakCommand::DoCommandParams(const char* aCommandName,
-                                        nsICommandParams* aParams,
-                                        nsISupports* aCommandRefCon) {
-  return DoCommand(aCommandName, aCommandRefCon);
+nsresult InsertLineBreakCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-InsertLineBreakCommand::GetCommandStateParams(const char* aCommandName,
-                                              nsICommandParams* aParams,
-                                              nsISupports* aCommandRefCon) {
-  if (NS_WARN_IF(!aParams)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  bool aIsEnabled = false;
-  IsCommandEnabled(aCommandName, aCommandRefCon, &aIsEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, aIsEnabled);
+nsresult InsertLineBreakCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /******************************************************************************
  * mozilla::PasteQuotationCommand
  ******************************************************************************/
 
 StaticRefPtr<PasteQuotationCommand> PasteQuotationCommand::sInstance;
 
-NS_IMETHODIMP
-PasteQuotationCommand::IsCommandEnabled(const char* aCommandName,
-                                        nsISupports* aCommandRefCon,
-                                        bool* aIsEnabled) {
-  if (NS_WARN_IF(!aIsEnabled)) {
-    return NS_ERROR_INVALID_ARG;
+bool PasteQuotationCommand::IsCommandEnabled(const char* aCommandName,
+                                             TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-
-  *aIsEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  if (textEditor->IsSingleLineEditor()) {
-    return NS_OK;
-  }
-  *aIsEnabled = textEditor->CanPaste(nsIClipboard::kGlobalClipboard);
-  return NS_OK;
+  return !aTextEditor->IsSingleLineEditor() &&
+         aTextEditor->CanPaste(nsIClipboard::kGlobalClipboard);
 }
 
-NS_IMETHODIMP
-PasteQuotationCommand::DoCommand(const char* aCommandName,
-                                 nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  // MOZ_KnownLive because we are holding a stack ref in "editor".
-  nsresult rv =
-      MOZ_KnownLive(textEditor)
-          ->PasteAsQuotationAsAction(nsIClipboard::kGlobalClipboard, true);
+nsresult PasteQuotationCommand::DoCommand(const char* aCommandName,
+                                          TextEditor& aTextEditor) const {
+  nsresult rv = aTextEditor.PasteAsQuotationAsAction(
+      nsIClipboard::kGlobalClipboard, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-PasteQuotationCommand::DoCommandParams(const char* aCommandName,
-                                       nsICommandParams* aParams,
-                                       nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_ERROR_FAILURE;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  // MOZ_KnownLive because we are holding a stack ref in "editor".
-  nsresult rv =
-      MOZ_KnownLive(textEditor)
-          ->PasteAsQuotationAsAction(nsIClipboard::kGlobalClipboard, true);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
+nsresult PasteQuotationCommand::DoCommandParams(const char* aCommandName,
+                                                nsCommandParams* aParams,
+                                                TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-PasteQuotationCommand::GetCommandStateParams(const char* aCommandName,
-                                             nsICommandParams* aParams,
-                                             nsISupports* aCommandRefCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
+nsresult PasteQuotationCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  if (!aTextEditor) {
     return NS_OK;
   }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-  aParams->AsCommandParams()->SetBool(
-      STATE_ENABLED, textEditor->CanPaste(nsIClipboard::kGlobalClipboard));
+  aParams.SetBool(STATE_ENABLED,
+                  aTextEditor->CanPaste(nsIClipboard::kGlobalClipboard));
   return NS_OK;
 }
 
 }  // namespace mozilla
--- a/editor/libeditor/EditorCommands.h
+++ b/editor/libeditor/EditorCommands.h
@@ -1,79 +1,132 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef EditorCommands_h_
-#define EditorCommands_h_
+#ifndef mozilla_EditorCommands_h
+#define mozilla_EditorCommands_h
 
 #include "mozilla/StaticPtr.h"
 #include "nsIControllerCommand.h"
 #include "nsISupportsImpl.h"
-#include "nscore.h"
+#include "nsRefPtrHashtable.h"
+#include "nsStringFwd.h"
 
+class nsAtom;
+class nsCommandParams;
 class nsICommandParams;
-class nsISupports;
+class nsIEditingSession;
 
 namespace mozilla {
 
+class HTMLEditor;
+class TextEditor;
+
 /**
  * This is a base class for commands registered with the editor controller.
  * Note that such commands are designed as singleton classes.  So, MUST be
  * stateless. Any state must be stored via the refCon (an nsIEditor).
  */
 
-class EditorCommandBase : public nsIControllerCommand {
+class EditorCommand : public nsIControllerCommand {
  public:
   NS_DECL_ISUPPORTS
 
+  // nsIControllerCommand methods.  Use EditorCommand specific methods instead
+  // for internal use.
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   NS_IMETHOD IsCommandEnabled(const char* aCommandName,
                               nsISupports* aCommandRefCon,
-                              bool* aIsEnabled) override = 0;
+                              bool* aIsEnabled) final;
   MOZ_CAN_RUN_SCRIPT
   NS_IMETHOD DoCommand(const char* aCommandName,
-                       nsISupports* aCommandRefCon) override = 0;
+                       nsISupports* aCommandRefCon) final;
+  MOZ_CAN_RUN_SCRIPT
+  NS_IMETHOD DoCommandParams(const char* aCommandName,
+                             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,
+                                TextEditor* aTextEditor) const = 0;
+  MOZ_CAN_RUN_SCRIPT
+  virtual nsresult DoCommand(const char* aCommandName,
+                             TextEditor& aTextEditor) const = 0;
+  MOZ_CAN_RUN_SCRIPT
+  virtual nsresult DoCommandParams(const char* aCommandName,
+                                   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;
 
  protected:
-  EditorCommandBase();
-  virtual ~EditorCommandBase() {}
+  EditorCommand() = default;
+  virtual ~EditorCommand() = default;
 };
 
-#define NS_DECL_EDITOR_COMMAND(_cmd)                                        \
-  class _cmd final : public EditorCommandBase {                             \
-   public:                                                                  \
-    NS_IMETHOD IsCommandEnabled(const char* aCommandName,                   \
-                                nsISupports* aCommandRefCon,                \
-                                bool* aIsEnabled) override;                 \
-    MOZ_CAN_RUN_SCRIPT                                                      \
-    NS_IMETHOD DoCommand(const char* aCommandName,                          \
-                         nsISupports* aCommandRefCon) override;             \
-    MOZ_CAN_RUN_SCRIPT                                                      \
-    NS_IMETHOD DoCommandParams(const char* aCommandName,                    \
-                               nsICommandParams* aParams,                   \
-                               nsISupports* aCommandRefCon) override;       \
-    NS_IMETHOD GetCommandStateParams(const char* aCommandName,              \
-                                     nsICommandParams* aParams,             \
-                                     nsISupports* aCommandRefCon) override; \
-    static _cmd* GetInstance() {                                            \
-      if (!sInstance) {                                                     \
-        sInstance = new _cmd();                                             \
-      }                                                                     \
-      return sInstance;                                                     \
-    }                                                                       \
-                                                                            \
-    static void Shutdown() { sInstance = nullptr; }                         \
-                                                                            \
-   protected:                                                               \
-    _cmd() = default;                                                       \
-    virtual ~_cmd() = default;                                              \
-                                                                            \
-   private:                                                                 \
-    static StaticRefPtr<_cmd> sInstance;                                    \
+#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;                                                       \
+  using EditorCommand::GetCommandStateParams;
+
+#define NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(_cmd) \
+ public:                                                   \
+  static _cmd* GetInstance() {                             \
+    if (!sInstance) {                                      \
+      sInstance = new _cmd();                              \
+    }                                                      \
+    return sInstance;                                      \
+  }                                                        \
+                                                           \
+  static void Shutdown() { sInstance = nullptr; }          \
+                                                           \
+ private:                                                  \
+  static StaticRefPtr<_cmd> sInstance;
+
+#define NS_DECL_EDITOR_COMMAND(_cmd)                   \
+  class _cmd final : public EditorCommand {            \
+    NS_DECL_EDITOR_COMMAND_METHODS(_cmd)               \
+    NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(_cmd) \
+                                                       \
+   protected:                                          \
+    _cmd() = default;                                  \
+    virtual ~_cmd() = default;                         \
   };
 
 // basic editor commands
 NS_DECL_EDITOR_COMMAND(UndoCommand)
 NS_DECL_EDITOR_COMMAND(RedoCommand)
 
 NS_DECL_EDITOR_COMMAND(CutCommand)
 NS_DECL_EDITOR_COMMAND(CutOrDeleteCommand)
@@ -88,30 +141,333 @@ NS_DECL_EDITOR_COMMAND(SelectAllCommand)
 NS_DECL_EDITOR_COMMAND(SelectionMoveCommands)
 
 // Insert content commands
 NS_DECL_EDITOR_COMMAND(InsertPlaintextCommand)
 NS_DECL_EDITOR_COMMAND(InsertParagraphCommand)
 NS_DECL_EDITOR_COMMAND(InsertLineBreakCommand)
 NS_DECL_EDITOR_COMMAND(PasteQuotationCommand)
 
-#if 0
-// template for new command
-NS_IMETHODIMP
-FooCommand::IsCommandEnabled(const char* aCommandName,
-                             nsISupports* aCommandRefCon,
-                             bool* aIsEnabled)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
+/******************************************************************************
+ * Commands for HTML editor
+ ******************************************************************************/
+
+// virtual base class for commands that need to save and update Boolean state
+// (like styles etc)
+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(); }
+
+  // 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;
+    }
+    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;
+};
+
+// 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)
+
+ protected:
+  StyleUpdatingCommand() = default;
+  virtual ~StyleUpdatingCommand() = default;
+
+  // get the current state (on or off) for this style or block format
+  MOZ_CAN_RUN_SCRIPT
+  nsresult GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
+                           nsCommandParams& aParams) const final;
+
+  // add/remove the style
+  MOZ_CAN_RUN_SCRIPT
+  nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) const final;
+};
+
+class InsertTagCommand final : public EditorCommand {
+ 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(); }
+
+  static already_AddRefed<nsAtom> TagName(const char* aCommandName) {
+    MOZ_DIAGNOSTIC_ASSERT(aCommandName);
+    if (NS_WARN_IF(!aCommandName)) {
+      return nullptr;
+    }
+    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;
+  virtual ~ListCommand() = default;
+
+  // get the current state (on or off) for this style or block format
+  MOZ_CAN_RUN_SCRIPT
+  nsresult GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
+                           nsCommandParams& aParams) const final;
+
+  // add/remove the style
+  MOZ_CAN_RUN_SCRIPT
+  nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) const final;
+};
+
+class ListItemCommand final : public StateUpdatingCommandBase {
+ public:
+  NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(ListItemCommand)
+
+ protected:
+  ListItemCommand() = default;
+  virtual ~ListItemCommand() = default;
+
+  // get the current state (on or off) for this style or block format
+  MOZ_CAN_RUN_SCRIPT
+  nsresult GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
+                           nsCommandParams& aParams) const final;
+
+  // add/remove the style
+  MOZ_CAN_RUN_SCRIPT
+  nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) const final;
+};
+
+// 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_METHODS(MultiStateCommandBase)
+
+ protected:
+  MultiStateCommandBase() = default;
+  virtual ~MultiStateCommandBase() = default;
 
-NS_IMETHODIMP
-FooCommand::DoCommand(const char* aCommandName,
-                      const nsAString& aCommandParams,
-                      nsISupports* aCommandRefCon)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-#endif
+  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;
+};
+
+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;
+};
+
+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;
+};
+
+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;
+};
+
+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;
+};
+
+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;
+};
+
+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;
+};
+
+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;
+};
+
+class AbsolutePositioningCommand final : public StateUpdatingCommandBase {
+ public:
+  NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON(AbsolutePositioningCommand)
+
+ protected:
+  AbsolutePositioningCommand() = default;
+  virtual ~AbsolutePositioningCommand() = default;
+
+  MOZ_CAN_RUN_SCRIPT
+  nsresult GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
+                           nsCommandParams& aParams) const final;
+  MOZ_CAN_RUN_SCRIPT
+  nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) const final;
+};
+
+// composer commands
+
+NS_DECL_EDITOR_COMMAND(DocumentStateCommand)
+NS_DECL_EDITOR_COMMAND(SetDocumentStateCommand)
+
+NS_DECL_EDITOR_COMMAND(DecreaseZIndexCommand)
+NS_DECL_EDITOR_COMMAND(IncreaseZIndexCommand)
+
+// Generic commands
+
+// Edit menu
+NS_DECL_EDITOR_COMMAND(PasteNoFormattingCommand)
+
+// Block transformations
+NS_DECL_EDITOR_COMMAND(IndentCommand)
+NS_DECL_EDITOR_COMMAND(OutdentCommand)
+
+NS_DECL_EDITOR_COMMAND(RemoveListCommand)
+NS_DECL_EDITOR_COMMAND(RemoveStylesCommand)
+NS_DECL_EDITOR_COMMAND(IncreaseFontSizeCommand)
+NS_DECL_EDITOR_COMMAND(DecreaseFontSizeCommand)
+
+// Insert content commands
+NS_DECL_EDITOR_COMMAND(InsertHTMLCommand)
+
+#undef NS_DECL_EDITOR_COMMAND
+#undef NS_DECL_EDITOR_COMMAND_METHODS
+#undef NS_INLINE_DECL_EDITOR_COMMAND_MAKE_SINGLETON
 
 }  // namespace mozilla
 
-#endif  // #ifndef EditorCommands_h_
+#endif  // #ifndef mozilla_EditorCommands_h
--- a/editor/libeditor/HTMLEditorCommands.cpp
+++ b/editor/libeditor/HTMLEditorCommands.cpp
@@ -1,243 +1,203 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include <stdio.h>  // for printf
+#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/HTMLEditorCommands.h"
 #include "mozilla/dom/Element.h"
 #include "nsAString.h"
 #include "nsCommandParams.h"          // for nsCommandParams, etc
-#include "nsCOMPtr.h"                 // for nsCOMPtr, do_QueryInterface, etc
 #include "nsComponentManagerUtils.h"  // for do_CreateInstance
-#include "nsDebug.h"                  // for NS_ENSURE_TRUE, etc
-#include "nsError.h"                  // for NS_OK, NS_ERROR_FAILURE, etc
 #include "nsGkAtoms.h"                // for nsGkAtoms, nsGkAtoms::font, etc
 #include "nsAtom.h"                   // for nsAtom, etc
 #include "nsIClipboard.h"             // for nsIClipboard, etc
-#include "nsID.h"
-#include "nsIEditor.h"        // for nsIEditor
-#include "nsIHTMLEditor.h"    // for nsIHTMLEditor, 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;
 
 namespace mozilla {
 using dom::Element;
 
 // prototype
-MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-    static nsresult
-    GetListState(HTMLEditor* aHTMLEditor, bool* aMixed, nsAString& aLocalName);
+MOZ_CAN_RUN_SCRIPT
+static nsresult GetListState(HTMLEditor* aHTMLEditor, bool* aMixed,
+                             nsAString& aLocalName);
 
 // defines
 #define STATE_ENABLED "state_enabled"
 #define STATE_ALL "state_all"
 #define STATE_ANY "state_any"
 #define STATE_MIXED "state_mixed"
 #define STATE_BEGIN "state_begin"
 #define STATE_END "state_end"
 #define STATE_ATTRIBUTE "state_attribute"
 #define STATE_DATA "state_data"
 
 /*****************************************************************************
- * mozilla::HTMLEditorCommandBase
- *****************************************************************************/
-
-NS_IMPL_ISUPPORTS(HTMLEditorCommandBase, nsIControllerCommand)
-
-/*****************************************************************************
  * mozilla::StateUpdatingCommandBase
  *****************************************************************************/
 
 nsRefPtrHashtable<nsCharPtrHashKey, nsAtom>
     StateUpdatingCommandBase::sTagNameTable;
 
-NS_IMETHODIMP
-StateUpdatingCommandBase::IsCommandEnabled(const char* aCommandName,
-                                           nsISupports* refCon,
-                                           bool* outCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool StateUpdatingCommandBase::IsCommandEnabled(const char* aCommandName,
+                                                TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
+  if (!aTextEditor->IsSelectionEditable()) {
+    return false;
+  }
+  if (!strcmp(aCommandName, "cmd_absPos")) {
+    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+    return htmlEditor && htmlEditor->IsAbsolutePositionEditorEnabled();
+  }
+  return true;
 }
 
-NS_IMETHODIMP
-StateUpdatingCommandBase::DoCommand(const char* aCommandName,
-                                    nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult StateUpdatingCommandBase::DoCommand(const char* aCommandName,
+                                             TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   RefPtr<nsAtom> tagName = TagName(aCommandName);
   if (NS_WARN_IF(!tagName)) {
     return NS_ERROR_UNEXPECTED;
   }
   return ToggleState(tagName, MOZ_KnownLive(htmlEditor));
 }
 
-NS_IMETHODIMP
-StateUpdatingCommandBase::DoCommandParams(const char* aCommandName,
-                                          nsICommandParams* aParams,
-                                          nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult StateUpdatingCommandBase::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-StateUpdatingCommandBase::GetCommandStateParams(const char* aCommandName,
-                                                nsICommandParams* aParams,
-                                                nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
+nsresult StateUpdatingCommandBase::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  if (!aTextEditor) {
     return NS_OK;
   }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+  HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   RefPtr<nsAtom> tagName = TagName(aCommandName);
   if (NS_WARN_IF(!tagName)) {
     return NS_ERROR_UNEXPECTED;
   }
-  return GetCurrentState(tagName, htmlEditor, aParams);
+  return GetCurrentState(tagName, MOZ_KnownLive(htmlEditor), aParams);
 }
 
 /*****************************************************************************
  * mozilla::PasteNoFormattingCommand
  *****************************************************************************/
 
 StaticRefPtr<PasteNoFormattingCommand> PasteNoFormattingCommand::sInstance;
 
-NS_IMETHODIMP
-PasteNoFormattingCommand::IsCommandEnabled(const char* aCommandName,
-                                           nsISupports* refCon,
-                                           bool* outCmdEnabled) {
-  NS_ENSURE_ARG_POINTER(outCmdEnabled);
-  *outCmdEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
+bool PasteNoFormattingCommand::IsCommandEnabled(const char* aCommandName,
+                                                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
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
-  if (NS_WARN_IF(!htmlEditor)) {
-    return NS_ERROR_FAILURE;
+  HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+  if (!htmlEditor) {
+    return false;
   }
-  *outCmdEnabled = htmlEditor->CanPaste(nsIClipboard::kGlobalClipboard);
-  return NS_OK;
+  return htmlEditor->CanPaste(nsIClipboard::kGlobalClipboard);
 }
 
-NS_IMETHODIMP
-PasteNoFormattingCommand::DoCommand(const char* aCommandName,
-                                    nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult PasteNoFormattingCommand::DoCommand(const char* aCommandName,
+                                             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);
 }
 
-NS_IMETHODIMP
-PasteNoFormattingCommand::DoCommandParams(const char* aCommandName,
-                                          nsICommandParams* aParams,
-                                          nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult PasteNoFormattingCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-PasteNoFormattingCommand::GetCommandStateParams(const char* aCommandName,
-                                                nsICommandParams* aParams,
-                                                nsISupports* refCon) {
-  NS_ENSURE_ARG_POINTER(aParams);
-
-  bool enabled = false;
-  nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, enabled);
+nsresult PasteNoFormattingCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::StyleUpdatingCommand
  *****************************************************************************/
 
 StaticRefPtr<StyleUpdatingCommand> StyleUpdatingCommand::sInstance;
 
 nsresult StyleUpdatingCommand::GetCurrentState(nsAtom* aTagName,
                                                HTMLEditor* aHTMLEditor,
-                                               nsICommandParams* aParams) {
+                                               nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aTagName) || NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   bool firstOfSelectionHasProp = false;
   bool anyOfSelectionHasProp = false;
   bool allOfSelectionHasProp = false;
 
   nsresult rv = aHTMLEditor->GetInlineProperty(
       aTagName, nullptr, EmptyString(), &firstOfSelectionHasProp,
       &anyOfSelectionHasProp, &allOfSelectionHasProp);
 
-  nsCommandParams* params = aParams->AsCommandParams();
-  params->SetBool(STATE_ENABLED, NS_SUCCEEDED(rv));
-  params->SetBool(STATE_ALL, allOfSelectionHasProp);
-  params->SetBool(STATE_ANY, anyOfSelectionHasProp);
-  params->SetBool(STATE_MIXED, anyOfSelectionHasProp && !allOfSelectionHasProp);
-  params->SetBool(STATE_BEGIN, firstOfSelectionHasProp);
-  params->SetBool(STATE_END, allOfSelectionHasProp);  // not completely accurate
+  aParams.SetBool(STATE_ENABLED, NS_SUCCEEDED(rv));
+  aParams.SetBool(STATE_ALL, allOfSelectionHasProp);
+  aParams.SetBool(STATE_ANY, anyOfSelectionHasProp);
+  aParams.SetBool(STATE_MIXED, anyOfSelectionHasProp && !allOfSelectionHasProp);
+  aParams.SetBool(STATE_BEGIN, firstOfSelectionHasProp);
+  aParams.SetBool(STATE_END, allOfSelectionHasProp);  // not completely accurate
   return NS_OK;
 }
 
 nsresult StyleUpdatingCommand::ToggleState(nsAtom* aTagName,
-                                           HTMLEditor* aHTMLEditor) {
+                                           HTMLEditor* aHTMLEditor) const {
   if (NS_WARN_IF(!aTagName) || NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   RefPtr<nsCommandParams> params = new nsCommandParams();
 
   // tags "href" and "name" are special cases in the core editor
   // they are used to remove named anchor/link and shouldn't be used for
   // insertion
   bool doTagRemoval;
   if (aTagName == nsGkAtoms::href || aTagName == nsGkAtoms::name) {
     doTagRemoval = true;
   } else {
     // check current selection; set doTagRemoval if formatting should be removed
-    nsresult rv = GetCurrentState(aTagName, aHTMLEditor, params);
+    nsresult rv = GetCurrentState(aTagName, aHTMLEditor, *params);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     ErrorResult error;
     doTagRemoval = params->GetBool(STATE_ALL, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
@@ -285,42 +245,42 @@ nsresult StyleUpdatingCommand::ToggleSta
 
 /*****************************************************************************
  * mozilla::ListCommand
  *****************************************************************************/
 
 StaticRefPtr<ListCommand> ListCommand::sInstance;
 
 nsresult ListCommand::GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
-                                      nsICommandParams* aParams) {
+                                      nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aTagName) || NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   bool bMixed;
   nsAutoString localName;
   nsresult rv = GetListState(aHTMLEditor, &bMixed, localName);
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool inList = aTagName->Equals(localName);
-  nsCommandParams* params = aParams->AsCommandParams();
-  params->SetBool(STATE_ALL, !bMixed && inList);
-  params->SetBool(STATE_MIXED, bMixed);
-  params->SetBool(STATE_ENABLED, true);
+  aParams.SetBool(STATE_ALL, !bMixed && inList);
+  aParams.SetBool(STATE_MIXED, bMixed);
+  aParams.SetBool(STATE_ENABLED, true);
   return NS_OK;
 }
 
-nsresult ListCommand::ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) {
+nsresult ListCommand::ToggleState(nsAtom* aTagName,
+                                  HTMLEditor* aHTMLEditor) const {
   if (NS_WARN_IF(!aTagName) || NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsresult rv;
   RefPtr<nsCommandParams> params = new nsCommandParams();
-  rv = GetCurrentState(aTagName, aHTMLEditor, params);
+  rv = GetCurrentState(aTagName, aHTMLEditor, *params);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   ErrorResult error;
   bool inList = params->GetBool(STATE_ALL, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
@@ -339,17 +299,17 @@ nsresult ListCommand::ToggleState(nsAtom
 /*****************************************************************************
  * mozilla::ListItemCommand
  *****************************************************************************/
 
 StaticRefPtr<ListItemCommand> ListItemCommand::sInstance;
 
 nsresult ListItemCommand::GetCurrentState(nsAtom* aTagName,
                                           HTMLEditor* aHTMLEditor,
-                                          nsICommandParams* aParams) {
+                                          nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aTagName) || NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   bool bMixed, bLI, bDT, bDD;
   nsresult rv = aHTMLEditor->GetListItemState(&bMixed, &bLI, &bDT, &bDD);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -359,32 +319,31 @@ nsresult ListItemCommand::GetCurrentStat
       inList = aTagName == nsGkAtoms::li;
     } else if (bDT) {
       inList = aTagName == nsGkAtoms::dt;
     } else if (bDD) {
       inList = aTagName == nsGkAtoms::dd;
     }
   }
 
-  nsCommandParams* params = aParams->AsCommandParams();
-  params->SetBool(STATE_ALL, !bMixed && inList);
-  params->SetBool(STATE_MIXED, bMixed);
+  aParams.SetBool(STATE_ALL, !bMixed && inList);
+  aParams.SetBool(STATE_MIXED, bMixed);
 
   return NS_OK;
 }
 
 nsresult ListItemCommand::ToggleState(nsAtom* aTagName,
-                                      HTMLEditor* aHTMLEditor) {
+                                      HTMLEditor* aHTMLEditor) const {
   if (NS_WARN_IF(!aTagName) || NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // Need to use aTagName????
   RefPtr<nsCommandParams> params = new nsCommandParams();
-  GetCurrentState(aTagName, aHTMLEditor, params);
+  GetCurrentState(aTagName, aHTMLEditor, *params);
   ErrorResult error;
   bool inList = params->GetBool(STATE_ALL, error);
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
 
   if (inList) {
     // To remove a list, first get what kind of list we're in
@@ -408,315 +367,254 @@ nsresult ListItemCommand::ToggleState(ns
 }
 
 /*****************************************************************************
  * mozilla::RemoveListCommand
  *****************************************************************************/
 
 StaticRefPtr<RemoveListCommand> RemoveListCommand::sInstance;
 
-NS_IMETHODIMP
-RemoveListCommand::IsCommandEnabled(const char* aCommandName,
-                                    nsISupports* refCon, bool* outCmdEnabled) {
-  *outCmdEnabled = false;
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    return NS_OK;
+bool RemoveListCommand::IsCommandEnabled(const char* aCommandName,
+                                         TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
 
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
-
-  if (!editorBase->IsSelectionEditable()) {
-    return NS_OK;
+  if (!aTextEditor->IsSelectionEditable()) {
+    return false;
   }
 
   // It is enabled if we are in any list type
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+  HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
-    return NS_ERROR_FAILURE;
+    return false;
   }
 
   bool bMixed;
   nsAutoString localName;
   nsresult rv = GetListState(MOZ_KnownLive(htmlEditor), &bMixed, localName);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *outCmdEnabled = bMixed || !localName.IsEmpty();
-  return NS_OK;
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+  return bMixed || !localName.IsEmpty();
 }
 
-NS_IMETHODIMP
-RemoveListCommand::DoCommand(const char* aCommandName, nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult RemoveListCommand::DoCommand(const char* aCommandName,
+                                      TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   // This removes any list type
   return htmlEditor->RemoveList(EmptyString());
 }
 
-NS_IMETHODIMP
-RemoveListCommand::DoCommandParams(const char* aCommandName,
-                                   nsICommandParams* aParams,
-                                   nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult RemoveListCommand::DoCommandParams(const char* aCommandName,
+                                            nsCommandParams* aParams,
+                                            TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-RemoveListCommand::GetCommandStateParams(const char* aCommandName,
-                                         nsICommandParams* aParams,
-                                         nsISupports* refCon) {
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
+nsresult RemoveListCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::IndentCommand
  *****************************************************************************/
 
 StaticRefPtr<IndentCommand> IndentCommand::sInstance;
 
-NS_IMETHODIMP
-IndentCommand::IsCommandEnabled(const char* aCommandName, nsISupports* refCon,
-                                bool* outCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool IndentCommand::IsCommandEnabled(const char* aCommandName,
+                                     TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-IndentCommand::DoCommand(const char* aCommandName, nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult IndentCommand::DoCommand(const char* aCommandName,
+                                  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;
 }
 
-NS_IMETHODIMP
-IndentCommand::DoCommandParams(const char* aCommandName,
-                               nsICommandParams* aParams, nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult IndentCommand::DoCommandParams(const char* aCommandName,
+                                        nsCommandParams* aParams,
+                                        TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-IndentCommand::GetCommandStateParams(const char* aCommandName,
-                                     nsICommandParams* aParams,
-                                     nsISupports* refCon) {
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
+nsresult IndentCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::OutdentCommand
  *****************************************************************************/
 
 StaticRefPtr<OutdentCommand> OutdentCommand::sInstance;
 
-NS_IMETHODIMP
-OutdentCommand::IsCommandEnabled(const char* aCommandName, nsISupports* refCon,
-                                 bool* outCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool OutdentCommand::IsCommandEnabled(const char* aCommandName,
+                                      TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-OutdentCommand::DoCommand(const char* aCommandName, nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult OutdentCommand::DoCommand(const char* aCommandName,
+                                   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;
 }
 
-NS_IMETHODIMP
-OutdentCommand::DoCommandParams(const char* aCommandName,
-                                nsICommandParams* aParams,
-                                nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult OutdentCommand::DoCommandParams(const char* aCommandName,
+                                         nsCommandParams* aParams,
+                                         TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-OutdentCommand::GetCommandStateParams(const char* aCommandName,
-                                      nsICommandParams* aParams,
-                                      nsISupports* refCon) {
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
+nsresult OutdentCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::MultiStateCommandBase
  *****************************************************************************/
 
-NS_IMETHODIMP
-MultiStateCommandBase::IsCommandEnabled(const char* aCommandName,
-                                        nsISupports* refCon,
-                                        bool* outCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool MultiStateCommandBase::IsCommandEnabled(const char* aCommandName,
+                                             TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
   // should be disabled sometimes, like if the current selection is an image
-  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return aTextEditor->IsSelectionEditable();
+}
+
+nsresult MultiStateCommandBase::DoCommand(const char* aCommandName,
+                                          TextEditor& aTextEditor) const {
+  NS_WARNING(
+      "who is calling MultiStateCommandBase::DoCommand (no implementation)?");
   return NS_OK;
 }
 
-NS_IMETHODIMP
-MultiStateCommandBase::DoCommand(const char* aCommandName,
-                                 nsISupports* refCon) {
-#ifdef DEBUG
-  printf(
-      "who is calling MultiStateCommandBase::DoCommand \
-          (no implementation)? %s\n",
-      aCommandName);
-#endif
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-MultiStateCommandBase::DoCommandParams(const char* aCommandName,
-                                       nsICommandParams* aParams,
-                                       nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult MultiStateCommandBase::DoCommandParams(const char* aCommandName,
+                                                nsCommandParams* aParams,
+                                                TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   nsAutoString attribute;
   if (aParams) {
-    nsCommandParams* params = aParams->AsCommandParams();
     nsAutoCString asciiAttribute;
-    nsresult rv = params->GetCString(STATE_ATTRIBUTE, asciiAttribute);
+    nsresult rv = aParams->GetCString(STATE_ATTRIBUTE, asciiAttribute);
     if (NS_SUCCEEDED(rv)) {
       CopyASCIItoUTF16(asciiAttribute, attribute);
     } else {
-      params->GetString(STATE_ATTRIBUTE, attribute);
+      aParams->GetString(STATE_ATTRIBUTE, attribute);
     }
   }
   return SetState(MOZ_KnownLive(htmlEditor), attribute);
 }
 
-NS_IMETHODIMP
-MultiStateCommandBase::GetCommandStateParams(const char* aCommandName,
-                                             nsICommandParams* aParams,
-                                             nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
+nsresult MultiStateCommandBase::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  if (!aTextEditor) {
     return NS_OK;
   }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+  HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   return GetCurrentState(MOZ_KnownLive(htmlEditor), aParams);
 }
 
 /*****************************************************************************
  * mozilla::ParagraphStateCommand
  *****************************************************************************/
 
 StaticRefPtr<ParagraphStateCommand> ParagraphStateCommand::sInstance;
 
-nsresult ParagraphStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
-                                                nsICommandParams* aParams) {
+nsresult ParagraphStateCommand::GetCurrentState(
+    HTMLEditor* aHTMLEditor, nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   bool outMixed;
   nsAutoString outStateString;
   nsresult rv = aHTMLEditor->GetParagraphState(&outMixed, outStateString);
   if (NS_SUCCEEDED(rv)) {
     nsAutoCString tOutStateString;
     LossyCopyUTF16toASCII(outStateString, tOutStateString);
-    nsCommandParams* params = aParams->AsCommandParams();
-    params->SetBool(STATE_MIXED, outMixed);
-    params->SetCString(STATE_ATTRIBUTE, tOutStateString);
+    aParams.SetBool(STATE_MIXED, outMixed);
+    aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   }
   return rv;
 }
 
 nsresult ParagraphStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                         const nsString& newState) {
+                                         const nsString& newState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
   return aHTMLEditor->SetParagraphFormat(newState);
 }
 
 /*****************************************************************************
  * mozilla::FontFaceStateCommand
  *****************************************************************************/
 
 StaticRefPtr<FontFaceStateCommand> FontFaceStateCommand::sInstance;
 
 nsresult FontFaceStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
-                                               nsICommandParams* aParams) {
+                                               nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsAutoString outStateString;
   bool outMixed;
   nsresult rv = aHTMLEditor->GetFontFaceState(&outMixed, outStateString);
   if (NS_SUCCEEDED(rv)) {
-    nsCommandParams* params = aParams->AsCommandParams();
-    params->SetBool(STATE_MIXED, outMixed);
-    params->SetCString(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString));
+    aParams.SetBool(STATE_MIXED, outMixed);
+    aParams.SetCString(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString));
   }
   return rv;
 }
 
 nsresult FontFaceStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                        const nsString& newState) {
+                                        const nsString& newState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (newState.EqualsLiteral("tt")) {
     // The old "teletype" attribute
     nsresult rv = aHTMLEditor->SetInlinePropertyAsAction(
         *nsGkAtoms::tt, nullptr, EmptyString());
@@ -758,49 +656,48 @@ nsresult FontFaceStateCommand::SetState(
 
 /*****************************************************************************
  * mozilla::FontSizeStateCommand
  *****************************************************************************/
 
 StaticRefPtr<FontSizeStateCommand> FontSizeStateCommand::sInstance;
 
 nsresult FontSizeStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
-                                               nsICommandParams* aParams) {
+                                               nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsAutoString outStateString;
   bool firstHas, anyHas, allHas;
   nsresult rv = aHTMLEditor->GetInlinePropertyWithAttrValue(
       nsGkAtoms::font, nsGkAtoms::size, EmptyString(), &firstHas, &anyHas,
       &allHas, outStateString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
-  nsCommandParams* params = aParams->AsCommandParams();
-  params->SetBool(STATE_MIXED, anyHas && !allHas);
-  params->SetCString(STATE_ATTRIBUTE, tOutStateString);
-  params->SetBool(STATE_ENABLED, true);
+  aParams.SetBool(STATE_MIXED, anyHas && !allHas);
+  aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
+  aParams.SetBool(STATE_ENABLED, true);
 
   return rv;
 }
 
 // acceptable values for "newState" are:
 //   -2
 //   -1
 //    0
 //   +1
 //   +2
 //   +3
 //   medium
 //   normal
 nsresult FontSizeStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                        const nsString& newState) {
+                                        const nsString& newState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (!newState.IsEmpty() && !newState.EqualsLiteral("normal") &&
       !newState.EqualsLiteral("medium")) {
     nsresult rv = aHTMLEditor->SetInlinePropertyAsAction(
         *nsGkAtoms::font, nsGkAtoms::size, newState);
@@ -830,39 +727,38 @@ nsresult FontSizeStateCommand::SetState(
 }
 
 /*****************************************************************************
  * mozilla::FontColorStateCommand
  *****************************************************************************/
 
 StaticRefPtr<FontColorStateCommand> FontColorStateCommand::sInstance;
 
-nsresult FontColorStateCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
-                                                nsICommandParams* aParams) {
+nsresult FontColorStateCommand::GetCurrentState(
+    HTMLEditor* aHTMLEditor, nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   bool outMixed;
   nsAutoString outStateString;
   nsresult rv = aHTMLEditor->GetFontColorState(&outMixed, outStateString);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
-  nsCommandParams* params = aParams->AsCommandParams();
-  params->SetBool(STATE_MIXED, outMixed);
-  params->SetCString(STATE_ATTRIBUTE, tOutStateString);
+  aParams.SetBool(STATE_MIXED, outMixed);
+  aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   return NS_OK;
 }
 
 nsresult FontColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                         const nsString& newState) {
+                                         const nsString& newState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
     nsresult rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::font,
                                                             nsGkAtoms::color);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -881,36 +777,35 @@ nsresult FontColorStateCommand::SetState
 
 /*****************************************************************************
  * mozilla::HighlightColorStateCommand
  *****************************************************************************/
 
 StaticRefPtr<HighlightColorStateCommand> HighlightColorStateCommand::sInstance;
 
 nsresult HighlightColorStateCommand::GetCurrentState(
-    HTMLEditor* aHTMLEditor, nsICommandParams* aParams) {
+    HTMLEditor* aHTMLEditor, nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   bool outMixed;
   nsAutoString outStateString;
   nsresult rv = aHTMLEditor->GetHighlightColorState(&outMixed, outStateString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
-  nsCommandParams* params = aParams->AsCommandParams();
-  params->SetBool(STATE_MIXED, outMixed);
-  params->SetCString(STATE_ATTRIBUTE, tOutStateString);
+  aParams.SetBool(STATE_MIXED, outMixed);
+  aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   return NS_OK;
 }
 
 nsresult HighlightColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                              const nsString& newState) {
+                                              const nsString& newState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   if (newState.IsEmpty() || newState.EqualsLiteral("normal")) {
     nsresult rv = aHTMLEditor->RemoveInlinePropertyAsAction(*nsGkAtoms::font,
                                                             nsGkAtoms::bgcolor);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -922,73 +817,57 @@ nsresult HighlightColorStateCommand::Set
   nsresult rv = aHTMLEditor->SetInlinePropertyAsAction(
       *nsGkAtoms::font, nsGkAtoms::bgcolor, newState);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-HighlightColorStateCommand::IsCommandEnabled(const char* aCommandName,
-                                             nsISupports* refCon,
-                                             bool* outCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
-  }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
-}
-
 /*****************************************************************************
  * mozilla::BackgroundColorStateCommand
  *****************************************************************************/
 
 StaticRefPtr<BackgroundColorStateCommand>
     BackgroundColorStateCommand::sInstance;
 
 nsresult BackgroundColorStateCommand::GetCurrentState(
-    HTMLEditor* aHTMLEditor, nsICommandParams* aParams) {
+    HTMLEditor* aHTMLEditor, nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   bool outMixed;
   nsAutoString outStateString;
   nsresult rv = aHTMLEditor->GetBackgroundColorState(&outMixed, outStateString);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
-  nsCommandParams* params = aParams->AsCommandParams();
-  params->SetBool(STATE_MIXED, outMixed);
-  params->SetCString(STATE_ATTRIBUTE, tOutStateString);
+  aParams.SetBool(STATE_MIXED, outMixed);
+  aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   return NS_OK;
 }
 
 nsresult BackgroundColorStateCommand::SetState(HTMLEditor* aHTMLEditor,
-                                               const nsString& newState) {
+                                               const nsString& newState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
   return aHTMLEditor->SetBackgroundColor(newState);
 }
 
 /*****************************************************************************
  * mozilla::AlignCommand
  *****************************************************************************/
 
 StaticRefPtr<AlignCommand> AlignCommand::sInstance;
 
 nsresult AlignCommand::GetCurrentState(HTMLEditor* aHTMLEditor,
-                                       nsICommandParams* aParams) {
+                                       nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsIHTMLEditor::EAlignment firstAlign;
   bool outMixed;
   nsresult rv = aHTMLEditor->GetAlignment(&outMixed, &firstAlign);
 
@@ -1010,490 +889,346 @@ nsresult AlignCommand::GetCurrentState(H
       break;
 
     case nsIHTMLEditor::eJustify:
       outStateString.AssignLiteral("justify");
       break;
   }
   nsAutoCString tOutStateString;
   LossyCopyUTF16toASCII(outStateString, tOutStateString);
-  nsCommandParams* params = aParams->AsCommandParams();
-  params->SetBool(STATE_MIXED, outMixed);
-  params->SetCString(STATE_ATTRIBUTE, tOutStateString);
+  aParams.SetBool(STATE_MIXED, outMixed);
+  aParams.SetCString(STATE_ATTRIBUTE, tOutStateString);
   return NS_OK;
 }
 
 nsresult AlignCommand::SetState(HTMLEditor* aHTMLEditor,
-                                const nsString& newState) {
+                                const nsString& newState) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
   return aHTMLEditor->Align(newState);
 }
 
 /*****************************************************************************
  * mozilla::AbsolutePositioningCommand
  *****************************************************************************/
 
 StaticRefPtr<AbsolutePositioningCommand> AbsolutePositioningCommand::sInstance;
 
-NS_IMETHODIMP
-AbsolutePositioningCommand::IsCommandEnabled(const char* aCommandName,
-                                             nsISupports* aCommandRefCon,
-                                             bool* aOutCmdEnabled) {
-  *aOutCmdEnabled = false;
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
-  if (!htmlEditor) {
-    return NS_OK;
-  }
-  if (!htmlEditor->IsSelectionEditable()) {
-    return NS_OK;
-  }
-  *aOutCmdEnabled = htmlEditor->IsAbsolutePositionEditorEnabled();
-  return NS_OK;
-}
-
 nsresult AbsolutePositioningCommand::GetCurrentState(
-    nsAtom* aTagName, HTMLEditor* aHTMLEditor, nsICommandParams* aParams) {
+    nsAtom* aTagName, HTMLEditor* aHTMLEditor, nsCommandParams& aParams) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  nsCommandParams* params = aParams->AsCommandParams();
   if (!aHTMLEditor->IsAbsolutePositionEditorEnabled()) {
-    params->SetBool(STATE_MIXED, false);
-    params->SetCString(STATE_ATTRIBUTE, EmptyCString());
+    aParams.SetBool(STATE_MIXED, false);
+    aParams.SetCString(STATE_ATTRIBUTE, EmptyCString());
     return NS_OK;
   }
 
   RefPtr<Element> container =
       aHTMLEditor->GetAbsolutelyPositionedSelectionContainer();
-  params->SetBool(STATE_MIXED, false);
-  params->SetCString(STATE_ATTRIBUTE, container ? NS_LITERAL_CSTRING("absolute")
+  aParams.SetBool(STATE_MIXED, false);
+  aParams.SetCString(STATE_ATTRIBUTE, container ? NS_LITERAL_CSTRING("absolute")
                                                 : EmptyCString());
   return NS_OK;
 }
 
-nsresult AbsolutePositioningCommand::ToggleState(nsAtom* aTagName,
-                                                 HTMLEditor* aHTMLEditor) {
+nsresult AbsolutePositioningCommand::ToggleState(
+    nsAtom* aTagName, HTMLEditor* aHTMLEditor) const {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   RefPtr<Element> container =
       aHTMLEditor->GetAbsolutelyPositionedSelectionContainer();
   return aHTMLEditor->SetSelectionToAbsoluteOrStatic(!container);
 }
 
 /*****************************************************************************
  * mozilla::DecreaseZIndexCommand
  *****************************************************************************/
 
 StaticRefPtr<DecreaseZIndexCommand> DecreaseZIndexCommand::sInstance;
 
-NS_IMETHODIMP
-DecreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
-                                        nsISupports* aRefCon,
-                                        bool* aOutCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
+bool DecreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
+                                             TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
-  if (NS_WARN_IF(!htmlEditor)) {
-    return NS_ERROR_FAILURE;
+  HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+  if (!htmlEditor) {
+    return false;
   }
-
   if (!htmlEditor->IsAbsolutePositionEditorEnabled()) {
-    *aOutCmdEnabled = false;
-    return NS_OK;
+    return false;
   }
-
   RefPtr<Element> positionedElement = htmlEditor->GetPositionedElement();
   if (!positionedElement) {
-    *aOutCmdEnabled = false;
-    return NS_OK;
+    return false;
   }
-
-  int32_t z = htmlEditor->GetZIndex(*positionedElement);
-  *aOutCmdEnabled = (z > 0);
-  return NS_OK;
+  return htmlEditor->GetZIndex(*positionedElement) > 0;
 }
 
-NS_IMETHODIMP
-DecreaseZIndexCommand::DoCommand(const char* aCommandName,
-                                 nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult DecreaseZIndexCommand::DoCommand(const char* aCommandName,
+                                          TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   return htmlEditor->AddZIndex(-1);
 }
 
-NS_IMETHODIMP
-DecreaseZIndexCommand::DoCommandParams(const char* aCommandName,
-                                       nsICommandParams* aParams,
-                                       nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult DecreaseZIndexCommand::DoCommandParams(const char* aCommandName,
+                                                nsCommandParams* aParams,
+                                                TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-DecreaseZIndexCommand::GetCommandStateParams(const char* aCommandName,
-                                             nsICommandParams* aParams,
-                                             nsISupports* refCon) {
-  NS_ENSURE_ARG_POINTER(aParams);
-
-  bool enabled = false;
-  nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, enabled);
+nsresult DecreaseZIndexCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::IncreaseZIndexCommand
  *****************************************************************************/
 
 StaticRefPtr<IncreaseZIndexCommand> IncreaseZIndexCommand::sInstance;
 
-NS_IMETHODIMP
-IncreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
-                                        nsISupports* aRefCon,
-                                        bool* aOutCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(aRefCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
+bool IncreaseZIndexCommand::IsCommandEnabled(const char* aCommandName,
+                                             TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
-  if (NS_WARN_IF(!htmlEditor)) {
-    return NS_ERROR_FAILURE;
+  HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
+  if (!htmlEditor) {
+    return false;
   }
-
   if (!htmlEditor->IsAbsolutePositionEditorEnabled()) {
-    *aOutCmdEnabled = false;
-    return NS_OK;
+    return false;
   }
-
-  *aOutCmdEnabled = !!htmlEditor->GetPositionedElement();
-  return NS_OK;
+  return !!htmlEditor->GetPositionedElement();
 }
 
-NS_IMETHODIMP
-IncreaseZIndexCommand::DoCommand(const char* aCommandName,
-                                 nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult IncreaseZIndexCommand::DoCommand(const char* aCommandName,
+                                          TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   return htmlEditor->AddZIndex(1);
 }
 
-NS_IMETHODIMP
-IncreaseZIndexCommand::DoCommandParams(const char* aCommandName,
-                                       nsICommandParams* aParams,
-                                       nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult IncreaseZIndexCommand::DoCommandParams(const char* aCommandName,
+                                                nsCommandParams* aParams,
+                                                TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-IncreaseZIndexCommand::GetCommandStateParams(const char* aCommandName,
-                                             nsICommandParams* aParams,
-                                             nsISupports* refCon) {
-  NS_ENSURE_ARG_POINTER(aParams);
-
-  bool enabled = false;
-  nsresult rv = IsCommandEnabled(aCommandName, refCon, &enabled);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, enabled);
+nsresult IncreaseZIndexCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::RemoveStylesCommand
  *****************************************************************************/
 
 StaticRefPtr<RemoveStylesCommand> RemoveStylesCommand::sInstance;
 
-NS_IMETHODIMP
-RemoveStylesCommand::IsCommandEnabled(const char* aCommandName,
-                                      nsISupports* refCon,
-                                      bool* outCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool RemoveStylesCommand::IsCommandEnabled(const char* aCommandName,
+                                           TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
   // test if we have any styles?
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-RemoveStylesCommand::DoCommand(const char* aCommandName, nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult RemoveStylesCommand::DoCommand(const char* aCommandName,
+                                        TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   return MOZ_KnownLive(htmlEditor)->RemoveAllInlineProperties();
 }
 
-NS_IMETHODIMP
-RemoveStylesCommand::DoCommandParams(const char* aCommandName,
-                                     nsICommandParams* aParams,
-                                     nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult RemoveStylesCommand::DoCommandParams(const char* aCommandName,
+                                              nsCommandParams* aParams,
+                                              TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-RemoveStylesCommand::GetCommandStateParams(const char* aCommandName,
-                                           nsICommandParams* aParams,
-                                           nsISupports* refCon) {
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
+nsresult RemoveStylesCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::IncreaseFontSizeCommand
  *****************************************************************************/
 
 StaticRefPtr<IncreaseFontSizeCommand> IncreaseFontSizeCommand::sInstance;
 
-NS_IMETHODIMP
-IncreaseFontSizeCommand::IsCommandEnabled(const char* aCommandName,
-                                          nsISupports* refCon,
-                                          bool* outCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool IncreaseFontSizeCommand::IsCommandEnabled(const char* aCommandName,
+                                               TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
   // test if we are at max size?
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-IncreaseFontSizeCommand::DoCommand(const char* aCommandName,
-                                   nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult IncreaseFontSizeCommand::DoCommand(const char* aCommandName,
+                                            TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   return MOZ_KnownLive(htmlEditor)->IncreaseFontSize();
 }
 
-NS_IMETHODIMP
-IncreaseFontSizeCommand::DoCommandParams(const char* aCommandName,
-                                         nsICommandParams* aParams,
-                                         nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult IncreaseFontSizeCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-IncreaseFontSizeCommand::GetCommandStateParams(const char* aCommandName,
-                                               nsICommandParams* aParams,
-                                               nsISupports* refCon) {
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
+nsresult IncreaseFontSizeCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::DecreaseFontSizeCommand
  *****************************************************************************/
 
 StaticRefPtr<DecreaseFontSizeCommand> DecreaseFontSizeCommand::sInstance;
 
-NS_IMETHODIMP
-DecreaseFontSizeCommand::IsCommandEnabled(const char* aCommandName,
-                                          nsISupports* refCon,
-                                          bool* outCmdEnabled) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool DecreaseFontSizeCommand::IsCommandEnabled(const char* aCommandName,
+                                               TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
   // test if we are at min size?
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-DecreaseFontSizeCommand::DoCommand(const char* aCommandName,
-                                   nsISupports* refCon) {
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    return NS_OK;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+nsresult DecreaseFontSizeCommand::DoCommand(const char* aCommandName,
+                                            TextEditor& aTextEditor) const {
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
   return MOZ_KnownLive(htmlEditor)->DecreaseFontSize();
 }
 
-NS_IMETHODIMP
-DecreaseFontSizeCommand::DoCommandParams(const char* aCommandName,
-                                         nsICommandParams* aParams,
-                                         nsISupports* refCon) {
-  return DoCommand(aCommandName, refCon);
+nsresult DecreaseFontSizeCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
+  return DoCommand(aCommandName, aTextEditor);
 }
 
-NS_IMETHODIMP
-DecreaseFontSizeCommand::GetCommandStateParams(const char* aCommandName,
-                                               nsICommandParams* aParams,
-                                               nsISupports* refCon) {
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
+nsresult DecreaseFontSizeCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::InsertHTMLCommand
  *****************************************************************************/
 
 StaticRefPtr<InsertHTMLCommand> InsertHTMLCommand::sInstance;
 
-NS_IMETHODIMP
-InsertHTMLCommand::IsCommandEnabled(const char* aCommandName,
-                                    nsISupports* refCon, bool* outCmdEnabled) {
-  NS_ENSURE_ARG_POINTER(outCmdEnabled);
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool InsertHTMLCommand::IsCommandEnabled(const char* aCommandName,
+                                         TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
-NS_IMETHODIMP
-InsertHTMLCommand::DoCommand(const char* aCommandName, nsISupports* refCon) {
+nsresult InsertHTMLCommand::DoCommand(const char* aCommandName,
+                                      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
-  NS_ENSURE_ARG_POINTER(refCon);
-
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
   nsAutoString html;
   return MOZ_KnownLive(htmlEditor)->InsertHTML(html);
 }
 
-NS_IMETHODIMP
-InsertHTMLCommand::DoCommandParams(const char* aCommandName,
-                                   nsICommandParams* aParams,
-                                   nsISupports* refCon) {
-  NS_ENSURE_ARG_POINTER(aParams);
-  NS_ENSURE_ARG_POINTER(refCon);
+nsresult InsertHTMLCommand::DoCommandParams(const char* aCommandName,
+                                            nsCommandParams* aParams,
+                                            TextEditor& aTextEditor) const {
+  if (NS_WARN_IF(!aParams)) {
+    return NS_ERROR_INVALID_ARG;
+  }
 
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   // Get HTML source string to insert from command params
   nsAutoString html;
-  nsresult rv = aParams->AsCommandParams()->GetString(STATE_DATA, html);
+  nsresult rv = aParams->GetString(STATE_DATA, html);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return MOZ_KnownLive(htmlEditor)->InsertHTML(html);
 }
 
-NS_IMETHODIMP
-InsertHTMLCommand::GetCommandStateParams(const char* aCommandName,
-                                         nsICommandParams* aParams,
-                                         nsISupports* refCon) {
-  NS_ENSURE_ARG_POINTER(aParams);
-  NS_ENSURE_ARG_POINTER(refCon);
-
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
+nsresult InsertHTMLCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * mozilla::InsertTagCommand
  *****************************************************************************/
 
 StaticRefPtr<InsertTagCommand> InsertTagCommand::sInstance;
 nsRefPtrHashtable<nsCharPtrHashKey, nsAtom> InsertTagCommand::sTagNameTable;
 
-NS_IMETHODIMP
-InsertTagCommand::IsCommandEnabled(const char* aCommandName,
-                                   nsISupports* refCon, bool* outCmdEnabled) {
-  NS_ENSURE_ARG_POINTER(outCmdEnabled);
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (!editor) {
-    *outCmdEnabled = false;
-    return NS_OK;
+bool InsertTagCommand::IsCommandEnabled(const char* aCommandName,
+                                        TextEditor* aTextEditor) const {
+  if (!aTextEditor) {
+    return false;
   }
-  mozilla::EditorBase* editorBase = editor->AsEditorBase();
-  MOZ_ASSERT(editorBase);
-  *outCmdEnabled = editorBase->IsSelectionEditable();
-  return NS_OK;
+  return aTextEditor->IsSelectionEditable();
 }
 
 // corresponding STATE_ATTRIBUTE is: src (img) and href (a)
-NS_IMETHODIMP
-InsertTagCommand::DoCommand(const char* aCmdName, nsISupports* refCon) {
-  if (NS_WARN_IF(!aCmdName) || NS_WARN_IF(!refCon)) {
-    return NS_ERROR_INVALID_ARG;
-  }
+nsresult InsertTagCommand::DoCommand(const char* aCmdName,
+                                     TextEditor& aTextEditor) const {
   RefPtr<nsAtom> tagName = TagName(aCmdName);
   if (NS_WARN_IF(tagName != nsGkAtoms::hr)) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<Element> newElement =
       MOZ_KnownLive(htmlEditor)->CreateElementWithDefaults(*tagName);
   if (NS_WARN_IF(!newElement)) {
     return NS_ERROR_FAILURE;
@@ -1501,51 +1236,42 @@ InsertTagCommand::DoCommand(const char* 
   nsresult rv =
       MOZ_KnownLive(htmlEditor)->InsertElementAtSelection(newElement, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-InsertTagCommand::DoCommandParams(const char* aCommandName,
-                                  nsICommandParams* aParams,
-                                  nsISupports* refCon) {
-  if (NS_WARN_IF(!aCommandName) || NS_WARN_IF(!refCon)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
+nsresult InsertTagCommand::DoCommandParams(const char* aCommandName,
+                                           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, refCon);
+    return DoCommand(aCommandName, aTextEditor);
   }
 
   if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
   RefPtr<nsAtom> tagName = TagName(aCommandName);
   if (NS_WARN_IF(!tagName)) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_FAILURE;
-  }
-  mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
+  HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   // Don't use nsAutoString here because nsCommandParams stores string member
   // with nsString*.  Therefore, nsAutoString always needs to copy the storage
   // but nsString may avoid it.
   nsString value;
-  nsresult rv = aParams->AsCommandParams()->GetString(STATE_ATTRIBUTE, value);
+  nsresult rv = aParams->GetString(STATE_ATTRIBUTE, value);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (NS_WARN_IF(value.IsEmpty())) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // filter out tags we don't know how to insert
@@ -1581,26 +1307,21 @@ InsertTagCommand::DoCommandParams(const 
 
   rv = MOZ_KnownLive(htmlEditor)->InsertElementAtSelection(newElement, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-InsertTagCommand::GetCommandStateParams(const char* aCommandName,
-                                        nsICommandParams* aParams,
-                                        nsISupports* refCon) {
-  NS_ENSURE_ARG_POINTER(aParams);
-  NS_ENSURE_ARG_POINTER(refCon);
-
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  return aParams->AsCommandParams()->SetBool(STATE_ENABLED, outCmdEnabled);
+nsresult InsertTagCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  return aParams.SetBool(STATE_ENABLED,
+                         IsCommandEnabled(aCommandName, aTextEditor));
 }
 
 /*****************************************************************************
  * Helper methods
  *****************************************************************************/
 
 static nsresult GetListState(HTMLEditor* aHTMLEditor, bool* aMixed,
                              nsAString& aLocalName)
deleted file mode 100644
--- a/editor/libeditor/HTMLEditorCommands.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_HTMLEditorCommands_h_
-#define mozilla_HTMLEditorCommands_h_
-
-#include "mozilla/StaticPtr.h"
-#include "nsIControllerCommand.h"
-#include "nsISupportsImpl.h"  // for NS_DECL_ISUPPORTS_INHERITED, etc
-#include "nsRefPtrHashtable.h"
-#include "nsStringFwd.h"
-#include "nscore.h"  // for nsresult, NS_IMETHOD
-
-class nsAtom;
-class nsICommandParams;
-class nsISupports;
-
-namespace mozilla {
-class HTMLEditor;
-
-// This is a base class for commands registered with window which includes
-// HTMLEditor.  Like editor commands, these command classes are also designed
-// as singleton classes.  So, MUST be stateless.  Also note that
-// IsCommandEnabled can be called with an editor that may not have an editor
-// yet (because the document is loading).  Most commands will want to return
-// false in this case.  Don't hold on to any references to the editor or
-// document from your command.  This will cause leaks.  Also, be aware that
-// the document the editor is editing can change under you (if the user
-// Reverts the file, for instance).
-class HTMLEditorCommandBase : public nsIControllerCommand {
- public:
-  // nsISupports
-  NS_DECL_ISUPPORTS
-
- protected:
-  HTMLEditorCommandBase() = default;
-  virtual ~HTMLEditorCommandBase() = default;
-};
-
-#define NS_DECL_HTML_EDITOR_COMMAND(_cmd)           \
-  class _cmd final : public HTMLEditorCommandBase { \
-   public:                                          \
-    NS_DECL_NSICONTROLLERCOMMAND                    \
-                                                    \
-    static _cmd* GetInstance() {                    \
-      if (!sInstance) {                             \
-        sInstance = new _cmd();                     \
-      }                                             \
-      return sInstance;                             \
-    }                                               \
-                                                    \
-    static void Shutdown() { sInstance = nullptr; } \
-                                                    \
-   private:                                         \
-    static StaticRefPtr<_cmd> sInstance;            \
-  };
-
-#define NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(_cmd) \
- public:                                            \
-  static _cmd* GetInstance() {                      \
-    if (!sInstance) {                               \
-      sInstance = new _cmd();                       \
-    }                                               \
-    return sInstance;                               \
-  }                                                 \
-                                                    \
-  static void Shutdown() { sInstance = nullptr; }   \
-                                                    \
- private:                                           \
-  static StaticRefPtr<_cmd> sInstance;
-
-// virtual base class for commands that need to save and update Boolean state
-// (like styles etc)
-class StateUpdatingCommandBase : public HTMLEditorCommandBase {
- public:
-  NS_INLINE_DECL_REFCOUNTING_INHERITED(StateUpdatingCommandBase,
-                                       HTMLEditorCommandBase)
-
-  NS_DECL_NSICONTROLLERCOMMAND
-
- protected:
-  StateUpdatingCommandBase() = default;
-  virtual ~StateUpdatingCommandBase() { sTagNameTable.Clear(); }
-
-  // get the current state (on or off) for this style or block format
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      virtual nsresult
-      GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
-                      nsICommandParams* aParams) = 0;
-
-  // add/remove the style
-  MOZ_CAN_RUN_SCRIPT
-  virtual nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) = 0;
-
-  static already_AddRefed<nsAtom> TagName(const char* aCommandName) {
-    MOZ_DIAGNOSTIC_ASSERT(aCommandName);
-    if (NS_WARN_IF(!aCommandName)) {
-      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;
-};
-
-// 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_DECL_HTML_EDITOR_COMMAND_SINGLETON(StyleUpdatingCommand)
-
- protected:
-  StyleUpdatingCommand() = default;
-  virtual ~StyleUpdatingCommand() = default;
-
-  // get the current state (on or off) for this style or block format
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
-                      nsICommandParams* aParams) final;
-
-  // add/remove the style
-  MOZ_CAN_RUN_SCRIPT
-  nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) final;
-};
-
-class InsertTagCommand final : public HTMLEditorCommandBase {
- public:
-  NS_INLINE_DECL_REFCOUNTING_INHERITED(InsertTagCommand, HTMLEditorCommandBase)
-
-  NS_DECL_NSICONTROLLERCOMMAND
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(InsertTagCommand)
-
- protected:
-  InsertTagCommand() = default;
-  virtual ~InsertTagCommand() { sTagNameTable.Clear(); }
-
-  static already_AddRefed<nsAtom> TagName(const char* aCommandName) {
-    MOZ_DIAGNOSTIC_ASSERT(aCommandName);
-    if (NS_WARN_IF(!aCommandName)) {
-      return nullptr;
-    }
-    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_DECL_HTML_EDITOR_COMMAND_SINGLETON(ListCommand)
-
- protected:
-  ListCommand() = default;
-  virtual ~ListCommand() = default;
-
-  // get the current state (on or off) for this style or block format
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
-                      nsICommandParams* aParams) final;
-
-  // add/remove the style
-  MOZ_CAN_RUN_SCRIPT
-  nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) final;
-};
-
-class ListItemCommand final : public StateUpdatingCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(ListItemCommand)
-
- protected:
-  ListItemCommand() = default;
-  virtual ~ListItemCommand() = default;
-
-  // get the current state (on or off) for this style or block format
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
-                      nsICommandParams* aParams) final;
-
-  // add/remove the style
-  MOZ_CAN_RUN_SCRIPT
-  nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) final;
-};
-
-// Base class for commands whose state consists of a string (e.g. para format)
-class MultiStateCommandBase : public HTMLEditorCommandBase {
- public:
-  NS_INLINE_DECL_REFCOUNTING_INHERITED(MultiStateCommandBase,
-                                       HTMLEditorCommandBase)
-  NS_DECL_NSICONTROLLERCOMMAND
-
- protected:
-  MultiStateCommandBase() = default;
-  virtual ~MultiStateCommandBase() = default;
-
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      virtual nsresult
-      GetCurrentState(HTMLEditor* aHTMLEditor, nsICommandParams* aParams) = 0;
-  MOZ_CAN_RUN_SCRIPT
-  virtual nsresult SetState(HTMLEditor* aHTMLEditor,
-                            const nsString& newState) = 0;
-};
-
-class ParagraphStateCommand final : public MultiStateCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(ParagraphStateCommand)
-
- protected:
-  ParagraphStateCommand() = default;
-  virtual ~ParagraphStateCommand() = default;
-
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(HTMLEditor* aHTMLEditor, nsICommandParams* aParams) final;
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetState(HTMLEditor* aHTMLEditor, const nsString& newState) final;
-};
-
-class FontFaceStateCommand final : public MultiStateCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(FontFaceStateCommand)
-
- protected:
-  FontFaceStateCommand() = default;
-  virtual ~FontFaceStateCommand() = default;
-
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(HTMLEditor* aHTMLEditor, nsICommandParams* aParams) final;
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetState(HTMLEditor* aHTMLEditor, const nsString& newState) final;
-};
-
-class FontSizeStateCommand final : public MultiStateCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(FontSizeStateCommand)
-
- protected:
-  FontSizeStateCommand() = default;
-  virtual ~FontSizeStateCommand() = default;
-
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(HTMLEditor* aHTMLEditor, nsICommandParams* aParams) final;
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetState(HTMLEditor* aHTMLEditor, const nsString& newState) final;
-};
-
-class HighlightColorStateCommand final : public MultiStateCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(HighlightColorStateCommand)
-
- protected:
-  HighlightColorStateCommand() = default;
-  virtual ~HighlightColorStateCommand() = default;
-
-  NS_IMETHOD IsCommandEnabled(const char* aCommandName,
-                              nsISupports* aCommandRefCon, bool* _retval) final;
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(HTMLEditor* aHTMLEditor, nsICommandParams* aParams) final;
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetState(HTMLEditor* aHTMLEditor, const nsString& newState) final;
-};
-
-class FontColorStateCommand final : public MultiStateCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(FontColorStateCommand)
-
- protected:
-  FontColorStateCommand() = default;
-  virtual ~FontColorStateCommand() = default;
-
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(HTMLEditor* aHTMLEditor, nsICommandParams* aParams) final;
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetState(HTMLEditor* aHTMLEditor, const nsString& newState) final;
-};
-
-class AlignCommand final : public MultiStateCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(AlignCommand)
-
- protected:
-  AlignCommand() = default;
-  virtual ~AlignCommand() = default;
-
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(HTMLEditor* aHTMLEditor, nsICommandParams* aParams) final;
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetState(HTMLEditor* aHTMLEditor, const nsString& newState) final;
-};
-
-class BackgroundColorStateCommand final : public MultiStateCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(BackgroundColorStateCommand)
-
- protected:
-  BackgroundColorStateCommand() = default;
-  virtual ~BackgroundColorStateCommand() = default;
-
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(HTMLEditor* aHTMLEditor, nsICommandParams* aParams) final;
-  MOZ_CAN_RUN_SCRIPT
-  nsresult SetState(HTMLEditor* aHTMLEditor, const nsString& newState) final;
-};
-
-class AbsolutePositioningCommand final : public StateUpdatingCommandBase {
- public:
-  NS_DECL_HTML_EDITOR_COMMAND_SINGLETON(AbsolutePositioningCommand)
-
- protected:
-  AbsolutePositioningCommand() = default;
-  virtual ~AbsolutePositioningCommand() = default;
-
-  NS_IMETHOD IsCommandEnabled(const char* aCommandName,
-                              nsISupports* aCommandRefCon, bool* _retval) final;
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY  // XXX Needs to change nsIControllerCommand.idl
-      nsresult
-      GetCurrentState(nsAtom* aTagName, HTMLEditor* aHTMLEditor,
-                      nsICommandParams* aParams) final;
-  MOZ_CAN_RUN_SCRIPT
-  nsresult ToggleState(nsAtom* aTagName, HTMLEditor* aHTMLEditor) final;
-};
-
-// composer commands
-
-NS_DECL_HTML_EDITOR_COMMAND(DocumentStateCommand)
-NS_DECL_HTML_EDITOR_COMMAND(SetDocumentStateCommand)
-
-NS_DECL_HTML_EDITOR_COMMAND(DecreaseZIndexCommand)
-NS_DECL_HTML_EDITOR_COMMAND(IncreaseZIndexCommand)
-
-// Generic commands
-
-// Edit menu
-NS_DECL_HTML_EDITOR_COMMAND(PasteNoFormattingCommand)
-
-// Block transformations
-NS_DECL_HTML_EDITOR_COMMAND(IndentCommand)
-NS_DECL_HTML_EDITOR_COMMAND(OutdentCommand)
-
-NS_DECL_HTML_EDITOR_COMMAND(RemoveListCommand)
-NS_DECL_HTML_EDITOR_COMMAND(RemoveStylesCommand)
-NS_DECL_HTML_EDITOR_COMMAND(IncreaseFontSizeCommand)
-NS_DECL_HTML_EDITOR_COMMAND(DecreaseFontSizeCommand)
-
-// Insert content commands
-NS_DECL_HTML_EDITOR_COMMAND(InsertHTMLCommand)
-
-}  // namespace mozilla
-
-#endif  // mozilla_HTMLEditorCommands_h_
--- a/editor/libeditor/HTMLEditorController.cpp
+++ b/editor/libeditor/HTMLEditorController.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/HTMLEditorController.h"
 
-#include "mozilla/HTMLEditorCommands.h"  // for StyleUpdatingCommand, etc
+#include "mozilla/EditorCommands.h"      // for StyleUpdatingCommand, etc
 #include "mozilla/mozalloc.h"            // for operator new
 #include "nsControllerCommandTable.h"    // for nsControllerCommandTable
 #include "nsError.h"                     // for NS_OK
 
 namespace mozilla {
 
 #define NS_REGISTER_COMMAND(_cmdClass, _cmdName)                        \
   {                                                                     \
--- a/editor/libeditor/HTMLEditorDocumentCommands.cpp
+++ b/editor/libeditor/HTMLEditorDocumentCommands.cpp
@@ -1,34 +1,26 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/EditorCommands.h"
+
 #include "mozilla/HTMLEditor.h"          // for HTMLEditor
-#include "mozilla/HTMLEditorCommands.h"  // for SetDocumentStateCommand, etc
 #include "mozilla/TextEditor.h"          // for TextEditor
+#include "mozilla/dom/Document.h"        // for Document
 #include "nsCommandParams.h"             // for nsCommandParams
-#include "nsCOMPtr.h"                    // for nsCOMPtr, do_QueryInterface, etc
-#include "nsCRT.h"                       // for nsCRT
-#include "nsDebug.h"                     // for NS_ENSURE_ARG_POINTER, etc
-#include "nsError.h"                     // for NS_ERROR_INVALID_ARG, etc
 #include "nsIDocShell.h"                 // for nsIDocShell
-#include "mozilla/dom/Document.h"        // for Document
 #include "nsIEditingSession.h"           // for nsIEditingSession, etc
-#include "nsIEditor.h"                   // for nsIEditor
-#include "nsIPlaintextEditor.h"          // for nsIPlaintextEditor, etc
 #include "nsISelectionController.h"      // for nsISelectionController
 #include "nsISupportsImpl.h"             // for nsPresContext::Release
 #include "nsISupportsUtils.h"            // for NS_IF_ADDREF
 #include "nsIURI.h"                      // for nsIURI
 #include "nsPresContext.h"               // for nsPresContext
-#include "nscore.h"                      // for NS_IMETHODIMP, nsresult, etc
-
-class nsISupports;
 
 // defines
 #define STATE_ENABLED "state_enabled"
 #define STATE_ALL "state_all"
 #define STATE_ATTRIBUTE "state_attribute"
 #define STATE_DATA "state_data"
 
 namespace mozilla {
@@ -40,139 +32,121 @@ 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;
 
-NS_IMETHODIMP
-SetDocumentStateCommand::IsCommandEnabled(const char* aCommandName,
-                                          nsISupports* refCon,
-                                          bool* outCmdEnabled) {
-  if (NS_WARN_IF(!outCmdEnabled)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
+bool SetDocumentStateCommand::IsCommandEnabled(const char* aCommandName,
+                                               TextEditor* aTextEditor) const {
   // These commands are always enabled
-  *outCmdEnabled = true;
-  return NS_OK;
+  return true;
 }
 
-NS_IMETHODIMP
-SetDocumentStateCommand::DoCommand(const char* aCommandName,
-                                   nsISupports* refCon) {
+nsresult SetDocumentStateCommand::DoCommand(const char* aCommandName,
+                                            TextEditor& aTextEditor) const {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_IMETHODIMP
-SetDocumentStateCommand::DoCommandParams(const char* aCommandName,
-                                         nsICommandParams* aParams,
-                                         nsISupports* refCon) {
+nsresult SetDocumentStateCommand::DoCommandParams(
+    const char* aCommandName, nsCommandParams* aParams,
+    TextEditor& aTextEditor) const {
   if (NS_WARN_IF(!aParams)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-
-  nsCommandParams* params = aParams->AsCommandParams();
-
-  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentModified")) {
+  if (!strcmp(aCommandName, "cmd_setDocumentModified")) {
     ErrorResult error;
-    bool modified = params->GetBool(STATE_ATTRIBUTE, 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 = textEditor->IncrementModificationCount(1);
+      nsresult rv = aTextEditor.IncrementModificationCount(1);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       return NS_OK;
     }
-    nsresult rv = textEditor->ResetModificationCount();
+    nsresult rv = aTextEditor.ResetModificationCount();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
-  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
+  if (!strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
     ErrorResult error;
-    bool isReadOnly = params->GetBool(STATE_ATTRIBUTE, error);
+    bool isReadOnly = aParams->GetBool(STATE_ATTRIBUTE, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     if (isReadOnly) {
       nsresult rv =
-          textEditor->AddFlags(nsIPlaintextEditor::eEditorReadonlyMask);
+          aTextEditor.AddFlags(nsIPlaintextEditor::eEditorReadonlyMask);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       return NS_OK;
     }
     nsresult rv =
-        textEditor->RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask);
+        aTextEditor.RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
-  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
+    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
     ErrorResult error;
-    bool desireCSS = params->GetBool(STATE_ATTRIBUTE, 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 (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_insertBrOnReturn")) {
+    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
     ErrorResult error;
-    bool insertBrOnReturn = params->GetBool(STATE_ATTRIBUTE, 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 (!nsCRT::strcmp(aCommandName, "cmd_defaultParagraphSeparator")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_defaultParagraphSeparator")) {
+    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
 
     nsAutoCString newValue;
-    nsresult rv = params->GetCString(STATE_ATTRIBUTE, 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;
     }
@@ -186,227 +160,213 @@ SetDocumentStateCommand::DoCommandParams
       return NS_OK;
     }
 
     // This should not be reachable from nsHTMLDocument::ExecCommand
     NS_WARNING("Invalid default paragraph separator");
     return NS_ERROR_UNEXPECTED;
   }
 
-  if (!nsCRT::strcmp(aCommandName, "cmd_enableObjectResizing")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_enableObjectResizing")) {
+    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
     ErrorResult error;
-    bool enabled = params->GetBool(STATE_ATTRIBUTE, error);
+    bool enabled = aParams->GetBool(STATE_ATTRIBUTE, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     htmlEditor->EnableObjectResizer(enabled);
     return NS_OK;
   }
 
-  if (!nsCRT::strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
+    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
     ErrorResult error;
-    bool enabled = params->GetBool(STATE_ATTRIBUTE, error);
+    bool enabled = aParams->GetBool(STATE_ATTRIBUTE, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
     htmlEditor->EnableInlineTableEditor(enabled);
     return NS_OK;
   }
 
-  if (!nsCRT::strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
-    NS_ENSURE_ARG_POINTER(aParams);
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
+    HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
     ErrorResult error;
-    bool enabled = params->GetBool(STATE_ATTRIBUTE, 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;
 }
 
-NS_IMETHODIMP
-SetDocumentStateCommand::GetCommandStateParams(const char* aCommandName,
-                                               nsICommandParams* aParams,
-                                               nsISupports* refCon) {
-  if (NS_WARN_IF(!aParams) || NS_WARN_IF(!refCon)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
+nsresult SetDocumentStateCommand::GetCommandStateParams(
+    const char* aCommandName, 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
-  nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-  if (NS_WARN_IF(!editor)) {
+  if (NS_WARN_IF(!aTextEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
-  TextEditor* textEditor = editor->AsTextEditor();
-  MOZ_ASSERT(textEditor);
-
-  nsCommandParams* params = aParams->AsCommandParams();
-
   // Always get the enabled state
-  bool outCmdEnabled = false;
-  IsCommandEnabled(aCommandName, refCon, &outCmdEnabled);
-  nsresult rv = params->SetBool(STATE_ENABLED, outCmdEnabled);
+  nsresult rv = aParams.SetBool(STATE_ENABLED,
+                                IsCommandEnabled(aCommandName, aTextEditor));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // cmd_setDocumentModified is an internal command.
-  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentModified")) {
+  if (!strcmp(aCommandName, "cmd_setDocumentModified")) {
     bool modified;
-    rv = textEditor->GetDocumentModified(&modified);
+    rv = aTextEditor->GetDocumentModified(&modified);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     // XXX Nobody refers this result due to wrong type.
-    rv = params->SetBool(STATE_ATTRIBUTE, modified);
+    rv = aParams.SetBool(STATE_ATTRIBUTE, modified);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   // cmd_setDocumentReadOnly is a Gecko specific command, "contentReadOnly".
-  if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
+  if (!strcmp(aCommandName, "cmd_setDocumentReadOnly")) {
     // XXX Nobody refers this result due to wrong type.
-    rv = params->SetBool(STATE_ATTRIBUTE, textEditor->IsReadonly());
+    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 (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_setDocumentUseCSS")) {
+    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
-    rv = params->SetBool(STATE_ALL, htmlEditor->IsCSSEnabled());
+    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 (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_insertBrOnReturn")) {
+    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 = params->SetBool(STATE_ATTRIBUTE, !createPOnReturn);
+    rv = aParams.SetBool(STATE_ATTRIBUTE, !createPOnReturn);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   // cmd_defaultParagraphSeparator is a common command,
   // "defaultParagraphSeparator".
-  if (!nsCRT::strcmp(aCommandName, "cmd_defaultParagraphSeparator")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_defaultParagraphSeparator")) {
+    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
 
     switch (htmlEditor->GetDefaultParagraphSeparator()) {
       case ParagraphSeparator::div: {
         DebugOnly<nsresult> rv =
-            params->SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("div"));
+            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 =
-            params->SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("p"));
+            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 =
-            params->SetCString(STATE_ATTRIBUTE, NS_LITERAL_CSTRING("br"));
+            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 (!nsCRT::strcmp(aCommandName, "cmd_enableObjectResizing")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  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 = params->SetBool(STATE_ALL, htmlEditor->IsObjectResizerEnabled());
+    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 (!nsCRT::strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_enableInlineTableEditing")) {
+    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 = params->SetBool(STATE_ALL, htmlEditor->IsInlineTableEditorEnabled());
+    rv = aParams.SetBool(STATE_ALL, htmlEditor->IsInlineTableEditorEnabled());
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   // cmd_enableAbsolutePositionEditing is a Gecko specific command,
   // "cenableAbsolutePositionEditing".
-  if (!nsCRT::strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
-    NS_ENSURE_ARG_POINTER(aParams);
-    HTMLEditor* htmlEditor = textEditor->AsHTMLEditor();
+  if (!strcmp(aCommandName, "cmd_enableAbsolutePositionEditing")) {
+    HTMLEditor* htmlEditor = aTextEditor->AsHTMLEditor();
     if (NS_WARN_IF(!htmlEditor)) {
       return NS_ERROR_INVALID_ARG;
     }
-    return params->SetBool(STATE_ALL,
+    return aParams.SetBool(STATE_ALL,
                            htmlEditor->IsAbsolutePositionEditorEnabled());
   }
 
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /*****************************************************************************
  * mozilla::DocumentStateCommand
@@ -442,97 +402,72 @@ SetDocumentStateCommand::GetCommandState
  *  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;
 
-NS_IMETHODIMP
-DocumentStateCommand::IsCommandEnabled(const char* aCommandName,
-                                       nsISupports* refCon,
-                                       bool* outCmdEnabled) {
-  if (NS_WARN_IF(!outCmdEnabled)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
+bool DocumentStateCommand::IsCommandEnabled(const char* aCommandName,
+                                            TextEditor* aTextEditor) const {
   // Always return false to discourage callers from using DoCommand()
-  *outCmdEnabled = false;
-  return NS_OK;
+  return false;
 }
 
-NS_IMETHODIMP
-DocumentStateCommand::DoCommand(const char* aCommandName, nsISupports* refCon) {
+nsresult DocumentStateCommand::DoCommand(const char* aCommandName,
+                                         TextEditor& aTextEditor) const {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_IMETHODIMP
-DocumentStateCommand::DoCommandParams(const char* aCommandName,
-                                      nsICommandParams* aParams,
-                                      nsISupports* refCon) {
+nsresult DocumentStateCommand::DoCommandParams(const char* aCommandName,
+                                               nsCommandParams* aParams,
+                                               TextEditor& aTextEditor) const {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_IMETHODIMP
-DocumentStateCommand::GetCommandStateParams(const char* aCommandName,
-                                            nsICommandParams* aParams,
-                                            nsISupports* refCon) {
-  if (NS_WARN_IF(!aParams) || NS_WARN_IF(!aCommandName)) {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  nsCommandParams* params = aParams->AsCommandParams();
-
-  if (!nsCRT::strcmp(aCommandName, "obs_documentCreated")) {
+nsresult DocumentStateCommand::GetCommandStateParams(
+    const char* aCommandName, nsCommandParams& aParams, TextEditor* aTextEditor,
+    nsIEditingSession* aEditingSession) const {
+  if (!strcmp(aCommandName, "obs_documentCreated")) {
     uint32_t editorStatus = nsIEditingSession::eEditorErrorUnknown;
-
-    nsCOMPtr<nsIEditingSession> editingSession = do_QueryInterface(refCon);
-    if (editingSession) {
-      // refCon 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 = eEditorCreationInProgress
-      nsresult rv = editingSession->GetEditorStatus(&editorStatus);
+    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 refCon is an editor, then everything started up OK!
-      nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-      if (editor) {
-        editorStatus = nsIEditingSession::eEditorOK;
-      }
+    } 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 = params->SetInt(STATE_DATA, editorStatus);
+    DebugOnly<nsresult> rv = aParams.SetInt(STATE_DATA, editorStatus);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to set editor status");
     return NS_OK;
   }
 
-  if (!nsCRT::strcmp(aCommandName, "obs_documentLocationChanged")) {
-    nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
-    if (!editor) {
+  if (!strcmp(aCommandName, "obs_documentLocationChanged")) {
+    if (!aTextEditor) {
       return NS_OK;
     }
-    TextEditor* textEditor = editor->AsTextEditor();
-    MOZ_ASSERT(textEditor);
-
-    RefPtr<Document> doc = textEditor->GetDocument();
-    if (NS_WARN_IF(!doc)) {
+    Document* document = aTextEditor->GetDocument();
+    if (NS_WARN_IF(!document)) {
       return NS_ERROR_FAILURE;
     }
-    nsIURI* uri = doc->GetDocumentURI();
+    nsIURI* uri = document->GetDocumentURI();
     if (NS_WARN_IF(!uri)) {
       return NS_ERROR_FAILURE;
     }
-    nsresult rv = params->SetISupports(STATE_DATA, uri);
+    nsresult rv = aParams.SetISupports(STATE_DATA, uri);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   return NS_ERROR_NOT_IMPLEMENTED;
 }
--- a/editor/libeditor/moz.build
+++ b/editor/libeditor/moz.build
@@ -13,22 +13,22 @@ MOCHITEST_CHROME_MANIFESTS += ['tests/ch
 
 BROWSER_CHROME_MANIFESTS += ['tests/browser.ini']
 
 EXPORTS.mozilla += [
     'ChangeStyleTransaction.h',
     'CSSEditUtils.h',
     'EditAction.h',
     'EditorBase.h',
+    'EditorCommands.h',
     'EditorController.h',
     'EditorDOMPoint.h',
     'EditorUtils.h',
     'EditTransactionBase.h',
     'HTMLEditor.h',
-    'HTMLEditorCommands.h',
     'HTMLEditorController.h',
     'ManualNAC.h',
     'SelectionState.h',
     'TextEditor.h',
     'TextEditRules.h',
 ]
 
 UNIFIED_SOURCES += [
--- a/editor/libeditor/tests/test_bug597331.html
+++ b/editor/libeditor/tests/test_bug597331.html
@@ -4,16 +4,19 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=597331
 -->
 <head>
   <title>Test for Bug 597331</title>
   <script src="/tests/SimpleTest/SimpleTest.js"></script>
   <script src="/tests/SimpleTest/EventUtils.js"></script>
   <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+  textarea { border-color: white; }
+  </style>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=597331">Mozilla Bug 597331</a>
 <p id="display"></p>
 <div id="content">
 <textarea>line1
 line2
 line3
--- a/editor/libeditor/tests/test_bug600570.html
+++ b/editor/libeditor/tests/test_bug600570.html
@@ -4,16 +4,19 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=600570
 -->
 <head>
   <title>Test for Bug 600570</title>
   <script src="/tests/SimpleTest/SimpleTest.js"></script>
   <script src="/tests/SimpleTest/EventUtils.js"></script>
   <script src="/tests/SimpleTest/WindowSnapshot.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+  textarea { border-color: white; }
+  </style>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=600570">Mozilla Bug 600570</a>
 <p id="display"></p>
 <div id="content">
 <textarea spellcheck="false">
 aaa
 [bbb]</textarea>
--- a/js/src/vm/GeneratorObject.h
+++ b/js/src/vm/GeneratorObject.h
@@ -123,29 +123,28 @@ class AbstractGeneratorObject : public N
   // JSOP_INITIALYIELD/JSOP_YIELD/JSOP_AWAIT operand) of the yield instruction
   // that suspended the generator. The resumeIndex can be mapped to the
   // bytecode offset (interpreter) or to the native code offset (JIT).
 
   bool isBeforeInitialYield() const {
     return getFixedSlot(RESUME_INDEX_SLOT).isUndefined();
   }
   bool isRunning() const {
-    MOZ_ASSERT(!isClosed());
-    return getFixedSlot(RESUME_INDEX_SLOT).toInt32() == RESUME_INDEX_RUNNING;
+    return getFixedSlot(RESUME_INDEX_SLOT) == Int32Value(RESUME_INDEX_RUNNING);
   }
   bool isClosing() const {
-    return getFixedSlot(RESUME_INDEX_SLOT).toInt32() == RESUME_INDEX_CLOSING;
+    return getFixedSlot(RESUME_INDEX_SLOT) == Int32Value(RESUME_INDEX_CLOSING);
   }
   bool isSuspended() const {
     // Note: also update Baseline's IsSuspendedGenerator code if this
     // changes.
-    MOZ_ASSERT(!isClosed());
     static_assert(RESUME_INDEX_CLOSING < RESUME_INDEX_RUNNING,
                   "test below should return false for RESUME_INDEX_RUNNING");
-    return getFixedSlot(RESUME_INDEX_SLOT).toInt32() < RESUME_INDEX_CLOSING;
+    Value resumeIndex = getFixedSlot(RESUME_INDEX_SLOT);
+    return resumeIndex.isInt32() && resumeIndex.toInt32() < RESUME_INDEX_CLOSING;
   }
   void setRunning() {
     MOZ_ASSERT(isSuspended());
     setFixedSlot(RESUME_INDEX_SLOT, Int32Value(RESUME_INDEX_RUNNING));
   }
   void setClosing() {
     MOZ_ASSERT(isRunning());
     setFixedSlot(RESUME_INDEX_SLOT, Int32Value(RESUME_INDEX_CLOSING));
--- a/layout/reftests/w3c-css/failures.list
+++ b/layout/reftests/w3c-css/failures.list
@@ -231,17 +231,17 @@ fuzzy(0-135,0-80) css-multicol/multicol-
 fuzzy(0-135,0-821) css-multicol/multicol-gap-000.xht
 fuzzy(0-255,0-329) css-multicol/multicol-gap-001.xht
 fuzzy(0-204,0-930) fuzzy-if(skiaContent,0-208,0-930) css-multicol/multicol-gap-002.xht
 fuzzy(0-204,0-930) fuzzy-if(skiaContent,0-208,0-930) css-multicol/multicol-gap-003.xht
 fuzzy(0-107,0-1823) css-multicol/multicol-gap-fraction-001.xht
 fuzzy-if(winWidget||OSX||gtkWidget,0-204,0-1048) fuzzy-if(skiaContent,0-208,0-1048) css-multicol/multicol-gap-large-001.xht
 fuzzy(0-225,0-920) css-multicol/multicol-gap-large-002.xht
 fuzzy(0-204,0-930) fuzzy-if(skiaContent,0-208,0-930) css-multicol/multicol-gap-negative-001.xht
-fails css-multicol/multicol-height-block-child-001.xht
+pref(layout.css.column-span.enabled,true) css-multicol/multicol-height-block-child-001.xht
 fuzzy(0-255,0-3762) css-multicol/multicol-inherit-001.xht
 fuzzy(0-135,0-1893) css-multicol/multicol-inherit-002.xht
 fails-if(!OSX) random-if(OSX) css-multicol/multicol-inherit-003.xht
 fuzzy(0-97,0-264) css-multicol/multicol-list-item-001.xht
 fuzzy(0-73,0-1200) css-multicol/multicol-margin-001.xht
 fuzzy(0-73,0-1200) css-multicol/multicol-margin-002.xht
 fuzzy(0-243,0-3322) fuzzy-if(skiaContent,0-244,0-3322) css-multicol/multicol-margin-child-001.xht
 fuzzy(0-255,0-4008) css-multicol/multicol-nested-002.xht
@@ -269,28 +269,31 @@ fuzzy(0-127,0-500) css-multicol/multicol
 fuzzy(0-94,0-256) css-multicol/multicol-rule-hidden-000.xht
 fuzzy(0-127,0-500) css-multicol/multicol-rule-inset-000.xht
 fuzzy(0-127,0-500) css-multicol/multicol-rule-outset-000.xht
 fails-if(!OSX) random-if(OSX) css-multicol/multicol-rule-px-001.xht
 fuzzy(0-127,0-500) css-multicol/multicol-rule-ridge-000.xht
 fuzzy(0-106,0-354) css-multicol/multicol-rule-solid-000.xht
 fails-if(!OSX) random-if(OSX) css-multicol/multicol-rule-stacking-001.xht
 fails-if(!OSX||webrender) random-if(OSX) css-multicol/multicol-shorthand-001.xht
-fails css-multicol/multicol-span-000.xht
-fails css-multicol/multicol-span-all-001.xht
-fails css-multicol/multicol-span-all-002.xht
-fails css-multicol/multicol-span-all-003.xht
-fails css-multicol/multicol-span-all-margin-001.xht
-fails css-multicol/multicol-span-all-margin-002.xht
-fails css-multicol/multicol-span-all-margin-bottom-001.xht
-fails css-multicol/multicol-span-all-margin-nested-001.xht
-fails css-multicol/multicol-span-all-margin-nested-002.xht
-fails css-multicol/multicol-span-all-margin-nested-firstchild-001.xht
-fails css-multicol/multicol-span-float-001.xht
-fails css-multicol/multicol-span-none-001.xht
+
+# Bug 1547160: Fix existing reftests failure related to column-span
+pref(layout.css.column-span.enabled,true) fails css-multicol/multicol-span-000.xht
+pref(layout.css.column-span.enabled,true) css-multicol/multicol-span-all-001.xht
+pref(layout.css.column-span.enabled,true) css-multicol/multicol-span-all-002.xht
+pref(layout.css.column-span.enabled,true) fails-if(!OSX) random-if(OSX) css-multicol/multicol-span-all-003.xht
+pref(layout.css.column-span.enabled,true) css-multicol/multicol-span-all-margin-001.xht
+pref(layout.css.column-span.enabled,true) css-multicol/multicol-span-all-margin-002.xht
+pref(layout.css.column-span.enabled,true) fails css-multicol/multicol-span-all-margin-bottom-001.xht
+pref(layout.css.column-span.enabled,true) css-multicol/multicol-span-all-margin-nested-001.xht
+pref(layout.css.column-span.enabled,true) fails css-multicol/multicol-span-all-margin-nested-002.xht
+pref(layout.css.column-span.enabled,true) css-multicol/multicol-span-all-margin-nested-firstchild-001.xht
+pref(layout.css.column-span.enabled,true) css-multicol/multicol-span-float-001.xht
+pref(layout.css.column-span.enabled,true) fails css-multicol/multicol-span-none-001.xht
+
 fails css-multicol/multicol-table-cell-001.xht
 fails css-multicol/multicol-table-cell-height-001.xht
 fails css-multicol/multicol-table-cell-height-002.xht
 fails css-multicol/multicol-table-cell-vertical-align-001.xht
 fuzzy(0-204,0-930) fuzzy-if(skiaContent,0-208,0-930) css-multicol/multicol-width-002.xht
 fails-if(!OSX) random-if(OSX) css-multicol/multicol-width-count-002.xht
 fails-if(!OSX) random-if(OSX) css-multicol/multicol-width-negative-001.xht
 fuzzy(0-225,0-1060) css-multicol/multicol-width-large-001.xht
@@ -303,17 +306,17 @@ fuzzy-if(OSX&&!webrender,255-255,100-150
 
 #This test seems to pass only on Linux-opt build, on everything else
 #Therefore using fuzzy annotation as a catch all
 fuzzy(0-255,0-2808) css-multicol/multicol-rule-large-001.xht
 
 # fails because column-span property not implemented (Bug 616436)
 fails css-multicol/multicol-fill-auto-block-children-001.xht
 fails css-multicol/multicol-fill-auto-block-children-002.xht
-fails css-multicol/multicol-span-all-block-sibling-003.xht
+pref(layout.css.column-span.enabled,true) fuzzy-if(winWidget,40-47,8-8) fuzzy-if(OSX,0-27,0-11) css-multicol/multicol-span-all-block-sibling-003.xht
 
 # skip these tests since they haven't been triaged yet.
 # These tests were added to the tree as part of an update for Bug 1430939.
 skip css-multicol/multicol-fill-balance-002.html
 skip css-multicol/multicol-gap-fraction-002.html
 skip css-multicol/multicol-rule-shorthand-2.xht
 skip css-multicol/multicol-width-ch-001.xht
 skip css-values/ex-calc-expression-001.html
--- a/layout/reftests/w3c-css/import-tests.py
+++ b/layout/reftests/w3c-css/import-tests.py
@@ -4,16 +4,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 import os
 from optparse import OptionParser
 from subprocess import Popen, PIPE
 import xml.dom.minidom
 import html5lib
 import fnmatch
 import shutil
+import string
 import sys
 import re
 
 # FIXME:
 #   * Import more tests rather than just the very limited set currently
 #     chosen.
 #   * Read in a (checked-in) input file with a list of test assertions
 #     expected to fail.
@@ -153,17 +154,17 @@ def copy_support_files(test, dirname):
     global gSrcPath
     if dirname in support_dirs_mapped:
         return
     support_dirs_mapped.add(dirname)
     support_dir = os.path.join(dirname, "support")
     if not os.path.exists(support_dir):
         return
     for dirpath, dirnames, filenames in os.walk(support_dir):
-        for srcname in filenames:
+        for srcname in sorted(filenames, key=string.lower):
             if srcname == "LOCK":
                 continue
             full_srcname = os.path.join(dirpath, srcname)
             destname = to_unix_path_sep(os.path.relpath(full_srcname, gSrcPath))
             copy_file(test, full_srcname, destname, True)
 
 def map_file(srcname):
     global gSrcPath
@@ -341,17 +342,23 @@ def main():
     write_log_header()
     remove_existing_dirs()
     populate_test_files()
 
     for t in gTestfiles:
         add_test_items(t)
 
     listfile = open(os.path.join(gDestPath, "reftest.list"), "wb")
-    listfile.write("# THIS FILE IS AUTOGENERATED BY {0}\n# DO NOT EDIT!\n".format(os.path.basename(__file__)))
+    listfile.write(
+        """# THIS FILE IS AUTOGENERATED BY {0}
+# DO NOT EDIT!!!
+# To update the test expectations, please edit failures.list, and rerun
+# {0} locally on web platform tests repository against the
+# revision listed at the beginning of received/import.log.\n\n"""\
+        .format(os.path.basename(__file__)))
     lastDefaultPreferences = None
     for test in tests:
         defaultPreferences = gDefaultPreferences.get(test[1].split("/")[0], None)
         if defaultPreferences != lastDefaultPreferences:
             if defaultPreferences is None:
                 listfile.write("\ndefault-preferences\n\n")
             else:
                 listfile.write("\ndefault-preferences {0}\n\n".format(defaultPreferences))
--- a/layout/reftests/w3c-css/received/import.log
+++ b/layout/reftests/w3c-css/received/import.log
@@ -1,10 +1,10 @@
 Importing revision: 15f199c91a72b0d51bf0a12b3b77827ecb5051ff
-from repository: https://github.com/neerjapancholi/web-platform-tests.git
+from repository: https://github.com/web-platform-tests/wpt.git
 Importing css-conditional/OWNERS to css-conditional/OWNERS
 Importing css-conditional/at-media-whitespace-optional-001.html to css-conditional/at-media-whitespace-optional-001.html
 Importing css-conditional/reference/background-lime.html to css-conditional/reference/background-lime.html
 Importing css-conditional/at-media-whitespace-optional-002.html to css-conditional/at-media-whitespace-optional-002.html
 Importing css-conditional/at-supports-001.html to css-conditional/at-supports-001.html
 Importing css-conditional/at-supports-001-ref.html to css-conditional/at-supports-001-ref.html
 Importing css-conditional/at-supports-002.html to css-conditional/at-supports-002.html
 Importing css-conditional/at-supports-003.html to css-conditional/at-supports-003.html
--- a/layout/reftests/w3c-css/received/reftest.list
+++ b/layout/reftests/w3c-css/received/reftest.list
@@ -1,10 +1,14 @@
 # THIS FILE IS AUTOGENERATED BY import-tests.py
-# DO NOT EDIT!
+# DO NOT EDIT!!!
+# To update the test expectations, please edit failures.list, and rerun
+# import-tests.py locally on web platform tests repository against the
+# revision listed at the beginning of received/import.log.
+
 == css-conditional/at-media-whitespace-optional-001.html css-conditional/reference/background-lime.html
 == css-conditional/at-media-whitespace-optional-002.html css-conditional/reference/background-lime.html
 == css-conditional/at-supports-001.html css-conditional/at-supports-001-ref.html
 == css-conditional/at-supports-002.html css-conditional/at-supports-001-ref.html
 == css-conditional/at-supports-003.html css-conditional/at-supports-001-ref.html
 == css-conditional/at-supports-004.html css-conditional/at-supports-001-ref.html
 == css-conditional/at-supports-005.html css-conditional/at-supports-001-ref.html
 == css-conditional/at-supports-006.html css-conditional/at-supports-001-ref.html
@@ -93,17 +97,17 @@ fuzzy(0-255,0-329) == css-multicol/multi
 fuzzy(0-204,0-930) fuzzy-if(skiaContent,0-208,0-930) == css-multicol/multicol-gap-002.xht css-multicol/multicol-gap-002-ref.xht
 fuzzy(0-204,0-930) fuzzy-if(skiaContent,0-208,0-930) == css-multicol/multicol-gap-003.xht css-multicol/multicol-gap-002-ref.xht
 fuzzy(0-107,0-1823) == css-multicol/multicol-gap-fraction-001.xht css-multicol/multicol-gap-fraction-001-ref.xht
 skip == css-multicol/multicol-gap-fraction-002.html reference/nothing.html
 fuzzy-if(winWidget||OSX||gtkWidget,0-204,0-1048) fuzzy-if(skiaContent,0-208,0-1048) == css-multicol/multicol-gap-large-001.xht css-multicol/multicol-gap-large-001-ref.xht
 fuzzy(0-225,0-920) == css-multicol/multicol-gap-large-002.xht css-multicol/multicol-gap-large-002-ref.xht
 fuzzy(0-204,0-930) fuzzy-if(skiaContent,0-208,0-930) == css-multicol/multicol-gap-negative-001.xht css-multicol/multicol-gap-002-ref.xht
 == css-multicol/multicol-height-001.xht css-multicol/multicol-height-001-ref.xht
-fails == css-multicol/multicol-height-block-child-001.xht css-multicol/multicol-height-block-child-001-ref.xht
+pref(layout.css.column-span.enabled,true) == css-multicol/multicol-height-block-child-001.xht css-multicol/multicol-height-block-child-001-ref.xht
 fuzzy(0-255,0-3762) == css-multicol/multicol-inherit-001.xht css-multicol/multicol-inherit-001-ref.xht
 fuzzy(0-135,0-1893) == css-multicol/multicol-inherit-002.xht css-multicol/multicol-inherit-002-ref.xht
 fails-if(!OSX) random-if(OSX) == css-multicol/multicol-inherit-003.xht css-multicol/multicol-inherit-3-ref.xht
 fuzzy(0-97,0-264) == css-multicol/multicol-list-item-001.xht css-multicol/multicol-list-item-001-ref.xht
 fuzzy(0-73,0-1200) == css-multicol/multicol-margin-001.xht reference/ref-filled-green-100px-square.xht
 fuzzy(0-73,0-1200) == css-multicol/multicol-margin-002.xht reference/ref-filled-green-100px-square.xht
 fuzzy(0-243,0-3322) fuzzy-if(skiaContent,0-244,0-3322) == css-multicol/multicol-margin-child-001.xht css-multicol/multicol-margin-child-001-ref.xht
 fuzzy(0-255,0-4008) == css-multicol/multicol-nested-002.xht css-multicol/multicol-nested-002-ref.xht
@@ -141,29 +145,29 @@ fuzzy(0-127,0-500) == css-multicol/multi
 fails-if(!OSX) random-if(OSX) == css-multicol/multicol-rule-px-001.xht css-multicol/multicol-rule-ref.xht
 fuzzy(0-127,0-500) == css-multicol/multicol-rule-ridge-000.xht css-multicol/multicol-rule-ridge-000-ref.xht
 == css-multicol/multicol-rule-samelength-001.xht css-multicol/multicol-rule-samelength-001-ref.xht
 == css-multicol/multicol-rule-shorthand-001.xht css-multicol/multicol-rule-samelength-001-ref.xht
 skip == css-multicol/multicol-rule-shorthand-2.xht css-multicol/multicol-rule-shorthand-2-ref.xht
 fuzzy(0-106,0-354) == css-multicol/multicol-rule-solid-000.xht css-multicol/multicol-rule-solid-000-ref.xht
 fails-if(!OSX) random-if(OSX) == css-multicol/multicol-rule-stacking-001.xht css-multicol/multicol-rule-stacking-ref.xht
 fails-if(!OSX||webrender) random-if(OSX) == css-multicol/multicol-shorthand-001.xht css-multicol/multicol-rule-ref.xht
-fails == css-multicol/multicol-span-000.xht css-multicol/multicol-span-000-ref.xht
-fails == css-multicol/multicol-span-all-001.xht css-multicol/multicol-span-all-001-ref.xht
-fails == css-multicol/multicol-span-all-002.xht css-multicol/multicol-span-all-002-ref.xht
-fails == css-multicol/multicol-span-all-003.xht css-multicol/multicol-count-002-ref.xht
-fails == css-multicol/multicol-span-all-block-sibling-003.xht css-multicol/multicol-span-all-block-sibling-3-ref.xht
-fails == css-multicol/multicol-span-all-margin-001.xht css-multicol/multicol-span-all-margin-001-ref.xht
-fails == css-multicol/multicol-span-all-margin-002.xht css-multicol/multicol-span-all-margin-002-ref.xht
-fails == css-multicol/multicol-span-all-margin-bottom-001.xht css-multicol/multicol-span-all-margin-bottom-001-ref.xht
-fails == css-multicol/multicol-span-all-margin-nested-001.xht css-multicol/multicol-span-all-margin-nested-001-ref.xht
-fails == css-multicol/multicol-span-all-margin-nested-002.xht css-multicol/multicol-span-all-margin-nested-001-ref.xht
-fails == css-multicol/multicol-span-all-margin-nested-firstchild-001.xht css-multicol/multicol-span-all-margin-nested-firstchild-ref.xht
-fails == css-multicol/multicol-span-float-001.xht css-multicol/multicol-span-float-001-ref.xht
-fails == css-multicol/multicol-span-none-001.xht css-multicol/multicol-span-none-001-ref.xht
+pref(layout.css.column-span.enabled,true) fails == css-multicol/multicol-span-000.xht css-multicol/multicol-span-000-ref.xht
+pref(layout.css.column-span.enabled,true) == css-multicol/multicol-span-all-001.xht css-multicol/multicol-span-all-001-ref.xht
+pref(layout.css.column-span.enabled,true) == css-multicol/multicol-span-all-002.xht css-multicol/multicol-span-all-002-ref.xht
+pref(layout.css.column-span.enabled,true) fails-if(!OSX) random-if(OSX) == css-multicol/multicol-span-all-003.xht css-multicol/multicol-count-002-ref.xht
+pref(layout.css.column-span.enabled,true) fuzzy-if(winWidget,40-47,8-8) fuzzy-if(OSX,0-27,0-11) == css-multicol/multicol-span-all-block-sibling-003.xht css-multicol/multicol-span-all-block-sibling-3-ref.xht
+pref(layout.css.column-span.enabled,true) == css-multicol/multicol-span-all-margin-001.xht css-multicol/multicol-span-all-margin-001-ref.xht
+pref(layout.css.column-span.enabled,true) == css-multicol/multicol-span-all-margin-002.xht css-multicol/multicol-span-all-margin-002-ref.xht
+pref(layout.css.column-span.enabled,true) fails == css-multicol/multicol-span-all-margin-bottom-001.xht css-multicol/multicol-span-all-margin-bottom-001-ref.xht
+pref(layout.css.column-span.enabled,true) == css-multicol/multicol-span-all-margin-nested-001.xht css-multicol/multicol-span-all-margin-nested-001-ref.xht
+pref(layout.css.column-span.enabled,true) fails == css-multicol/multicol-span-all-margin-nested-002.xht css-multicol/multicol-span-all-margin-nested-001-ref.xht
+pref(layout.css.column-span.enabled,true) == css-multicol/multicol-span-all-margin-nested-firstchild-001.xht css-multicol/multicol-span-all-margin-nested-firstchild-ref.xht
+pref(layout.css.column-span.enabled,true) == css-multicol/multicol-span-float-001.xht css-multicol/multicol-span-float-001-ref.xht
+pref(layout.css.column-span.enabled,true) fails == css-multicol/multicol-span-none-001.xht css-multicol/multicol-span-none-001-ref.xht
 fails == css-multicol/multicol-table-cell-001.xht css-multicol/multicol-table-cell-001-ref.xht
 fails == css-multicol/multicol-table-cell-height-001.xht css-multicol/multicol-table-cell-height-001-ref.xht
 fails == css-multicol/multicol-table-cell-height-002.xht css-multicol/multicol-table-cell-height-001-ref.xht
 fails == css-multicol/multicol-table-cell-vertical-align-001.xht css-multicol/multicol-table-cell-vertical-align-ref.xht
 == css-multicol/multicol-width-001.xht css-multicol/multicol-width-001-ref.xht
 fuzzy(0-204,0-930) fuzzy-if(skiaContent,0-208,0-930) == css-multicol/multicol-width-002.xht css-multicol/multicol-width-002-ref.xht
 == css-multicol/multicol-width-003.xht css-multicol/multicol-width-002-ref.xht
 skip == css-multicol/multicol-width-ch-001.xht css-multicol/multicol-width-ch-ref.xht
--- a/netwerk/protocol/http/AlternateServices.cpp
+++ b/netwerk/protocol/http/AlternateServices.cpp
@@ -46,18 +46,18 @@ static nsresult SchemeIsHTTPS(const nsAC
 
 bool AltSvcMapping::AcceptableProxy(nsProxyInfo *proxyInfo) {
   return !proxyInfo || proxyInfo->IsDirect() || proxyInfo->IsSOCKS();
 }
 
 void AltSvcMapping::ProcessHeader(
     const nsCString &buf, const nsCString &originScheme,
     const nsCString &originHost, int32_t originPort, const nsACString &username,
-    bool privateBrowsing, nsIInterfaceRequestor *callbacks,
-    nsProxyInfo *proxyInfo, uint32_t caps,
+    const nsACString &topWindowOrigin, bool privateBrowsing,
+    nsIInterfaceRequestor *callbacks, nsProxyInfo *proxyInfo, uint32_t caps,
     const OriginAttributes &originAttributes) {
   MOZ_ASSERT(NS_IsMainThread());
   LOG(("AltSvcMapping::ProcessHeader: %s\n", buf.get()));
   if (!callbacks) {
     return;
   }
 
   if (!AcceptableProxy(proxyInfo)) {
@@ -140,18 +140,18 @@ void AltSvcMapping::ProcessHeader(
           spdyInfo->ProtocolEnabled(spdyIndex))) {
       LOG(("Alt Svc unknown protocol %s, ignoring", npnToken.get()));
       continue;
     }
 
     RefPtr<AltSvcMapping> mapping = new AltSvcMapping(
         gHttpHandler->ConnMgr()->GetStoragePtr(),
         gHttpHandler->ConnMgr()->StorageEpoch(), originScheme, originHost,
-        originPort, username, privateBrowsing, NowInSeconds() + maxage,
-        hostname, portno, npnToken, originAttributes);
+        originPort, username, topWindowOrigin, privateBrowsing,
+        NowInSeconds() + maxage, hostname, portno, npnToken, originAttributes);
     if (mapping->TTL() <= 0) {
       LOG(("Alt Svc invalid map"));
       mapping = nullptr;
       // since this isn't a parse error, let's clear any existing mapping
       // as that would have happened if we had accepted the parameters.
       gHttpHandler->ConnMgr()->ClearHostMapping(originHost, originPort,
                                                 originAttributes);
     } else {
@@ -164,28 +164,30 @@ void AltSvcMapping::ProcessHeader(
     Telemetry::Accumulate(Telemetry::HTTP_ALTSVC_ENTRIES_PER_HEADER,
                           numEntriesInHeader);
   }
 }
 
 AltSvcMapping::AltSvcMapping(DataStorage *storage, int32_t epoch,
                              const nsACString &originScheme,
                              const nsACString &originHost, int32_t originPort,
-                             const nsACString &username, bool privateBrowsing,
-                             uint32_t expiresAt,
+                             const nsACString &username,
+                             const nsACString &topWindowOrigin,
+                             bool privateBrowsing, uint32_t expiresAt,
                              const nsACString &alternateHost,
                              int32_t alternatePort, const nsACString &npnToken,
                              const OriginAttributes &originAttributes)
     : mStorage(storage),
       mStorageEpoch(epoch),
       mAlternateHost(alternateHost),
       mAlternatePort(alternatePort),
       mOriginHost(originHost),
       mOriginPort(originPort),
       mUsername(username),
+      mTopWindowOrigin(topWindowOrigin),
       mPrivate(privateBrowsing),
       mExpiresAt(expiresAt),
       mValidated(false),
       mMixedScheme(false),
       mNPNToken(npnToken),
       mOriginAttributes(originAttributes),
       mSyncOnlyOnSuccess(false) {
   MOZ_ASSERT(NS_IsMainThread());
@@ -305,18 +307,18 @@ bool AltSvcMapping::RouteEquals(AltSvcMa
          (mAlternatePort == map->mAlternatePort) &&
          mNPNToken.Equals(map->mNPNToken);
 }
 
 void AltSvcMapping::GetConnectionInfo(
     nsHttpConnectionInfo **outCI, nsProxyInfo *pi,
     const OriginAttributes &originAttributes) {
   RefPtr<nsHttpConnectionInfo> ci = new nsHttpConnectionInfo(
-      mOriginHost, mOriginPort, mNPNToken, mUsername, pi, originAttributes,
-      mAlternateHost, mAlternatePort);
+      mOriginHost, mOriginPort, mNPNToken, mUsername, mTopWindowOrigin, pi,
+      originAttributes, mAlternateHost, mAlternatePort);
 
   // http:// without the mixed-scheme attribute needs to be segmented in the
   // connection manager connection information hash with this attribute
   if (!mHttps && !mMixedScheme) {
     ci->SetInsecureScheme(true);
   }
   ci->SetPrivate(mPrivate);
   ci.forget(outCI);
@@ -329,16 +331,18 @@ void AltSvcMapping::Serialize(nsCString 
   out.AppendInt(mOriginPort);
   out.Append(':');
   out.Append(mAlternateHost);
   out.Append(':');
   out.AppendInt(mAlternatePort);
   out.Append(':');
   out.Append(mUsername);
   out.Append(':');
+  out.Append(mTopWindowOrigin);
+  out.Append('|');  // Be careful, the top window origin may contain colons!
   out.Append(mPrivate ? 'y' : 'n');
   out.Append(':');
   out.AppendInt(mExpiresAt);
   out.Append(':');
   out.Append(mNPNToken);
   out.Append(':');
   out.Append(mValidated ? 'y' : 'n');
   out.Append(':');
@@ -352,44 +356,51 @@ void AltSvcMapping::Serialize(nsCString 
   out.Append(':');
 }
 
 AltSvcMapping::AltSvcMapping(DataStorage *storage, int32_t epoch,
                              const nsCString &str)
     : mStorage(storage), mStorageEpoch(epoch), mSyncOnlyOnSuccess(false) {
   mValidated = false;
   nsresult code;
+  char separator = ':';
 
   // The the do {} while(0) loop acts like try/catch(e){} with the break in
   // _NS_NEXT_TOKEN
   do {
 #ifdef _NS_NEXT_TOKEN
     COMPILER ERROR
 #endif
-#define _NS_NEXT_TOKEN            \
-  start = idx + 1;                \
-  idx = str.FindChar(':', start); \
+#define _NS_NEXT_TOKEN                  \
+  start = idx + 1;                      \
+  idx = str.FindChar(separator, start); \
   if (idx < 0) break;
         int32_t start = 0;
     int32_t idx;
-    idx = str.FindChar(':', start);
+    idx = str.FindChar(separator, start);
     if (idx < 0) break;
     mHttps = Substring(str, start, idx - start).EqualsLiteral("https");
     _NS_NEXT_TOKEN;
     mOriginHost = Substring(str, start, idx - start);
     _NS_NEXT_TOKEN;
     mOriginPort =
         nsCString(Substring(str, start, idx - start)).ToInteger(&code);
     _NS_NEXT_TOKEN;
     mAlternateHost = Substring(str, start, idx - start);
     _NS_NEXT_TOKEN;
     mAlternatePort =
         nsCString(Substring(str, start, idx - start)).ToInteger(&code);
     _NS_NEXT_TOKEN;
     mUsername = Substring(str, start, idx - start);
+    // The separator after the top window origin is a pipe character since the
+    // origin string can contain colons.
+    separator = '|';
+    _NS_NEXT_TOKEN;
+    mTopWindowOrigin = Substring(str, start, idx - start);
+    separator = ':';
     _NS_NEXT_TOKEN;
     mPrivate = Substring(str, start, idx - start).EqualsLiteral("y");
     _NS_NEXT_TOKEN;
     mExpiresAt = nsCString(Substring(str, start, idx - start)).ToInteger(&code);
     _NS_NEXT_TOKEN;
     mNPNToken = Substring(str, start, idx - start);
     _NS_NEXT_TOKEN;
     mValidated = Substring(str, start, idx - start).EqualsLiteral("y");
--- a/netwerk/protocol/http/AlternateServices.h
+++ b/netwerk/protocol/http/AlternateServices.h
@@ -44,28 +44,30 @@ class WellKnownChecker;
 
 class AltSvcMapping {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AltSvcMapping)
 
  private:  // ctor from ProcessHeader
   AltSvcMapping(DataStorage *storage, int32_t storageEpoch,
                 const nsACString &originScheme, const nsACString &originHost,
                 int32_t originPort, const nsACString &username,
-                bool privateBrowsing, uint32_t expiresAt,
-                const nsACString &alternateHost, int32_t alternatePort,
-                const nsACString &npnToken,
+                const nsACString &topWindowOrigin, bool privateBrowsing,
+                uint32_t expiresAt, const nsACString &alternateHost,
+                int32_t alternatePort, const nsACString &npnToken,
                 const OriginAttributes &originAttributes);
 
  public:
   AltSvcMapping(DataStorage *storage, int32_t storageEpoch,
                 const nsCString &serialized);
 
   static void ProcessHeader(const nsCString &buf, const nsCString &originScheme,
                             const nsCString &originHost, int32_t originPort,
-                            const nsACString &username, bool privateBrowsing,
+                            const nsACString &username,
+                            const nsACString &topWindowOrigin,
+                            bool privateBrowsing,
                             nsIInterfaceRequestor *callbacks,
                             nsProxyInfo *proxyInfo, uint32_t caps,
                             const OriginAttributes &originAttributes);
 
   // AcceptableProxy() decides whether a particular proxy configuration (pi) is
   // suitable for use with Alt-Svc. No proxy (including a null pi) is suitable.
   static bool AcceptableProxy(nsProxyInfo *pi);
 
@@ -110,16 +112,17 @@ class AltSvcMapping {
   // If you change any of these members, update Serialize()
   nsCString mAlternateHost;
   MOZ_INIT_OUTSIDE_CTOR int32_t mAlternatePort;
 
   nsCString mOriginHost;
   MOZ_INIT_OUTSIDE_CTOR int32_t mOriginPort;
 
   nsCString mUsername;
+  nsCString mTopWindowOrigin;
   MOZ_INIT_OUTSIDE_CTOR bool mPrivate;
 
   MOZ_INIT_OUTSIDE_CTOR uint32_t mExpiresAt;  // alt-svc mappping
 
   MOZ_INIT_OUTSIDE_CTOR bool mValidated;
   MOZ_INIT_OUTSIDE_CTOR bool mHttps;  // origin is https://
   MOZ_INIT_OUTSIDE_CTOR bool
       mMixedScheme;  // .wk allows http and https on same con
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -2511,20 +2511,20 @@ class UpdateAltSvcEvent : public Runnabl
     if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), mOrigin))) {
       LOG(("UpdateAltSvcEvent origin does not parse %s\n", mOrigin.get()));
       return NS_OK;
     }
     uri->GetScheme(originScheme);
     uri->GetHost(originHost);
     uri->GetPort(&originPort);
 
-    AltSvcMapping::ProcessHeader(mHeader, originScheme, originHost, originPort,
-                                 mCI->GetUsername(), mCI->GetPrivate(),
-                                 mCallbacks, mCI->ProxyInfo(), 0,
-                                 mCI->GetOriginAttributes());
+    AltSvcMapping::ProcessHeader(
+        mHeader, originScheme, originHost, originPort, mCI->GetUsername(),
+        mCI->GetTopWindowOrigin(), mCI->GetPrivate(), mCallbacks,
+        mCI->ProxyInfo(), 0, mCI->GetOriginAttributes());
     return NS_OK;
   }
 
  private:
   nsCString mHeader;
   nsCString mOrigin;
   RefPtr<nsHttpConnectionInfo> mCI;
   nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -329,16 +329,19 @@ nsHttpChannel::nsHttpChannel()
       mHasAutoRedirectVetoNotifier(0),
       mPinCacheContent(0),
       mIsCorsPreflightDone(0),
       mStronglyFramed(false),
       mUsedNetwork(0),
       mAuthConnectionRestartable(0),
       mChannelClassifierCancellationPending(0),
       mAsyncResumePending(0),
+      mHasBeenIsolatedChecked(0),
+      mIsIsolated(0),
+      mTopWindowOriginComputed(0),
       mPushedStream(nullptr),
       mLocalBlocklist(false),
       mOnTailUnblock(nullptr),
       mWarningReporter(nullptr),
       mIsReadingFromCache(false),
       mFirstResponseSource(RESPONSE_PENDING),
       mRaceCacheWithNetwork(false),
       mRaceDelay(0),
@@ -620,23 +623,20 @@ nsresult nsHttpChannel::ContinueOnBefore
   if (mTRR) {
     mCaps |= NS_HTTP_LARGE_KEEPALIVE | NS_HTTP_DISABLE_TRR;
   }
 
   if (mLoadFlags & LOAD_DISABLE_TRR) {
     mCaps |= NS_HTTP_DISABLE_TRR;
   }
 
-  bool isIsolated = mPrivateBrowsing ||
-                    !AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
-                        this, mURI, nullptr);
-
   // Finalize ConnectionInfo flags before SpeculativeConnect
   mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
-  mConnectionInfo->SetPrivate(isIsolated);
+  mConnectionInfo->SetPrivate(mPrivateBrowsing);
+  mConnectionInfo->SetIsolated(IsIsolated());
   mConnectionInfo->SetNoSpdy(mCaps & NS_HTTP_DISALLOW_SPDY);
   mConnectionInfo->SetBeConservative((mCaps & NS_HTTP_BE_CONSERVATIVE) ||
                                      mBeConservative);
   mConnectionInfo->SetTlsFlags(mTlsFlags);
   mConnectionInfo->SetTrrUsed(mTRR);
   mConnectionInfo->SetTrrDisabled(mCaps & NS_HTTP_DISABLE_TRR);
   mConnectionInfo->SetIPv4Disabled(mCaps & NS_HTTP_DISABLE_IPV4);
   mConnectionInfo->SetIPv6Disabled(mCaps & NS_HTTP_DISABLE_IPV6);
@@ -2363,19 +2363,20 @@ void nsHttpChannel::ProcessAltService() 
                                          getter_AddRefs(callbacks));
   if (mProxyInfo) {
     proxyInfo = do_QueryInterface(mProxyInfo);
   }
 
   OriginAttributes originAttributes;
   NS_GetOriginAttributes(this, originAttributes);
 
-  AltSvcMapping::ProcessHeader(
-      altSvc, scheme, originHost, originPort, mUsername, mPrivateBrowsing,
-      callbacks, proxyInfo, mCaps & NS_HTTP_DISALLOW_SPDY, originAttributes);
+  AltSvcMapping::ProcessHeader(altSvc, scheme, originHost, originPort,
+                               mUsername, GetTopWindowOrigin(),
+                               mPrivateBrowsing, callbacks, proxyInfo,
+                               mCaps & NS_HTTP_DISALLOW_SPDY, originAttributes);
 }
 
 nsresult nsHttpChannel::ProcessResponse() {
   uint32_t httpStatus = mResponseHead->Status();
 
   LOG(("nsHttpChannel::ProcessResponse [this=%p httpStatus=%u]\n", this,
        httpStatus));
 
@@ -3890,16 +3891,52 @@ nsresult nsHttpChannel::OpenCacheEntry(b
     if (appCacheContainer) {
       appCacheContainer->GetApplicationCache(getter_AddRefs(mApplicationCache));
     }
   }
 
   return OpenCacheEntryInternal(isHttps, mApplicationCache, true);
 }
 
+bool nsHttpChannel::IsIsolated() {
+  if (mHasBeenIsolatedChecked) {
+    return mIsIsolated;
+  }
+  mIsIsolated = IsThirdPartyTrackingResource() &&
+                !AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(
+                    this, mURI, nullptr);
+  mHasBeenIsolatedChecked = true;
+  return mIsIsolated;
+}
+
+const nsCString &nsHttpChannel::GetTopWindowOrigin() {
+  if (mTopWindowOriginComputed) {
+    return mTopWindowOrigin;
+  }
+
+  nsCOMPtr<nsIURI> topWindowURI;
+  nsresult rv = GetTopWindowURI(getter_AddRefs(topWindowURI));
+  bool isDocument = false;
+  if (NS_FAILED(rv) && NS_SUCCEEDED(GetIsMainDocumentChannel(&isDocument)) &&
+      isDocument) {
+    // For top-level documents, use the document channel's origin to compute
+    // the unique storage space identifier instead of the top Window URI.
+    rv = NS_GetFinalChannelURI(this, getter_AddRefs(topWindowURI));
+    NS_ENSURE_SUCCESS(rv, mTopWindowOrigin);
+  }
+
+  rv = nsContentUtils::GetASCIIOrigin(topWindowURI ? topWindowURI : mURI,
+                                      mTopWindowOrigin);
+  NS_ENSURE_SUCCESS(rv, mTopWindowOrigin);
+
+  mTopWindowOriginComputed = true;
+
+  return mTopWindowOrigin;
+}
+
 nsresult nsHttpChannel::OpenCacheEntryInternal(
     bool isHttps, nsIApplicationCache *applicationCache,
     bool allowApplicationCache) {
   MOZ_ASSERT_IF(!allowApplicationCache, !applicationCache);
 
   nsresult rv;
 
   if (mResuming) {
@@ -4009,37 +4046,24 @@ nsresult nsHttpChannel::OpenCacheEntryIn
 
   if (mPostID) {
     extension.Append(nsPrintfCString("%d", mPostID));
   }
   if (mTRR) {
     extension.Append("TRR");
   }
 
-  if (IsThirdPartyTrackingResource() &&
-      !AntiTrackingCommon::IsFirstPartyStorageAccessGrantedFor(this, mURI,
-                                                               nullptr)) {
-    nsCOMPtr<nsIURI> topWindowURI;
-    rv = GetTopWindowURI(getter_AddRefs(topWindowURI));
-    bool isDocument = false;
-    if (NS_FAILED(rv) && NS_SUCCEEDED(GetIsMainDocumentChannel(&isDocument)) &&
-        isDocument) {
-      // For top-level documents, use the document channel's origin to compute
-      // the unique storage space identifier instead of the top Window URI.
-      rv = NS_GetFinalChannelURI(this, getter_AddRefs(topWindowURI));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    nsAutoString topWindowOrigin;
-    rv = nsContentUtils::GetUTFOrigin(topWindowURI ? topWindowURI : mURI,
-                                      topWindowOrigin);
-    NS_ENSURE_SUCCESS(rv, rv);
+  if (IsIsolated()) {
+    auto &topWindowOrigin = GetTopWindowOrigin();
+    if (topWindowOrigin.IsEmpty()) {
+      return NS_ERROR_FAILURE;
+    }
 
     extension.Append("-unique:");
-    extension.Append(NS_ConvertUTF16toUTF8(topWindowOrigin));
+    extension.Append(topWindowOrigin);
   }
 
   mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
   mCacheQueueSizeWhenOpen =
       CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
 
   if (sRCWNEnabled && maybeRCWN && !mApplicationCacheForWrite) {
     bool hasAltData = false;
@@ -6536,19 +6560,19 @@ nsresult nsHttpChannel::BeginConnect() {
   mRequestHead.SetOrigin(scheme, host, port);
 
   SetOriginHeader();
   SetDoNotTrack();
 
   OriginAttributes originAttributes;
   NS_GetOriginAttributes(this, originAttributes);
 
-  RefPtr<nsHttpConnectionInfo> connInfo =
-      new nsHttpConnectionInfo(host, port, EmptyCString(), mUsername, proxyInfo,
-                               originAttributes, isHttps);
+  RefPtr<nsHttpConnectionInfo> connInfo = new nsHttpConnectionInfo(
+      host, port, EmptyCString(), mUsername, GetTopWindowOrigin(), proxyInfo,
+      originAttributes, isHttps);
   mAllowAltSvc = (mAllowAltSvc && !gHttpHandler->IsSpdyBlacklisted(connInfo));
 
   RefPtr<AltSvcMapping> mapping;
   if (!mConnectionInfo && mAllowAltSvc &&  // per channel
       !(mLoadFlags & LOAD_FRESH_CONNECTION) &&
       AltSvcMapping::AcceptableProxy(proxyInfo) &&
       (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
       (mapping = gHttpHandler->GetAltServiceMapping(
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -541,16 +541,20 @@ class nsHttpChannel final : public HttpB
 
   void MaybeWarnAboutAppCache();
 
   void SetLoadGroupUserAgentOverride();
 
   void SetOriginHeader();
   void SetDoNotTrack();
 
+  bool IsIsolated();
+
+  const nsCString &GetTopWindowOrigin();
+
   already_AddRefed<nsChannelClassifier> GetOrCreateChannelClassifier();
 
   // Start an internal redirect to a new InterceptedHttpChannel which will
   // resolve in firing a ServiceWorker FetchEvent.
   MOZ_MUST_USE nsresult RedirectToInterceptedChannel();
 
   // Determines and sets content type in the cache entry. It's called when
   // writing a new entry. The content type is used in cache internally only.
@@ -713,16 +717,31 @@ class nsHttpChannel final : public HttpB
   // to the safe-browsing classifier rules, but the asynchronous cancellation
   // process hasn't finished yet.
   uint32_t mChannelClassifierCancellationPending : 1;
 
   // True only when we are between Resume and async fire of mCallOnResume.
   // Used to suspend any newly created pumps in mCallOnResume handler.
   uint32_t mAsyncResumePending : 1;
 
+  // True only when we have checked whether this channel has been isolated for
+  // anti-tracking purposes.
+  uint32_t mHasBeenIsolatedChecked : 1;
+  // True only when we have determined this channel should be isolated for
+  // anti-tracking purposes.  Can never ben true unless mHasBeenIsolatedChecked
+  // is true.
+  uint32_t mIsIsolated : 1;
+
+  // True only when we have computed the value of the top window origin.
+  uint32_t mTopWindowOriginComputed : 1;
+
+  // The origin of the top window, only valid when mTopWindowOriginComputed is
+  // true.
+  nsCString mTopWindowOrigin;
+
   nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
 
   // Needed for accurate DNS timing
   RefPtr<nsDNSPrefetch> mDNSPrefetch;
 
   Http2PushedStream *mPushedStream;
   // True if the channel's principal was found on a phishing, malware, or
   // tracking (if tracking protection is enabled) blocklist
--- a/netwerk/protocol/http/nsHttpConnectionInfo.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.cpp
@@ -38,48 +38,70 @@ static nsresult SHA256(const char *aPlai
 }
 
 namespace mozilla {
 namespace net {
 
 nsHttpConnectionInfo::nsHttpConnectionInfo(
     const nsACString &originHost, int32_t originPort,
     const nsACString &npnToken, const nsACString &username,
-    nsProxyInfo *proxyInfo, const OriginAttributes &originAttributes,
-    bool endToEndSSL)
-    : mRoutedPort(443), mLessThanTls13(false) {
-  Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes,
-       endToEndSSL);
+    const nsACString &topWindowOrigin, nsProxyInfo *proxyInfo,
+    const OriginAttributes &originAttributes, bool endToEndSSL, bool isolated)
+    : mRoutedPort(443), mIsolated(isolated), mLessThanTls13(false) {
+  Init(originHost, originPort, npnToken, username, topWindowOrigin, proxyInfo,
+       originAttributes, endToEndSSL);
 }
 
 nsHttpConnectionInfo::nsHttpConnectionInfo(
     const nsACString &originHost, int32_t originPort,
     const nsACString &npnToken, const nsACString &username,
-    nsProxyInfo *proxyInfo, const OriginAttributes &originAttributes,
-    const nsACString &routedHost, int32_t routedPort)
-    : mLessThanTls13(false) {
+    const nsACString &topWindowOrigin, nsProxyInfo *proxyInfo,
+    const OriginAttributes &originAttributes, bool endToEndSSL)
+    : nsHttpConnectionInfo(originHost, originPort, npnToken, username,
+                           topWindowOrigin, proxyInfo, originAttributes,
+                           endToEndSSL, false) {}
+
+nsHttpConnectionInfo::nsHttpConnectionInfo(
+    const nsACString &originHost, int32_t originPort,
+    const nsACString &npnToken, const nsACString &username,
+    const nsACString &topWindowOrigin, nsProxyInfo *proxyInfo,
+    const OriginAttributes &originAttributes, const nsACString &routedHost,
+    int32_t routedPort, bool isolated)
+    : mIsolated(isolated), mLessThanTls13(false) {
   mEndToEndSSL = true;  // so DefaultPort() works
   mRoutedPort = routedPort == -1 ? DefaultPort() : routedPort;
 
   if (!originHost.Equals(routedHost) || (originPort != routedPort)) {
     mRoutedHost = routedHost;
   }
-  Init(originHost, originPort, npnToken, username, proxyInfo, originAttributes,
-       true);
+  Init(originHost, originPort, npnToken, username, topWindowOrigin, proxyInfo,
+       originAttributes, true);
 }
 
+nsHttpConnectionInfo::nsHttpConnectionInfo(
+    const nsACString &originHost, int32_t originPort,
+    const nsACString &npnToken, const nsACString &username,
+    const nsACString &topWindowOrigin, nsProxyInfo *proxyInfo,
+    const OriginAttributes &originAttributes, const nsACString &routedHost,
+    int32_t routedPort)
+    : nsHttpConnectionInfo(originHost, originPort, npnToken, username,
+                           topWindowOrigin, proxyInfo, originAttributes,
+                           routedHost, routedPort, false) {}
+
 void nsHttpConnectionInfo::Init(const nsACString &host, int32_t port,
                                 const nsACString &npnToken,
                                 const nsACString &username,
+                                const nsACString &topWindowOrigin,
                                 nsProxyInfo *proxyInfo,
                                 const OriginAttributes &originAttributes,
                                 bool e2eSSL) {
   LOG(("Init nsHttpConnectionInfo @%p\n", this));
 
   mUsername = username;
+  mTopWindowOrigin = topWindowOrigin;
   mProxyInfo = proxyInfo;
   mEndToEndSSL = e2eSSL;
   mUsingConnect = false;
   mNPNToken = npnToken;
   mOriginAttributes = originAttributes;
   mTlsFlags = 0x0;
   mTrrUsed = false;
   mTrrDisabled = false;
@@ -126,18 +148,22 @@ void nsHttpConnectionInfo::BuildHashKey(
   // The hashkey has 4 fields followed by host connection info
   // byte 0 is P/T/. {P,T} for Plaintext/TLS Proxy over HTTP
   // byte 1 is S/. S is for end to end ssl such as https:// uris
   // byte 2 is A/. A is for an anonymous channel (no cookies, etc..)
   // byte 3 is P/. P is for a private browising channel
   // byte 4 is I/. I is for insecure scheme on TLS for http:// uris
   // byte 5 is X/. X is for disallow_spdy flag
   // byte 6 is C/. C is for be Conservative
+  // byte 7 is i/. i is for isolated
 
-  mHashKey.AssignLiteral(".......[tlsflags0x00000000]");
+  mHashKey.AssignLiteral("........[tlsflags0x00000000]");
+  if (mIsolated) {
+    mHashKey.SetCharAt('i', 7);
+  }
 
   mHashKey.Append(keyHost);
   mHashKey.Append(':');
   mHashKey.AppendInt(keyPort);
   if (!mUsername.IsEmpty()) {
     mHashKey.Append('[');
     mHashKey.Append(mUsername);
     mHashKey.Append(']');
@@ -213,39 +239,47 @@ void nsHttpConnectionInfo::BuildHashKey(
   if (GetIPv4Disabled()) {
     mHashKey.AppendLiteral("[!v4]");
   }
 
   if (GetIPv6Disabled()) {
     mHashKey.AppendLiteral("[!v6]");
   }
 
+  if (mIsolated && !mTopWindowOrigin.IsEmpty()) {
+    mHashKey.Append('{');
+    mHashKey.Append('{');
+    mHashKey.Append(mTopWindowOrigin);
+    mHashKey.Append('}');
+    mHashKey.Append('}');
+  }
+
   nsAutoCString originAttributes;
   mOriginAttributes.CreateSuffix(originAttributes);
   mHashKey.Append(originAttributes);
 }
 
 void nsHttpConnectionInfo::SetOriginServer(const nsACString &host,
                                            int32_t port) {
   mOrigin = host;
   mOriginPort = port == -1 ? DefaultPort() : port;
   BuildHashKey();
 }
 
 already_AddRefed<nsHttpConnectionInfo> nsHttpConnectionInfo::Clone() const {
   RefPtr<nsHttpConnectionInfo> clone;
   if (mRoutedHost.IsEmpty()) {
-    clone =
-        new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
-                                 mProxyInfo, mOriginAttributes, mEndToEndSSL);
+    clone = new nsHttpConnectionInfo(
+        mOrigin, mOriginPort, mNPNToken, mUsername, mTopWindowOrigin,
+        mProxyInfo, mOriginAttributes, mEndToEndSSL, mIsolated);
   } else {
     MOZ_ASSERT(mEndToEndSSL);
-    clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername,
-                                     mProxyInfo, mOriginAttributes, mRoutedHost,
-                                     mRoutedPort);
+    clone = new nsHttpConnectionInfo(
+        mOrigin, mOriginPort, mNPNToken, mUsername, mTopWindowOrigin,
+        mProxyInfo, mOriginAttributes, mRoutedHost, mRoutedPort, mIsolated);
   }
 
   // Make sure the anonymous, insecure-scheme, and private flags are transferred
   clone->SetAnonymous(GetAnonymous());
   clone->SetPrivate(GetPrivate());
   clone->SetInsecureScheme(GetInsecureScheme());
   clone->SetNoSpdy(GetNoSpdy());
   clone->SetBeConservative(GetBeConservative());
@@ -261,19 +295,19 @@ already_AddRefed<nsHttpConnectionInfo> n
 
 void nsHttpConnectionInfo::CloneAsDirectRoute(nsHttpConnectionInfo **outCI) {
   if (mRoutedHost.IsEmpty()) {
     RefPtr<nsHttpConnectionInfo> clone = Clone();
     clone.forget(outCI);
     return;
   }
 
-  RefPtr<nsHttpConnectionInfo> clone =
-      new nsHttpConnectionInfo(mOrigin, mOriginPort, EmptyCString(), mUsername,
-                               mProxyInfo, mOriginAttributes, mEndToEndSSL);
+  RefPtr<nsHttpConnectionInfo> clone = new nsHttpConnectionInfo(
+      mOrigin, mOriginPort, EmptyCString(), mUsername, mTopWindowOrigin,
+      mProxyInfo, mOriginAttributes, mEndToEndSSL, mIsolated);
   // Make sure the anonymous, insecure-scheme, and private flags are transferred
   clone->SetAnonymous(GetAnonymous());
   clone->SetPrivate(GetPrivate());
   clone->SetInsecureScheme(GetInsecureScheme());
   clone->SetNoSpdy(GetNoSpdy());
   clone->SetBeConservative(GetBeConservative());
   clone->SetTlsFlags(GetTlsFlags());
   clone->SetTrrUsed(GetTrrUsed());
@@ -289,19 +323,19 @@ nsresult nsHttpConnectionInfo::CreateWil
   // TS??*:0 (https:proxy.ducksong.com:3128)   [wildcard form]
 
   if (!mUsingHttpsProxy) {
     MOZ_ASSERT(false);
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   RefPtr<nsHttpConnectionInfo> clone;
-  clone =
-      new nsHttpConnectionInfo(NS_LITERAL_CSTRING("*"), 0, mNPNToken, mUsername,
-                               mProxyInfo, mOriginAttributes, true);
+  clone = new nsHttpConnectionInfo(NS_LITERAL_CSTRING("*"), 0, mNPNToken,
+                                   mUsername, mTopWindowOrigin, mProxyInfo,
+                                   mOriginAttributes, true);
   // Make sure the anonymous and private flags are transferred!
   clone->SetAnonymous(GetAnonymous());
   clone->SetPrivate(GetPrivate());
   clone.forget(outParam);
   return NS_OK;
 }
 
 void nsHttpConnectionInfo::SetTrrDisabled(bool aNoTrr) {
@@ -323,17 +357,17 @@ void nsHttpConnectionInfo::SetIPv6Disabl
     mIPv6Disabled = aNoIPv6;
     BuildHashKey();
   }
 }
 
 void nsHttpConnectionInfo::SetTlsFlags(uint32_t aTlsFlags) {
   mTlsFlags = aTlsFlags;
 
-  mHashKey.Replace(18, 8, nsPrintfCString("%08x", mTlsFlags));
+  mHashKey.Replace(19, 8, nsPrintfCString("%08x", mTlsFlags));
 }
 
 bool nsHttpConnectionInfo::UsingProxy() {
   if (!mProxyInfo) return false;
   return !mProxyInfo->IsDirect();
 }
 
 bool nsHttpConnectionInfo::HostIsLocalIPLiteral() const {
--- a/netwerk/protocol/http/nsHttpConnectionInfo.h
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.h
@@ -33,25 +33,27 @@ namespace mozilla {
 namespace net {
 
 extern LazyLogModule gHttpLog;
 
 class nsHttpConnectionInfo final : public ARefBase {
  public:
   nsHttpConnectionInfo(const nsACString &originHost, int32_t originPort,
                        const nsACString &npnToken, const nsACString &username,
+                       const nsACString &topWindowOrigin,
                        nsProxyInfo *proxyInfo,
                        const OriginAttributes &originAttributes,
                        bool endToEndSSL = false);
 
   // this version must use TLS and you may supply separate
   // connection (aka routing) information than the authenticated
   // origin information
   nsHttpConnectionInfo(const nsACString &originHost, int32_t originPort,
                        const nsACString &npnToken, const nsACString &username,
+                       const nsACString &topWindowOrigin,
                        nsProxyInfo *proxyInfo,
                        const OriginAttributes &originAttributes,
                        const nsACString &routedHost, int32_t routedPort);
 
  private:
   virtual ~nsHttpConnectionInfo() {
     MOZ_LOG(gHttpLog, LogLevel::Debug,
             ("Destroying nsHttpConnectionInfo @%p\n", this));
@@ -117,16 +119,22 @@ class nsHttpConnectionInfo final : publi
   void SetNoSpdy(bool aNoSpdy) { mHashKey.SetCharAt(aNoSpdy ? 'X' : '.', 5); }
   bool GetNoSpdy() const { return mHashKey.CharAt(5) == 'X'; }
 
   void SetBeConservative(bool aBeConservative) {
     mHashKey.SetCharAt(aBeConservative ? 'C' : '.', 6);
   }
   bool GetBeConservative() const { return mHashKey.CharAt(6) == 'C'; }
 
+  void SetIsolated(bool aIsolated) {
+    mIsolated = aIsolated;
+    BuildHashKey();
+  }
+  bool GetIsolated() const { return mIsolated; }
+
   void SetTlsFlags(uint32_t aTlsFlags);
   uint32_t GetTlsFlags() const { return mTlsFlags; }
 
   // TrrUsed means that this connection is used to send TRR requests over
   void SetTrrUsed(bool aUsed) { mTrrUsed = aUsed; }
   bool GetTrrUsed() const { return mTrrUsed; }
 
   // SetTrrDisabled means don't use TRR to resolve host names for this
@@ -137,16 +145,17 @@ class nsHttpConnectionInfo final : publi
   void SetIPv4Disabled(bool aNoIPv4);
   bool GetIPv4Disabled() const { return mIPv4Disabled; }
 
   void SetIPv6Disabled(bool aNoIPv6);
   bool GetIPv6Disabled() const { return mIPv6Disabled; }
 
   const nsCString &GetNPNToken() { return mNPNToken; }
   const nsCString &GetUsername() { return mUsername; }
+  const nsCString &GetTopWindowOrigin() { return mTopWindowOrigin; }
 
   const OriginAttributes &GetOriginAttributes() { return mOriginAttributes; }
 
   // Returns true for any kind of proxy (http, socks, https, etc..)
   bool UsingProxy();
 
   // Returns true when proxying over HTTP or HTTPS
   bool UsingHttpProxy() const { return mUsingHttpProxy || mUsingHttpsProxy; }
@@ -169,37 +178,55 @@ class nsHttpConnectionInfo final : publi
   bool HostIsLocalIPLiteral() const;
 
   bool GetLessThanTls13() const { return mLessThanTls13; }
   void SetLessThanTls13(bool aLessThanTls13) {
     mLessThanTls13 = aLessThanTls13;
   }
 
  private:
+  // These constructor versions are intended to only be used from Clone().
+  nsHttpConnectionInfo(const nsACString &originHost, int32_t originPort,
+                       const nsACString &npnToken, const nsACString &username,
+                       const nsACString &topWindowOrigin,
+                       nsProxyInfo *proxyInfo,
+                       const OriginAttributes &originAttributes,
+                       bool endToEndSSL, bool isolated);
+  nsHttpConnectionInfo(const nsACString &originHost, int32_t originPort,
+                       const nsACString &npnToken, const nsACString &username,
+                       const nsACString &topWindowOrigin,
+                       nsProxyInfo *proxyInfo,
+                       const OriginAttributes &originAttributes,
+                       const nsACString &routedHost, int32_t routedPort,
+                       bool isolated);
+
   void Init(const nsACString &host, int32_t port, const nsACString &npnToken,
-            const nsACString &username, nsProxyInfo *proxyInfo,
-            const OriginAttributes &originAttributes, bool EndToEndSSL);
+            const nsACString &username, const nsACString &topWindowOrigin,
+            nsProxyInfo *proxyInfo, const OriginAttributes &originAttributes,
+            bool EndToEndSSL);
   void SetOriginServer(const nsACString &host, int32_t port);
 
   nsCString mOrigin;
   int32_t mOriginPort;
   nsCString mRoutedHost;
   int32_t mRoutedPort;
 
   nsCString mHashKey;
   nsCString mUsername;
+  nsCString mTopWindowOrigin;
   nsCOMPtr<nsProxyInfo> mProxyInfo;
   bool mUsingHttpProxy;
   bool mUsingHttpsProxy;
   bool mEndToEndSSL;
   bool mUsingConnect;  // if will use CONNECT with http proxy
   nsCString mNPNToken;
   OriginAttributes mOriginAttributes;
 
   uint32_t mTlsFlags;
+  uint16_t mIsolated : 1;
   uint16_t mTrrUsed : 1;
   uint16_t mTrrDisabled : 1;
   uint16_t mIPv4Disabled : 1;
   uint16_t mIPv6Disabled : 1;
 
   bool mLessThanTls13;  // This will be set to true if we negotiate less than
                         // tls1.3. If the tls version is till not know or it
                         // is 1.3 or greater the value will be false.
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -4020,17 +4020,19 @@ nsresult nsHttpConnectionMgr::nsHalfOpen
 
   if (mCaps & NS_HTTP_DISABLE_TRR) {
     tmpFlags = nsISocketTransport::DISABLE_TRR;
   }
 
   if (mCaps & NS_HTTP_LOAD_ANONYMOUS)
     tmpFlags |= nsISocketTransport::ANONYMOUS_CONNECT;
 
-  if (ci->GetPrivate()) tmpFlags |= nsISocketTransport::NO_PERMANENT_STORAGE;
+  if (ci->GetPrivate() || ci->GetIsolated()) {
+    tmpFlags |= nsISocketTransport::NO_PERMANENT_STORAGE;
+  }
 
   if (ci->GetLessThanTls13()) {
     tmpFlags |= nsISocketTransport::DONT_TRY_ESNI;
   }
 
   if ((mCaps & NS_HTTP_BE_CONSERVATIVE) || ci->GetBeConservative()) {
     LOG(("Setting Socket to BE_CONSERVATIVE"));
     tmpFlags |= nsISocketTransport::BE_CONSERVATIVE;
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -2491,19 +2491,23 @@ nsresult nsHttpHandler::SpeculativeConne
 
   int32_t port = -1;
   rv = aURI->GetPort(&port);
   if (NS_FAILED(rv)) return rv;
 
   nsAutoCString username;
   aURI->GetUsername(username);
 
-  RefPtr<nsHttpConnectionInfo> ci =
-      new nsHttpConnectionInfo(host, port, EmptyCString(), username, nullptr,
-                               originAttributes, usingSSL);
+  // TODO For now pass EmptyCString() for topWindowOrigin for all speculative
+  // connection attempts, but ideally we should pass the accurate top window
+  // origin here.  This would require updating the nsISpeculativeConnect API
+  // and all of its consumers.
+  RefPtr<nsHttpConnectionInfo> ci = new nsHttpConnectionInfo(
+      host, port, EmptyCString(), username, EmptyCString(), nullptr,
+      originAttributes, usingSSL);
   ci->SetAnonymous(anonymous);
 
   return SpeculativeConnect(ci, aCallbacks);
 }
 
 NS_IMETHODIMP
 nsHttpHandler::SpeculativeConnect(nsIURI *aURI, nsIPrincipal *aPrincipal,
                                   nsIInterfaceRequestor *aCallbacks) {
--- a/netwerk/protocol/websocket/BaseWebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/BaseWebSocketChannel.cpp
@@ -195,24 +195,39 @@ BaseWebSocketChannel::SetPingTimeout(uin
 
   mPingResponseTimeout = aSeconds * 1000;
   mClientSetPingTimeout = 1;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+BaseWebSocketChannel::InitLoadInfoNative(nsINode *aLoadingNode,
+                                         nsIPrincipal *aLoadingPrincipal,
+                                         nsIPrincipal *aTriggeringPrincipal,
+                                         nsICookieSettings *aCookieSettings,
+                                         uint32_t aSecurityFlags,
+                                         uint32_t aContentPolicyType) {
+  mLoadInfo = new LoadInfo(aLoadingPrincipal, aTriggeringPrincipal,
+                           aLoadingNode, aSecurityFlags, aContentPolicyType);
+  if (aCookieSettings) {
+    mLoadInfo->SetCookieSettings(aCookieSettings);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 BaseWebSocketChannel::InitLoadInfo(nsINode *aLoadingNode,
                                    nsIPrincipal *aLoadingPrincipal,
                                    nsIPrincipal *aTriggeringPrincipal,
                                    uint32_t aSecurityFlags,
                                    uint32_t aContentPolicyType) {
-  mLoadInfo = new LoadInfo(aLoadingPrincipal, aTriggeringPrincipal,
-                           aLoadingNode, aSecurityFlags, aContentPolicyType);
-  return NS_OK;
+  return InitLoadInfoNative(aLoadingNode, aLoadingPrincipal,
+                            aTriggeringPrincipal, nullptr, aSecurityFlags,
+                            aContentPolicyType);
 }
 
 NS_IMETHODIMP
 BaseWebSocketChannel::GetSerial(uint32_t *aSerial) {
   if (!aSerial) {
     return NS_ERROR_FAILURE;
   }
 
--- a/netwerk/protocol/websocket/BaseWebSocketChannel.h
+++ b/netwerk/protocol/websocket/BaseWebSocketChannel.h
@@ -48,16 +48,22 @@ class BaseWebSocketChannel : public nsIW
   NS_IMETHOD GetLoadInfo(nsILoadInfo **aLoadInfo) override;
   NS_IMETHOD GetExtensions(nsACString &aExtensions) override;
   NS_IMETHOD GetProtocol(nsACString &aProtocol) override;
   NS_IMETHOD SetProtocol(const nsACString &aProtocol) override;
   NS_IMETHOD GetPingInterval(uint32_t *aSeconds) override;
   NS_IMETHOD SetPingInterval(uint32_t aSeconds) override;
   NS_IMETHOD GetPingTimeout(uint32_t *aSeconds) override;
   NS_IMETHOD SetPingTimeout(uint32_t aSeconds) override;
+  NS_IMETHOD InitLoadInfoNative(nsINode *aLoadingNode,
+                                nsIPrincipal *aLoadingPrincipal,
+                                nsIPrincipal *aTriggeringPrincipal,
+                                nsICookieSettings *aCookieSettings,
+                                uint32_t aSecurityFlags,
+                                uint32_t aContentPolicyType) override;
   NS_IMETHOD InitLoadInfo(nsINode *aLoadingNode,
                           nsIPrincipal *aLoadingPrincipal,
                           nsIPrincipal *aTriggeringPrincipal,
                           uint32_t aSecurityFlags,
                           uint32_t aContentPolicyType) override;
   NS_IMETHOD GetSerial(uint32_t *aSerial) override;
   NS_IMETHOD SetSerial(uint32_t aSerial) override;
   NS_IMETHOD SetServerParameters(
--- a/netwerk/protocol/websocket/nsIWebSocketChannel.idl
+++ b/netwerk/protocol/websocket/nsIWebSocketChannel.idl
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim: set sw=4 ts=4 et tw=80 : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+interface nsICookieSettings;
 interface nsIURI;
 interface nsIInterfaceRequestor;
 interface nsILoadGroup;
 interface nsIWebSocketListener;
 interface nsIInputStream;
 interface nsILoadInfo;
 interface nsIPrincipal;
 interface nsITransportProvider;
@@ -71,29 +72,41 @@ interface nsIWebSocketChannel : nsISuppo
      */
     [must_use] readonly attribute ACString extensions;
 
     /**
      * Init the WebSocketChannel with LoadInfo arguments.
      * @param aLoadingNode
      * @param aLoadingPrincipal
      * @param aTriggeringPrincipal
+     * @param aCookieSettings
      * @param aSecurityFlags
      * @param aContentPolicyType
      *        These will be used as values for the nsILoadInfo object on the
      *        created channel. For details, see nsILoadInfo in nsILoadInfo.idl
      * @return reference to the new nsIChannel object
      *
      * Keep in mind that URIs coming from a webpage should *never* use the
      * systemPrincipal as the loadingPrincipal.
      *
      * Please note, if you provide both a loadingNode and a loadingPrincipal,
      * then loadingPrincipal must be equal to loadingNode->NodePrincipal().
      * But less error prone is to just supply a loadingNode.
      */
+     [notxpcom] nsresult initLoadInfoNative(in Node aLoadingNode,
+                                            in nsIPrincipal aLoadingPrincipal,
+                                            in nsIPrincipal aTriggeringPrincipal,
+                                            in nsICookieSettings aCookieSettings,
+                                            in unsigned long aSecurityFlags,
+                                            in unsigned long aContentPolicyType);
+
+     /**
+      * Similar to the previous one but without nsICookieSettings.
+      * This method is used by JS code where nsICookieSettings is not exposed.
+      */
      [must_use] void initLoadInfo(in Node aLoadingNode,
                                   in nsIPrincipal aLoadingPrincipal,
                                   in nsIPrincipal aTriggeringPrincipal,
                                   in unsigned long aSecurityFlags,
                                   in unsigned long aContentPolicyType);
 
     /**
      * Asynchronously open the websocket connection.  Received messages are fed
--- a/python/mozbuild/mozbuild/action/tooltool.py
+++ b/python/mozbuild/mozbuild/action/tooltool.py
@@ -554,17 +554,22 @@ def unpack_file(filename):
         tar.extractall()
         tar.close()
     elif filename.endswith('.tar.xz'):
         base_file = filename.replace('.tar.xz', '')
         if _cache_checksum_matches(base_file, checksum):
             return True
         clean_path(base_file)
         log.info('untarring "%s"' % filename)
-        if not execute('tar -Jxf %s 2>&1' % filename):
+        # Not using tar -Jxf because it fails on Windows for some reason.
+        process = Popen(['xz', '-d', '-c', filename], stdout=PIPE)
+        tar = tarfile.open(fileobj=process.stdout, mode='r|')
+        tar.extractall()
+        tar.close()
+        if not process.wait():
             return False
     elif zipfile.is_zipfile(filename):
         base_file = filename.replace('.zip', '')
         if _cache_checksum_matches(base_file, checksum):
             return True
         clean_path(base_file)
         log.info('unzipping "%s"' % filename)
         z = zipfile.ZipFile(filename)
--- a/taskcluster/ci/test/test-sets.yml
+++ b/taskcluster/ci/test/test-sets.yml
@@ -265,17 +265,17 @@ windows-aarch64-tests:
     - mochitest-devtools-chrome
     - mochitest-gpu
     - mochitest-media
     - mochitest-webgl1-core
     - mochitest-webgl1-ext
     - mochitest-webgl2-core
     - mochitest-webgl2-ext
     - reftest
-    # - web-platform-tests - disabled due to wpt11 experiencing BSoD
+    - web-platform-tests
     - web-platform-tests-reftests
     - xpcshell
 
 windows-talos:
     - talos-bcv
     - talos-chrome
     - talos-damp
     - talos-dromaeojs
--- a/taskcluster/ci/toolchain/rust.yml
+++ b/taskcluster/ci/toolchain/rust.yml
@@ -143,44 +143,41 @@ win64-rust-1.28:
         symbol: TW64(rust-1.28)
     run:
         arguments: [
             '--channel', '1.28.0',
             '--host', 'x86_64-pc-windows-msvc',
             '--target', 'x86_64-pc-windows-msvc',
             '--target', 'i686-pc-windows-msvc',
         ]
-        toolchain-artifact: public/build/rustc.tar.bz2
 
 win64-rust-1.34:
     treeherder:
         symbol: TW64(rust)
     run:
         arguments: [
             '--channel', '1.34.0',
             '--host', 'x86_64-pc-windows-msvc',
             '--target', 'x86_64-pc-windows-msvc',
             '--target', 'i686-pc-windows-msvc',
             '--target', 'aarch64-pc-windows-msvc',
         ]
         toolchain-alias: win64-rust
-        toolchain-artifact: public/build/rustc.tar.bz2
 
 win64-rust-nightly:
     description: "rust nightly repack"
     treeherder:
         symbol: TW64(rust-nightly)
     run:
         arguments: [
             '--channel', 'nightly-2018-12-14',
             '--host', 'x86_64-pc-windows-msvc',
             '--target', 'x86_64-pc-windows-msvc',
             '--target', 'i686-pc-windows-msvc',
         ]
-        toolchain-artifact: public/build/rustc.tar.bz2
 
 mingw32-rust-1.31:
     treeherder:
         symbol: TMW(rust-1.31)
     run:
         arguments: [
             '--channel', '1.31.0',
             '--host', 'x86_64-unknown-linux-gnu',
--- a/taskcluster/scripts/misc/repack_rust.py
+++ b/taskcluster/scripts/misc/repack_rust.py
@@ -235,22 +235,18 @@ def fetch_optional(manifest, pkg, host):
     try:
         return fetch_package(manifest, pkg, host)
     except KeyError:
         # The package is not available, oh well!
         return None
 
 
 def tar_for_host(host):
-    if 'linux' in host:
-        tar_options = 'cJf'
-        tar_ext = '.tar.xz'
-    else:
-        tar_options = 'cjf'
-        tar_ext = '.tar.bz2'
+    tar_options = 'cJf'
+    tar_ext = '.tar.xz'
     return tar_options, tar_ext
 
 
 def fetch_manifest(channel='stable'):
     if '-' in channel:
         channel, date = channel.split('-', 1)
         prefix = '/' + date
     else:
--- a/taskcluster/scripts/run-task
+++ b/taskcluster/scripts/run-task
@@ -131,17 +131,16 @@ def run_and_prefix_output(prefix, args, 
     p = subprocess.Popen(args,
                          # Disable buffering because we want to receive output
                          # as it is generated so timestamps in logs are
                          # accurate.
                          bufsize=0,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.STDOUT,
                          stdin=sys.stdin.fileno(),
-                         cwd='/',
                          env=env)
 
     stdout = io.TextIOWrapper(p.stdout, encoding='latin1')
 
     while True:
         data = stdout.readline().encode('latin1')
 
         if data == b'':
@@ -491,16 +490,20 @@ def fetch_artifacts():
     print_line(b'fetches', b'fetching artifacts\n')
 
     fetch_content = shutil.which('fetch-content')
     if not fetch_content and os.environ.get('GECKO_PATH'):
         fetch_content = os.path.join(os.environ['GECKO_PATH'], 'taskcluster',
                                      'scripts', 'misc', 'fetch-content')
 
     if not fetch_content or not os.path.isfile(fetch_content):
+        fetch_content = os.path.join(os.path.dirname(__file__),
+                                     'fetch-content')
+
+    if not os.path.isfile(fetch_content):
         print(FETCH_CONTENT_NOT_FOUND)
         sys.exit(1)
 
     cmd = [sys.executable, '-u', fetch_content, 'task-artifacts']
     print_line(b'fetches', b'executing %r\n' % cmd)
     subprocess.run(cmd, check=True, env=os.environ)
     print_line(b'fetches', b'finished fetching artifacts\n')
 
@@ -535,18 +538,22 @@ def resolve_checkout_url(base_repo, head
                    HGMOINTERNAL_CONFIG_URL.encode('utf-8'))
 
         # Get the hgmointernal config Taskcluster secret
         res = urllib.request.urlopen(HGMOINTERNAL_CONFIG_URL, timeout=10)
         hgmointernal_config = json.loads(res.read().decode('utf-8'))['secret']
 
         # Use public hg service if region not yet supported
         if region not in hgmointernal_config:
-            print_line(b'vcs', b'region %s not yet supported; using public '
-                               b'hg.mozilla.org service\n' % region.encode('utf-8'))
+            if region:
+                print_line(b'vcs', b'region %s not yet supported; using public '
+                                   b'hg.mozilla.org service\n' % region.encode('utf-8'))
+            else:
+                print_line(b'vcs', b'unspecified region; using public '
+                                   b'hg.mozilla.org service\n')
             return base_repo, head_repo
 
         # Only send a percentage of traffic to the internal mirror
         rate = float(hgmointernal_config[region]['rate'])
 
         if random.random() > rate:
             print_line(b'vcs', b'hgmointernal rate miss; using '
                                b'public hg.mozilla.org service\n')
--- a/taskcluster/taskgraph/transforms/job/run_task.py
+++ b/taskcluster/taskgraph/transforms/job/run_task.py
@@ -76,19 +76,21 @@ worker_defaults = {
     'cache-dotcache': False,
     'checkout': True,
     'comm-checkout': False,
     'sparse-profile': None,
     'tooltool-downloads': False,
 }
 
 
-def run_task_url(config):
-    return '{}/raw-file/{}/taskcluster/scripts/run-task'.format(
-                config.params['head_repository'], config.params['head_rev'])
+def script_url(config, script):
+    return '{}/raw-file/{}/taskcluster/scripts/{}'.format(
+                config.params['head_repository'],
+                config.params['head_rev'],
+                script)
 
 
 @run_job_using("docker-worker", "run-task", schema=run_task_schema, defaults=worker_defaults)
 def docker_worker_run_task(config, job, taskdesc):
     run = job['run']
     worker = taskdesc['worker'] = job['worker']
     command = ['/builds/worker/bin/run-task']
     common_setup(config, job, taskdesc, command)
@@ -136,20 +138,27 @@ def generic_worker_run_task(config, job,
     worker.setdefault('mounts', [])
     if run.get('cache-dotcache'):
         worker['mounts'].append({
             'cache-name': '{project}-dotcache'.format(**config.params),
             'directory': '{workdir}/.cache'.format(**run),
         })
     worker['mounts'].append({
         'content': {
-            'url': run_task_url(config),
+            'url': script_url(config, 'run-task'),
         },
         'file': './run-task',
     })
+    if worker.get('env', {}).get('MOZ_FETCHES'):
+        worker['mounts'].append({
+            'content': {
+                'url': script_url(config, 'misc/fetch-content'),
+            },
+            'file': './fetch-content',
+        })
 
     run_command = run['command']
     if isinstance(run_command, basestring):
         if is_win:
             run_command = '"{}"'.format(run_command)
         run_command = ['bash', '-cx', run_command]
 
     command.append('--')
--- a/taskcluster/taskgraph/util/docker.py
+++ b/taskcluster/taskgraph/util/docker.py
@@ -98,17 +98,17 @@ def post_to_docker(tar, api_path, **kwar
                     # Only print status changes.
                     if status != data['status']:
                         sys.stderr.write('{}: {}\n'.format(data['id'], data['status']))
                         status_line[data['id']] = data['status']
             else:
                 status_line = {}
                 sys.stderr.write('{}\n'.format(data['status']))
         elif 'stream' in data:
-            sys.stderr.write(data['stream'].encode("utf-8"))
+            sys.stderr.write(data['stream'])
         elif 'aux' in data:
             sys.stderr.write(repr(data['aux']))
         elif 'error' in data:
             sys.stderr.write('{}\n'.format(data['error']))
             # Sadly, docker doesn't give more than a plain string for errors,
             # so the best we can do to propagate the error code from the command
             # that failed is to parse the error message...
             errcode = 1
--- a/testing/web-platform/meta/css/css-multicol/multicol-breaking-000.html.ini
+++ b/testing/web-platform/meta/css/css-multicol/multicol-breaking-000.html.ini
@@ -1,2 +1,2 @@
 [multicol-breaking-000.html]
-  expected: FAIL
+  prefs: [layout.css.column-span.enabled:true]
--- a/testing/web-platform/meta/css/css-multicol/multicol-breaking-001.html.ini
+++ b/testing/web-platform/meta/css/css-multicol/multicol-breaking-001.html.ini
@@ -1,2 +1,2 @@
 [multicol-breaking-001.html]
-  expected: FAIL
+  prefs: [layout.css.column-span.enabled:true]
--- a/testing/web-platform/meta/css/css-multicol/multicol-height-block-child-001.xht.ini
+++ b/testing/web-platform/meta/css/css-multicol/multicol-height-block-child-001.xht.ini
@@ -1,2 +1,2 @@
 [multicol-height-block-child-001.xht]
-  expected: FAIL
+  prefs: [layout.css.column-span.enabled:true]
--- a/testing/web-platform/meta/css/css-multicol/multicol-span-all-margin-bottom-001.xht.ini
+++ b/testing/web-platform/meta/css/css-multicol/multicol-span-all-margin-bottom-001.xht.ini
@@ -1,2 +1,2 @@
 [multicol-span-all-margin-bottom-001.xht]
-  expected: FAIL
+  prefs: [layout.css.column-span.enabled:true]
--- a/testing/web-platform/meta/css/css-multicol/parsing/column-span-valid.html.ini
+++ b/testing/web-platform/meta/css/css-multicol/parsing/column-span-valid.html.ini
@@ -1,7 +1,2 @@
 [column-span-valid.html]
-  [e.style['column-span'\] = "none" should set the property value]
-    expected: FAIL
-
-  [e.style['column-span'\] = "all" should set the property value]
-    expected: FAIL
-
+  prefs: [layout.css.column-span.enabled:true]
--- a/testing/web-platform/meta/infrastructure/server/__dir__.ini
+++ b/testing/web-platform/meta/infrastructure/server/__dir__.ini
@@ -1,2 +1,2 @@
-lsan-allowed: [Alloc, Create, CreateInner, MakeUnique, NewPage, PLDHashTable::ChangeTable, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::WeakPtr, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::CookieSettings::Create, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsStandardURL::TemplatedMutator, nsSupportsWeakReference::GetWeakReference]
+lsan-allowed: [Alloc, Create, CreateInner, MakeUnique, NewPage, PLDHashTable::ChangeTable, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::WeakPtr, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::BaseWebSocketChannel::InitLoadInfoNative, mozilla::net::CookieSettings::Create, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsStandardURL::TemplatedMutator, nsSupportsWeakReference::GetWeakReference]
 leak-threshold: [default:51200, tab:51200]
--- a/testing/web-platform/meta/media-source/__dir__.ini
+++ b/testing/web-platform/meta/media-source/__dir__.ini
@@ -1,2 +1,4 @@
 prefs: [media.mediasource.experimental.enabled:true]
 leak-threshold: [default: 51200]
+disabled:
+    if (os == "win") and (processor == "aarch64"): https://bugzilla.mozilla.org/show_bug.cgi?id=1545810
\ No newline at end of file
--- a/testing/web-platform/meta/quirks/unitless-length/excluded-properties-002.html.ini
+++ b/testing/web-platform/meta/quirks/unitless-length/excluded-properties-002.html.ini
@@ -1,4 +1,2 @@
 [excluded-properties-002.html]
-  [Property column-span does not support quirky length]
-    expected: FAIL
-
+  prefs: [layout.css.column-span.enabled:true]
--- a/testing/web-platform/meta/websockets/__dir__.ini
+++ b/testing/web-platform/meta/websockets/__dir__.ini
@@ -1,2 +1,2 @@
 leak-threshold: [default:102400, tab:51200]
-lsan-allowed: [Alloc, Create, MakeUnique, NewPage, PLDHashTable::Add, Realloc, SetPropertyAsInterface, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::WeakPtr, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::CookieSettings::Create, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSupportsWeakReference::GetWeakReference]
+lsan-allowed: [Alloc, Create, MakeUnique, NewPage, PLDHashTable::Add, Realloc, SetPropertyAsInterface, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::WeakPtr, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::BaseWebSocketChannel::InitLoadInfoNative, mozilla::net::CookieSettings::Create, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSupportsWeakReference::GetWeakReference]
--- a/testing/web-platform/meta/websockets/binary/__dir__.ini
+++ b/testing/web-platform/meta/websockets/binary/__dir__.ini
@@ -1,3 +1,3 @@
-lsan-allowed: [MakeUnique, mozilla::dom::WebSocket::ConstructorCommon, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, Alloc, Create, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create]
+lsan-allowed: [MakeUnique, mozilla::dom::WebSocket::ConstructorCommon, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::BaseWebSocketChannel::InitLoadInfoNative, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, Alloc, Create, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create]
 lsan-max-stack-depth: 7
 leak-threshold: [tab:51200]
--- a/testing/web-platform/meta/websockets/constructor/__dir__.ini
+++ b/testing/web-platform/meta/websockets/constructor/__dir__.ini
@@ -1,3 +1,3 @@
-lsan-allowed: [Alloc, Create, MakeUnique, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
+lsan-allowed: [Alloc, Create, MakeUnique, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::BaseWebSocketChannel::InitLoadInfoNative, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
 lsan-max-stack-depth: 7
 leak-threshold: [tab:51200]
--- a/toolkit/components/antitracking/test/browser/browser_tlsSessionTickets.js
+++ b/toolkit/components/antitracking/test/browser/browser_tlsSessionTickets.js
@@ -1,8 +1,22 @@
+function isIsolated(key) {
+  return key.charAt(7) == "i";
+}
+
+function hasTopWindowOrigin(key, origin) {
+  let tokenAtEnd = `{{${origin}}}`;
+  let endPart = key.slice(-tokenAtEnd.length);
+  return endPart == tokenAtEnd;
+}
+
+function hasAnyTopWindowOrigin(key) {
+  return !!key.match(/{{[^}]+}}/);
+}
+
 add_task(async function() {
   info("Starting tlsSessionTickets test");
 
   await SpecialPowers.flushPrefEnv();
   await SpecialPowers.pushPrefEnv({"set": [
     ["browser.cache.disk.enable", false],
     ["browser.cache.memory.enable", false],
     ["browser.contentblocking.allowlist.annotations.enabled", true],
@@ -77,16 +91,26 @@ add_task(async function() {
     // second and third connections are the same.  The reason why this check is
     // done is that the private bit on the connection info object is used to
     // construct the hash key, so when the connection is isolated because it
     // comes from a third-party tracker context, its hash key must be
     // different.
     is(hashKeys.length, 3, "We should have observed 3 loads for " + trackingURL);
     is(hashKeys[1], hashKeys[2], "The second and third hash keys should match");
     isnot(hashKeys[0], hashKeys[1], "The first and second hash keys should not match");
+
+    ok(isIsolated(hashKeys[0]), "The first connection must have been isolated");
+    ok(!isIsolated(hashKeys[1]), "The second connection must not have been isolated");
+    ok(!isIsolated(hashKeys[2]), "The third connection must not have been isolated");
+    ok(hasTopWindowOrigin(hashKeys[0], TEST_DOMAIN.replace(/\/$/, "")),
+       "The first connection must be bound to its top-level window");
+    ok(!hasAnyTopWindowOrigin(hashKeys[1]),
+       "The second connection must not be bound to a top-level window");
+    ok(!hasAnyTopWindowOrigin(hashKeys[2]),
+       "The third connection must not be bound to a top-level window");
   });
 
   info("Removing the tab");
   BrowserTestUtils.removeTab(tab);
 });
 
 add_task(async function() {
   info("Cleaning up.");