Bug 700538 part 3 - Add and use new EditorRoot methods in nsEditor; r=ehsan
authorAryeh Gregor <ayg@aryeh.name>
Sun, 06 May 2012 10:53:11 +0300
changeset 95747 222fc2b8378ff05ed5003ce0647628ca40365643
parent 95746 edebd9b79fe51d15d0ad947a3b634a348322b847
child 95748 8396c8f870d353e0a2d554a38ff2e7f7f8b273ec
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs700538
milestone15.0a1
Bug 700538 part 3 - Add and use new EditorRoot methods in nsEditor; r=ehsan
editor/libeditor/base/nsEditor.cpp
editor/libeditor/base/nsEditor.h
editor/libeditor/html/nsHTMLEditor.cpp
editor/libeditor/html/nsHTMLEditor.h
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -3143,95 +3143,89 @@ nsEditor::GetLengthOfDOMNode(nsIDOMNode 
 }
 
 
 nsresult 
 nsEditor::GetPriorNode(nsIDOMNode  *aParentNode, 
                        PRInt32      aOffset, 
                        bool         aEditableNode, 
                        nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing,
-                       nsIContent  *aActiveEditorRoot)
+                       bool         bNoBlockCrossing)
 {
   NS_ENSURE_TRUE(aResultNode, NS_ERROR_NULL_POINTER);
   *aResultNode = nsnull;
 
   nsCOMPtr<nsINode> parentNode = do_QueryInterface(aParentNode);
   NS_ENSURE_TRUE(parentNode, NS_ERROR_NULL_POINTER);
 
   *aResultNode = do_QueryInterface(GetPriorNode(parentNode, aOffset,
-                                                aEditableNode, bNoBlockCrossing,
-                                                aActiveEditorRoot));
+                                                aEditableNode,
+                                                bNoBlockCrossing));
   return NS_OK;
 }
 
 nsIContent*
 nsEditor::GetPriorNode(nsINode* aParentNode,
                        PRInt32 aOffset,
                        bool aEditableNode,
-                       bool aNoBlockCrossing,
-                       nsIContent* aActiveEditorRoot)
+                       bool aNoBlockCrossing)
 {
   MOZ_ASSERT(aParentNode);
 
   // If we are at the beginning of the node, or it is a text node, then just
   // look before it.
   if (!aOffset || aParentNode->NodeType() == nsIDOMNode::TEXT_NODE) {
     if (aNoBlockCrossing && IsBlockNode(aParentNode)) {
       // If we aren't allowed to cross blocks, don't look before this block.
       return nsnull;
     }
-    return GetPriorNode(aParentNode, aEditableNode,
-                        aNoBlockCrossing, aActiveEditorRoot);
+    return GetPriorNode(aParentNode, aEditableNode, aNoBlockCrossing);
   }
 
   // else look before the child at 'aOffset'
   if (nsIContent* child = aParentNode->GetChildAt(aOffset)) {
-    return GetPriorNode(child, aEditableNode, aNoBlockCrossing,
-                        aActiveEditorRoot);
+    return GetPriorNode(child, aEditableNode, aNoBlockCrossing);
   }
 
   // unless there isn't one, in which case we are at the end of the node
   // and want the deep-right child.
   nsIContent* resultNode = GetRightmostChild(aParentNode, aNoBlockCrossing);
   if (!resultNode || !aEditableNode || IsEditable(resultNode)) {
     return resultNode;
   }
 
   // restart the search from the non-editable node we just found
-  return GetPriorNode(resultNode, aEditableNode, aNoBlockCrossing, aActiveEditorRoot);
+  return GetPriorNode(resultNode, aEditableNode, aNoBlockCrossing);
 }
 
 
 nsresult 
 nsEditor::GetNextNode(nsIDOMNode   *aParentNode, 
                       PRInt32      aOffset, 
                       bool         aEditableNode, 
                       nsCOMPtr<nsIDOMNode> *aResultNode,
-                      bool         bNoBlockCrossing,
-                      nsIContent  *aActiveEditorRoot)
+                      bool         bNoBlockCrossing)
 {
   NS_ENSURE_TRUE(aResultNode, NS_ERROR_NULL_POINTER);
   *aResultNode = nsnull;
 
   nsCOMPtr<nsINode> parentNode = do_QueryInterface(aParentNode);
   NS_ENSURE_TRUE(parentNode, NS_ERROR_NULL_POINTER);
 
   *aResultNode = do_QueryInterface(GetNextNode(parentNode, aOffset,
-                                               aEditableNode, bNoBlockCrossing,
-                                               aActiveEditorRoot));
+                                               aEditableNode,
+                                               bNoBlockCrossing));
   return NS_OK;
 }
 
 nsIContent*
 nsEditor::GetNextNode(nsINode* aParentNode,
                       PRInt32 aOffset,
                       bool aEditableNode,
-                      bool aNoBlockCrossing,
-                      nsIContent* aActiveEditorRoot)
+                      bool aNoBlockCrossing)
 {
   MOZ_ASSERT(aParentNode);
 
   // if aParentNode is a text node, use its location instead
   if (aParentNode->NodeType() == nsIDOMNode::TEXT_NODE) {
     nsINode* parent = aParentNode->GetNodeParent();
     NS_ENSURE_TRUE(parent, nsnull);
     aOffset = parent->IndexOf(aParentNode) + 1; // _after_ the text node
@@ -3245,89 +3239,76 @@ nsEditor::GetNextNode(nsINode* aParentNo
       return child;
     }
 
     nsIContent* resultNode = GetLeftmostChild(child, aNoBlockCrossing);
     if (!resultNode) {
       return child;
     }
 
-    if (!IsDescendantOfRoot(resultNode)) {
+    if (!IsDescendantOfEditorRoot(resultNode)) {
       return nsnull;
     }
 
     if (!aEditableNode || IsEditable(resultNode)) {
       return resultNode;
     }
 
     // restart the search from the non-editable node we just found
-    return GetNextNode(resultNode, aEditableNode, aNoBlockCrossing,
-                       aActiveEditorRoot);
+    return GetNextNode(resultNode, aEditableNode, aNoBlockCrossing);
   }
     
   // unless there isn't one, in which case we are at the end of the node
   // and want the next one.
   if (aNoBlockCrossing && IsBlockNode(aParentNode)) {
     // don't cross out of parent block
     return NS_OK;
   }
 
-  return GetNextNode(aParentNode, aEditableNode, aNoBlockCrossing,
-                     aActiveEditorRoot);
+  return GetNextNode(aParentNode, aEditableNode, aNoBlockCrossing);
 }
 
 
 nsresult 
 nsEditor::GetPriorNode(nsIDOMNode  *aCurrentNode, 
                        bool         aEditableNode, 
                        nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing,
-                       nsIContent  *aActiveEditorRoot)
+                       bool         bNoBlockCrossing)
 {
   NS_ENSURE_TRUE(aResultNode, NS_ERROR_NULL_POINTER);
 
   nsCOMPtr<nsINode> currentNode = do_QueryInterface(aCurrentNode);
   NS_ENSURE_TRUE(currentNode, NS_ERROR_NULL_POINTER);
 
   *aResultNode = do_QueryInterface(GetPriorNode(currentNode, aEditableNode,
-                                                bNoBlockCrossing,
-                                                aActiveEditorRoot));
+                                                bNoBlockCrossing));
   return NS_OK;
 }
 
 nsIContent*
 nsEditor::GetPriorNode(nsINode* aCurrentNode, bool aEditableNode,
-                       bool aNoBlockCrossing /* = false */,
-                       nsIContent* aActiveEditorRoot /* = null */)
+                       bool aNoBlockCrossing /* = false */)
 {
   MOZ_ASSERT(aCurrentNode);
 
-  if (!IsDescendantOfRoot(aCurrentNode) ||
-      (aActiveEditorRoot &&
-       !nsContentUtils::ContentIsDescendantOf(aCurrentNode,
-                                              aActiveEditorRoot))) {
+  if (!IsDescendantOfEditorRoot(aCurrentNode)) {
     return nsnull;
   }
 
-  return FindNode(aCurrentNode, false, aEditableNode, aNoBlockCrossing,
-                  aActiveEditorRoot);
+  return FindNode(aCurrentNode, false, aEditableNode, aNoBlockCrossing);
 }
 
 nsIContent*
 nsEditor::FindNextLeafNode(nsINode  *aCurrentNode, 
                            bool      aGoForward,
-                           bool      bNoBlockCrossing,
-                           nsIContent *aActiveEditorRoot)
+                           bool      bNoBlockCrossing)
 {
   // called only by GetPriorNode so we don't need to check params.
-  NS_PRECONDITION(IsDescendantOfRoot(aCurrentNode) &&
-                  !IsRoot(aCurrentNode) &&
-                  (!aActiveEditorRoot ||
-                   nsContentUtils::ContentIsDescendantOf(aCurrentNode,
-                                                         aActiveEditorRoot)),
+  NS_PRECONDITION(IsDescendantOfEditorRoot(aCurrentNode) &&
+                  !IsEditorRoot(aCurrentNode),
                   "Bogus arguments");
 
   nsINode* cur = aCurrentNode;
   for (;;) {
     // if aCurrentNode has a sibling in the right direction, return
     // that sibling's closest child (or itself if it has no children)
     nsIContent* sibling =
       aGoForward ? cur->GetNextSibling() : cur->GetPreviousSibling();
@@ -3346,99 +3327,88 @@ nsEditor::FindNextLeafNode(nsINode  *aCu
       return leaf;
     }
 
     nsINode *parent = cur->GetNodeParent();
     if (!parent) {
       return nsnull;
     }
 
-    NS_ASSERTION(IsDescendantOfRoot(parent),
+    NS_ASSERTION(IsDescendantOfEditorRoot(parent),
                  "We started with a proper descendant of root, and should stop "
                  "if we ever hit the root, so we better have a descendant of "
                  "root now!");
-    if (IsRoot(parent) ||
-        (bNoBlockCrossing && IsBlockNode(parent)) ||
-        parent == aActiveEditorRoot) {
+    if (IsEditorRoot(parent) ||
+        (bNoBlockCrossing && IsBlockNode(parent))) {
       return nsnull;
     }
 
     cur = parent;
   }
 
   NS_NOTREACHED("What part of for(;;) do you not understand?");
   return nsnull;
 }
 
 nsresult
 nsEditor::GetNextNode(nsIDOMNode* aCurrentNode,
                       bool aEditableNode,
                       nsCOMPtr<nsIDOMNode> *aResultNode,
-                      bool bNoBlockCrossing,
-                      nsIContent* aActiveEditorRoot)
+                      bool bNoBlockCrossing)
 {
   nsCOMPtr<nsINode> currentNode = do_QueryInterface(aCurrentNode);
   if (!currentNode || !aResultNode) {
     return NS_ERROR_NULL_POINTER;
   }
 
   *aResultNode = do_QueryInterface(GetNextNode(currentNode, aEditableNode,
-                                               bNoBlockCrossing,
-                                               aActiveEditorRoot));
+                                               bNoBlockCrossing));
   return NS_OK;
 }
 
 nsIContent*
 nsEditor::GetNextNode(nsINode* aCurrentNode,
                       bool aEditableNode,
-                      bool bNoBlockCrossing,
-                      nsIContent* aActiveEditorRoot)
+                      bool bNoBlockCrossing)
 {
   MOZ_ASSERT(aCurrentNode);
 
-  if (!IsDescendantOfRoot(aCurrentNode) ||
-      (aActiveEditorRoot &&
-       !nsContentUtils::ContentIsDescendantOf(aCurrentNode,
-                                              aActiveEditorRoot))) {
+  if (!IsDescendantOfEditorRoot(aCurrentNode)) {
     return nsnull;
   }
 
-  return FindNode(aCurrentNode, true, aEditableNode, bNoBlockCrossing,
-                  aActiveEditorRoot);
+  return FindNode(aCurrentNode, true, aEditableNode, bNoBlockCrossing);
 }
 
 nsIContent*
 nsEditor::FindNode(nsINode *aCurrentNode,
                    bool     aGoForward,
                    bool     aEditableNode,
-                   bool     bNoBlockCrossing,
-                   nsIContent *aActiveEditorRoot)
-{
-  if (IsRoot(aCurrentNode) || aCurrentNode == aActiveEditorRoot) {
+                   bool     bNoBlockCrossing)
+{
+  if (IsEditorRoot(aCurrentNode)) {
     // Don't allow traversal above the root node! This helps
     // prevent us from accidentally editing browser content
     // when the editor is in a text widget.
 
     return nsnull;
   }
 
   nsIContent* candidate =
-    FindNextLeafNode(aCurrentNode, aGoForward, bNoBlockCrossing,
-                     aActiveEditorRoot);
+    FindNextLeafNode(aCurrentNode, aGoForward, bNoBlockCrossing);
   
   if (!candidate) {
     return nsnull;
   }
 
   if (!aEditableNode || IsEditable(candidate)) {
     return candidate;
   }
 
-  return FindNode(candidate, aGoForward, aEditableNode, bNoBlockCrossing,
-                  aActiveEditorRoot);
+  return FindNode(candidate, aGoForward, aEditableNode, bNoBlockCrossing);
 }
 
 already_AddRefed<nsIDOMNode>
 nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode, 
                             bool bNoBlockCrossing)
 {
   NS_ENSURE_TRUE(aCurrentNode, nsnull);
   nsCOMPtr<nsIDOMNode> resultNode, temp = aCurrentNode;
@@ -3603,16 +3573,24 @@ nsEditor::IsRoot(nsINode* inNode)
 {
   NS_ENSURE_TRUE(inNode, false);
 
   nsCOMPtr<nsINode> rootNode = GetRoot();
 
   return inNode == rootNode;
 }
 
+bool
+nsEditor::IsEditorRoot(nsINode* aNode)
+{
+  NS_ENSURE_TRUE(aNode, false);
+  nsCOMPtr<nsINode> rootNode = GetEditorRoot();
+  return aNode == rootNode;
+}
+
 bool 
 nsEditor::IsDescendantOfRoot(nsIDOMNode* inNode)
 {
   nsCOMPtr<nsINode> node = do_QueryInterface(inNode);
   return IsDescendantOfRoot(node);
 }
 
 bool
@@ -3620,16 +3598,26 @@ nsEditor::IsDescendantOfRoot(nsINode* in
 {
   NS_ENSURE_TRUE(inNode, false);
   nsCOMPtr<nsIContent> root = GetRoot();
   NS_ENSURE_TRUE(root, false);
 
   return nsContentUtils::ContentIsDescendantOf(inNode, root);
 }
 
+bool
+nsEditor::IsDescendantOfEditorRoot(nsINode* aNode)
+{
+  NS_ENSURE_TRUE(aNode, false);
+  nsCOMPtr<nsIContent> root = GetEditorRoot();
+  NS_ENSURE_TRUE(root, false);
+
+  return nsContentUtils::ContentIsDescendantOf(aNode, root);
+}
+
 bool 
 nsEditor::IsContainer(nsIDOMNode *aNode)
 {
   return aNode ? true : false;
 }
 
 bool
 nsEditor::IsTextInDirtyFrameVisible(nsIContent *aNode)
@@ -5228,16 +5216,22 @@ nsEditor::GetRoot()
 
     // Let GetRootElement() do the work
     GetRootElement(getter_AddRefs(root));
   }
 
   return mRootElement;
 }
 
+dom::Element*
+nsEditor::GetEditorRoot()
+{
+  return GetRoot();
+}
+
 nsresult
 nsEditor::DetermineCurrentDirection()
 {
   // Get the current root direction from its frame
   dom::Element *rootElement = GetRoot();
 
   // If we don't have an explicit direction, determine our direction
   // from the content's direction
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -368,18 +368,17 @@ protected:
 
   // stub.  see comment in source.                     
   virtual bool IsBlockNode(nsIDOMNode *aNode);
   virtual bool IsBlockNode(nsINode *aNode);
   
   // helper for GetPriorNode and GetNextNode
   nsIContent* FindNextLeafNode(nsINode  *aCurrentNode,
                                bool      aGoForward,
-                               bool      bNoBlockCrossing,
-                               nsIContent *aActiveEditorRoot);
+                               bool      bNoBlockCrossing);
 
   // Get nsIWidget interface
   nsresult GetWidget(nsIWidget **aWidget);
 
 
   // install the event listeners for the editor 
   virtual nsresult InstallEventListeners();
 
@@ -472,77 +471,67 @@ public:
 
   /** get the node immediately prior to aCurrentNode
     * @param aCurrentNode   the node from which we start the search
     * @param aEditableNode  if true, only return an editable node
     * @param aResultNode    [OUT] the node that occurs before aCurrentNode in the tree,
     *                       skipping non-editable nodes if aEditableNode is true.
     *                       If there is no prior node, aResultNode will be nsnull.
     * @param bNoBlockCrossing If true, don't move across "block" nodes, whatever that means.
-    * @param aActiveEditorRoot If non-null, only return descendants of aActiveEditorRoot.
     */
   nsresult GetPriorNode(nsIDOMNode  *aCurrentNode, 
                         bool         aEditableNode,
                         nsCOMPtr<nsIDOMNode> *aResultNode,
-                        bool         bNoBlockCrossing = false,
-                        nsIContent  *aActiveEditorRoot = nsnull);
+                        bool         bNoBlockCrossing = false);
   nsIContent* GetPriorNode(nsINode* aCurrentNode, bool aEditableNode,
-                           bool aNoBlockCrossing = false,
-                           nsIContent* aActiveEditorRoot = nsnull);
+                           bool aNoBlockCrossing = false);
 
   // and another version that takes a {parent,offset} pair rather than a node
   nsresult GetPriorNode(nsIDOMNode  *aParentNode, 
                         PRInt32      aOffset, 
                         bool         aEditableNode, 
                         nsCOMPtr<nsIDOMNode> *aResultNode,
-                        bool         bNoBlockCrossing = false,
-                        nsIContent  *aActiveEditorRoot = nsnull);
+                        bool         bNoBlockCrossing = false);
   nsIContent* GetPriorNode(nsINode* aParentNode,
                            PRInt32 aOffset,
                            bool aEditableNode,
-                           bool aNoBlockCrossing = false,
-                           nsIContent* aActiveEditorRoot = nsnull);
+                           bool aNoBlockCrossing = false);
 
 
   /** get the node immediately after to aCurrentNode
     * @param aCurrentNode   the node from which we start the search
     * @param aEditableNode  if true, only return an editable node
     * @param aResultNode    [OUT] the node that occurs after aCurrentNode in the tree,
     *                       skipping non-editable nodes if aEditableNode is true.
     *                       If there is no prior node, aResultNode will be nsnull.
     */
   nsresult GetNextNode(nsIDOMNode  *aCurrentNode, 
                        bool         aEditableNode,
                        nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing = false,
-                       nsIContent  *aActiveEditorRoot = nsnull);
+                       bool         bNoBlockCrossing = false);
   nsIContent* GetNextNode(nsINode* aCurrentNode,
                           bool aEditableNode,
-                          bool bNoBlockCrossing = false,
-                          nsIContent* aActiveEditorRoot = nsnull);
+                          bool bNoBlockCrossing = false);
 
   // and another version that takes a {parent,offset} pair rather than a node
   nsresult GetNextNode(nsIDOMNode  *aParentNode, 
                        PRInt32      aOffset, 
                        bool         aEditableNode, 
                        nsCOMPtr<nsIDOMNode> *aResultNode,
-                       bool         bNoBlockCrossing = false,
-                       nsIContent  *aActiveEditorRoot = nsnull);
+                       bool         bNoBlockCrossing = false);
   nsIContent* GetNextNode(nsINode* aParentNode,
                           PRInt32 aOffset,
                           bool aEditableNode,
-                          bool aNoBlockCrossing = false,
-                          nsIContent* aActiveEditorRoot = nsnull);
+                          bool aNoBlockCrossing = false);
 
   // Helper for GetNextNode and GetPriorNode
   nsIContent* FindNode(nsINode *aCurrentNode,
                        bool     aGoForward,
                        bool     aEditableNode,
-                       bool     bNoBlockCrossing,
-                       nsIContent *aActiveEditorRoot);
+                       bool     bNoBlockCrossing);
   /**
    * Get the rightmost child of aCurrentNode;
    * return nsnull if aCurrentNode has no children.
    */
   already_AddRefed<nsIDOMNode> GetRightmostChild(nsIDOMNode *aCurrentNode, 
                                                  bool        bNoBlockCrossing = false);
   nsIContent* GetRightmostChild(nsINode *aCurrentNode,
                                 bool     bNoBlockCrossing = false);
@@ -574,20 +563,22 @@ public:
   bool CanContain(nsIDOMNode* aParent, nsIDOMNode* aChild);
   bool CanContainTag(nsIDOMNode* aParent, nsIAtom* aTag);
   bool TagCanContain(nsIAtom* aParentTag, nsIDOMNode* aChild);
   virtual bool TagCanContainTag(nsIAtom* aParentTag, nsIAtom* aChildTag);
 
   /** returns true if aNode is our root node */
   bool IsRoot(nsIDOMNode* inNode);
   bool IsRoot(nsINode* inNode);
+  bool IsEditorRoot(nsINode* aNode);
 
   /** returns true if aNode is a descendant of our root node */
   bool IsDescendantOfRoot(nsIDOMNode* inNode);
   bool IsDescendantOfRoot(nsINode* inNode);
+  bool IsDescendantOfEditorRoot(nsINode* aNode);
 
   /** returns true if aNode is a container */
   virtual bool IsContainer(nsIDOMNode *aNode);
 
   /** returns true if aNode is an editable node */
   bool IsEditable(nsIDOMNode *aNode);
   bool IsEditable(nsIContent *aNode);
 
@@ -667,16 +658,20 @@ public:
                                     nsIDOMNode *aEndNode,
                                     PRInt32 aEndOffset);
 
   virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget() = 0;
 
   // Fast non-refcounting editor root element accessor
   mozilla::dom::Element *GetRoot();
 
+  // Likewise, but gets the editor's root instead, which is different for HTML
+  // editors
+  virtual mozilla::dom::Element* GetEditorRoot();
+
   // Accessor methods to flags
   bool IsPlaintextEditor() const
   {
     return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
   }
 
   bool IsSingleLineEditor() const
   {
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -4348,17 +4348,18 @@ nsHTMLEditor::GetPriorHTMLNode(nsIDOMNod
   NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
 
   nsIContent* activeEditingHost = GetActiveEditingHost();
   if (!activeEditingHost) {
     *outNode = nsnull;
     return NS_OK;
   }
 
-  nsresult res = GetPriorNode(inNode, true, address_of(*outNode), bNoBlockCrossing, activeEditingHost);
+  nsresult res = GetPriorNode(inNode, true, address_of(*outNode),
+                              bNoBlockCrossing);
   NS_ENSURE_SUCCESS(res, res);
   
   NS_ASSERTION(!*outNode || IsNodeInActiveEditor(*outNode),
                "GetPriorNode screwed up");
   return res;
 }
 
 
@@ -4371,17 +4372,18 @@ nsHTMLEditor::GetPriorHTMLNode(nsIDOMNod
   NS_ENSURE_TRUE(outNode, NS_ERROR_NULL_POINTER);
 
   nsIContent* activeEditingHost = GetActiveEditingHost();
   if (!activeEditingHost) {
     *outNode = nsnull;
     return NS_OK;
   }
 
-  nsresult res = GetPriorNode(inParent, inOffset, true, address_of(*outNode), bNoBlockCrossing, activeEditingHost);
+  nsresult res = GetPriorNode(inParent, inOffset, true, address_of(*outNode),
+                              bNoBlockCrossing);
   NS_ENSURE_SUCCESS(res, res);
   
   NS_ASSERTION(!*outNode || IsNodeInActiveEditor(*outNode),
                "GetPriorNode screwed up");
   return res;
 }
 
 
@@ -5710,8 +5712,15 @@ nsHTMLEditor::GetPreferredIMEState(IMESt
 }
 
 already_AddRefed<nsIContent>
 nsHTMLEditor::GetInputEventTargetContent()
 {
   nsCOMPtr<nsIContent> target = GetActiveEditingHost();
   return target.forget();
 }
+
+// virtual MOZ_OVERRIDE
+dom::Element*
+nsHTMLEditor::GetEditorRoot()
+{
+  return GetActiveEditingHost();
+}
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -131,16 +131,17 @@ public:
 
   /* ------------ nsPlaintextEditor overrides -------------- */
   NS_IMETHOD GetIsDocumentEditable(bool *aIsDocumentEditable);
   NS_IMETHOD BeginningOfDocument();
   virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
   virtual already_AddRefed<nsIContent> GetFocusedContent();
   virtual bool IsActiveInDOMWindow();
   virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget();
+  virtual mozilla::dom::Element* GetEditorRoot() MOZ_OVERRIDE;
   virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode *aNode);
   virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
   virtual already_AddRefed<nsIContent> GetInputEventTargetContent();
 
   /* ------------ nsStubMutationObserver overrides --------- */
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED