Node::hasEditableStyle and isEditablePosition have too many options
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 28 Feb 2015 02:41:12 +0000 (02:41 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 28 Feb 2015 02:41:12 +0000 (02:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=142078

Reviewed by Andreas Kling.

Moved the code that dealt with accessibility to htmlediting.cpp from Node. This patch introduces
new editing helper functions hasEditableStyle and isEditableNode for this purpose.

Also removed UserSelectAllTreatment from isContentEditable's arguments in the favor of using
newly extracted computeEditability in call sites that specify this option since isContentEditable
is a public DOM API.

No new tests since there should be no observable behavior changes.

* accessibility/AXObjectCache.h: Removed the declaration of an undefined function.

* dom/Element.cpp:
(WebCore::Element::shouldUseInputMethod): Uses newly added computeEditability.

* dom/Node.cpp:
(WebCore::Node::isContentEditable): Ditto. No longer takes UserSelectAllTreatment as an argument.
(WebCore::Node::isContentRichlyEditable): Ditto.
(WebCore::Node::computeEditability): Renamed from hasEditableStyle to avoid the confusion with
a helper function of the same name. Added ShouldUpdateStyle as an argument to optionally update
style tree. Also returns tri-state Editability enum instead of returning a boolean based on
the value of EditableLevel argument.
(WebCore::Node::isEditableToAccessibility): Moved to htmlediting.cpp.
(WebCore::Node::willRespondToMouseClickEvents): Uses newly added computeEditability.
(WebCore::Node::rootEditableElement): Moved to htmlediting.cpp.

* dom/Node.h: No longer includes EditingBoundary.h.
(WebCore::Node::isContentEditable):
(WebCore::Node::hasEditableStyle): No longer takes EditableType as an argument.
(WebCore::Node::hasRichlyEditableStyle): Ditto.

* editing/ApplyStyleCommand.cpp:
(WebCore::ApplyStyleCommand::removeInlineStyleFromElement): Uses newly added isEditableNode.
(WebCore::ApplyStyleCommand::surroundNodeRangeWithElement): Ditto.
* editing/DeleteFromTextNodeCommand.cpp:
(WebCore::DeleteFromTextNodeCommand::doApply): Ditto.
* editing/FrameSelection.cpp:
(WebCore::CaretBase::invalidateCaretRect): Ditto.
* editing/InsertNodeBeforeCommand.cpp:
(WebCore::InsertNodeBeforeCommand::doApply): Ditto.
(WebCore::InsertNodeBeforeCommand::doUnapply): Ditto.
* editing/RemoveNodeCommand.cpp:
(WebCore::RemoveNodeCommand::doApply): Ditto.

* editing/VisibleSelection.cpp:
(WebCore::VisibleSelection::hasEditableStyle): Since this is the only caller of isEditablePosition
which sets DoNotUpdateStyle, directly call hasEditableStyle on the container node instead. This was
not possible prior to r180726 because isEditablePosition had to move out of tables.

* editing/VisibleUnits.cpp:
(WebCore::previousLeafWithSameEditability): Uses newly added hasEditableStyle.
(WebCore::nextLeafWithSameEditability): Ditto.
(WebCore::rootEditableOrDocumentElement): Extracted from previousLinePosition. Use helper functions
in htmlediting.cpp instead of member functions of Node since they no longer support EditableType.
(WebCore::previousLinePosition):
(WebCore::nextLinePosition):

* editing/htmlediting.cpp:
(WebCore::highestEditableRoot): Uses newly added hasEditableStyle.
(WebCore::isEditableToAccessibility): Moved from Node.
(WebCore::computeEditability): Extracted from isEditablePosition.
(WebCore::hasEditableStyle): Added.
(WebCore::isEditableNode): Added.
(WebCore::isEditablePosition): Now calls computeEditability.
(WebCore::isRichlyEditablePosition): No longer takes EditableType since that variant was never used.
(WebCore::editableRootForPosition): Moved the code from Node::rootEditableElement.

* editing/htmlediting.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@180809 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AXObjectCache.h
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/editing/ApplyStyleCommand.cpp
Source/WebCore/editing/DeleteFromTextNodeCommand.cpp
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/editing/InsertNodeBeforeCommand.cpp
Source/WebCore/editing/RemoveNodeCommand.cpp
Source/WebCore/editing/VisibleSelection.cpp
Source/WebCore/editing/VisibleUnits.cpp
Source/WebCore/editing/htmlediting.cpp
Source/WebCore/editing/htmlediting.h

index d588051..2bbf063 100644 (file)
@@ -1,3 +1,78 @@
+2015-02-27  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Node::hasEditableStyle and isEditablePosition have too many options
+        https://bugs.webkit.org/show_bug.cgi?id=142078
+
+        Reviewed by Andreas Kling.
+
+        Moved the code that dealt with accessibility to htmlediting.cpp from Node. This patch introduces
+        new editing helper functions hasEditableStyle and isEditableNode for this purpose.
+
+        Also removed UserSelectAllTreatment from isContentEditable's arguments in the favor of using
+        newly extracted computeEditability in call sites that specify this option since isContentEditable
+        is a public DOM API.
+
+        No new tests since there should be no observable behavior changes.
+
+        * accessibility/AXObjectCache.h: Removed the declaration of an undefined function.
+
+        * dom/Element.cpp:
+        (WebCore::Element::shouldUseInputMethod): Uses newly added computeEditability.
+
+        * dom/Node.cpp:
+        (WebCore::Node::isContentEditable): Ditto. No longer takes UserSelectAllTreatment as an argument.
+        (WebCore::Node::isContentRichlyEditable): Ditto.
+        (WebCore::Node::computeEditability): Renamed from hasEditableStyle to avoid the confusion with
+        a helper function of the same name. Added ShouldUpdateStyle as an argument to optionally update
+        style tree. Also returns tri-state Editability enum instead of returning a boolean based on
+        the value of EditableLevel argument.
+        (WebCore::Node::isEditableToAccessibility): Moved to htmlediting.cpp.
+        (WebCore::Node::willRespondToMouseClickEvents): Uses newly added computeEditability.
+        (WebCore::Node::rootEditableElement): Moved to htmlediting.cpp.
+
+        * dom/Node.h: No longer includes EditingBoundary.h.
+        (WebCore::Node::isContentEditable):
+        (WebCore::Node::hasEditableStyle): No longer takes EditableType as an argument.
+        (WebCore::Node::hasRichlyEditableStyle): Ditto.
+
+        * editing/ApplyStyleCommand.cpp:
+        (WebCore::ApplyStyleCommand::removeInlineStyleFromElement): Uses newly added isEditableNode.
+        (WebCore::ApplyStyleCommand::surroundNodeRangeWithElement): Ditto.
+        * editing/DeleteFromTextNodeCommand.cpp:
+        (WebCore::DeleteFromTextNodeCommand::doApply): Ditto.
+        * editing/FrameSelection.cpp:
+        (WebCore::CaretBase::invalidateCaretRect): Ditto.
+        * editing/InsertNodeBeforeCommand.cpp:
+        (WebCore::InsertNodeBeforeCommand::doApply): Ditto.
+        (WebCore::InsertNodeBeforeCommand::doUnapply): Ditto.
+        * editing/RemoveNodeCommand.cpp:
+        (WebCore::RemoveNodeCommand::doApply): Ditto.
+
+        * editing/VisibleSelection.cpp:
+        (WebCore::VisibleSelection::hasEditableStyle): Since this is the only caller of isEditablePosition
+        which sets DoNotUpdateStyle, directly call hasEditableStyle on the container node instead. This was
+        not possible prior to r180726 because isEditablePosition had to move out of tables.
+
+        * editing/VisibleUnits.cpp:
+        (WebCore::previousLeafWithSameEditability): Uses newly added hasEditableStyle.
+        (WebCore::nextLeafWithSameEditability): Ditto.
+        (WebCore::rootEditableOrDocumentElement): Extracted from previousLinePosition. Use helper functions
+        in htmlediting.cpp instead of member functions of Node since they no longer support EditableType.
+        (WebCore::previousLinePosition):
+        (WebCore::nextLinePosition):
+
+        * editing/htmlediting.cpp:
+        (WebCore::highestEditableRoot): Uses newly added hasEditableStyle.
+        (WebCore::isEditableToAccessibility): Moved from Node.
+        (WebCore::computeEditability): Extracted from isEditablePosition.
+        (WebCore::hasEditableStyle): Added.
+        (WebCore::isEditableNode): Added.
+        (WebCore::isEditablePosition): Now calls computeEditability.
+        (WebCore::isRichlyEditablePosition): No longer takes EditableType since that variant was never used.
+        (WebCore::editableRootForPosition): Moved the code from Node::rootEditableElement.
+
+        * editing/htmlediting.h:
+
 2015-02-27  Chris Dumez  <cdumez@apple.com>
 
         Make ActiveDOMObject::canSuspend() pure virtual
index f83ea7d..bfa9277 100644 (file)
@@ -146,7 +146,6 @@ public:
     void removeAXID(AccessibilityObject*);
     bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); }
 
-    Element* rootAXEditableElement(Node*);
     const Element* rootAXEditableElement(const Node*);
     bool nodeIsTextControl(const Node*);
 
index d093222..7dfecbd 100644 (file)
@@ -239,7 +239,7 @@ bool Element::isMouseFocusable() const
 
 bool Element::shouldUseInputMethod()
 {
-    return isContentEditable(UserSelectAllIsAlwaysNonEditable);
+    return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) != Editability::ReadOnly;
 }
 
 bool Element::dispatchMouseEvent(const PlatformMouseEvent& platformEvent, const AtomicString& eventType, int detail, Element* relatedTarget)
index ebf4618..f448764 100644 (file)
@@ -537,16 +537,14 @@ const AtomicString& Node::namespaceURI() const
     return nullAtom;
 }
 
-bool Node::isContentEditable(UserSelectAllTreatment treatment)
+bool Node::isContentEditable()
 {
-    document().updateStyleIfNeeded();
-    return hasEditableStyle(Editable, treatment);
+    return computeEditability(UserSelectAllDoesNotAffectEditability, ShouldUpdateStyle::Update) != Editability::ReadOnly;
 }
 
 bool Node::isContentRichlyEditable()
 {
-    document().updateStyleIfNeeded();
-    return hasEditableStyle(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
+    return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) == Editability::CanEditRichly;
 }
 
 void Node::inspect()
@@ -555,15 +553,18 @@ void Node::inspect()
         document().page()->inspectorController().inspect(this);
 }
 
-bool Node::hasEditableStyle(EditableLevel editableLevel, UserSelectAllTreatment treatment) const
+Node::Editability Node::computeEditability(UserSelectAllTreatment treatment, ShouldUpdateStyle shouldUpdateStyle) const
 {
+    if (shouldUpdateStyle == ShouldUpdateStyle::Update)
+        document().updateStyleIfNeeded();
+
     if (!document().hasLivingRenderTree())
-        return false;
+        return Editability::ReadOnly;
     if (document().frame() && document().frame()->page() && document().frame()->page()->isEditable() && !containingShadowRoot())
-        return true;
+        return Editability::CanEditRichly;
 
     if (isPseudoElement())
-        return false;
+        return Editability::ReadOnly;
 
     // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
     // ContainerNode::setFocus() calls setNeedsStyleRecalc(), so the assertion
@@ -579,40 +580,22 @@ bool Node::hasEditableStyle(EditableLevel editableLevel, UserSelectAllTreatment
         // Elements with user-select: all style are considered atomic
         // therefore non editable.
         if (treatment == UserSelectAllIsAlwaysNonEditable && style->userSelect() == SELECT_ALL)
-            return false;
+            return Editability::ReadOnly;
 #else
         UNUSED_PARAM(treatment);
 #endif
         switch (style->userModify()) {
         case READ_ONLY:
-            return false;
+            return Editability::ReadOnly;
         case READ_WRITE:
-            return true;
+            return Editability::CanEditRichly;
         case READ_WRITE_PLAINTEXT_ONLY:
-            return editableLevel != RichlyEditable;
+            return Editability::CanEditPlainText;
         }
         ASSERT_NOT_REACHED();
-        return false;
+        return Editability::ReadOnly;
     }
-    return false;
-}
-
-bool Node::isEditableToAccessibility(EditableLevel editableLevel) const
-{
-    if (hasEditableStyle(editableLevel))
-        return true;
-
-    // FIXME: Respect editableLevel for ARIA editable elements.
-    if (editableLevel == RichlyEditable)
-        return false;
-
-    ASSERT(AXObjectCache::accessibilityEnabled());
-    ASSERT(document().existingAXObjectCache());
-
-    if (AXObjectCache* cache = document().existingAXObjectCache())
-        return cache->rootAXEditableElement(this);
-
-    return false;
+    return Editability::ReadOnly;
 }
 
 RenderBox* Node::renderBox() const
@@ -1030,16 +1013,6 @@ bool Node::isRootEditableElement() const
         || !parentNode()->isElementNode() || hasTagName(bodyTag));
 }
 
-Element* Node::rootEditableElement(EditableType editableType) const
-{
-    if (editableType == HasEditableAXRole) {
-        if (AXObjectCache* cache = document().existingAXObjectCache())
-            return const_cast<Element*>(cache->rootAXEditableElement(this));
-    }
-    
-    return rootEditableElement();
-}
-
 Element* Node::rootEditableElement() const
 {
     Element* result = nullptr;
@@ -2163,7 +2136,8 @@ bool Node::willRespondToMouseClickEvents()
         return false;
     if (downcast<Element>(*this).isDisabledFormControl())
         return false;
-    return isContentEditable(UserSelectAllIsAlwaysNonEditable) || hasEventListeners(eventNames().mouseupEvent) || hasEventListeners(eventNames().mousedownEvent) || hasEventListeners(eventNames().clickEvent) || hasEventListeners(eventNames().DOMActivateEvent);
+    return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::Update) != Editability::ReadOnly
+        || hasEventListeners(eventNames().mouseupEvent) || hasEventListeners(eventNames().mousedownEvent) || hasEventListeners(eventNames().clickEvent) || hasEventListeners(eventNames().DOMActivateEvent);
 #endif
 }
 
index dcce27a..2465b06 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef Node_h
 #define Node_h
 
-#include "EditingBoundary.h"
 #include "EventTarget.h"
 #include "URLHash.h"
 #include "LayoutRect.h"
@@ -313,7 +312,6 @@ public:
 
     bool isRootEditableElement() const;
     WEBCORE_EXPORT Element* rootEditableElement() const;
-    Element* rootEditableElement(EditableType) const;
 
     // Called by the parser when this element's close tag is reached,
     // signaling that all child tags have been parsed and added.
@@ -358,35 +356,25 @@ public:
         UserSelectAllDoesNotAffectEditability,
         UserSelectAllIsAlwaysNonEditable
     };
-    WEBCORE_EXPORT bool isContentEditable(UserSelectAllTreatment = UserSelectAllDoesNotAffectEditability);
+    WEBCORE_EXPORT bool isContentEditable();
     bool isContentRichlyEditable();
 
     WEBCORE_EXPORT void inspect();
 
-    bool hasEditableStyle(EditableType editableType = ContentIsEditable, UserSelectAllTreatment treatment = UserSelectAllIsAlwaysNonEditable) const
+    bool hasEditableStyle(UserSelectAllTreatment treatment = UserSelectAllIsAlwaysNonEditable) const
     {
-        switch (editableType) {
-        case ContentIsEditable:
-            return hasEditableStyle(Editable, treatment);
-        case HasEditableAXRole:
-            return isEditableToAccessibility(Editable);
-        }
-        ASSERT_NOT_REACHED();
-        return false;
+        return computeEditability(treatment, ShouldUpdateStyle::DoNotUpdate) != Editability::ReadOnly;
     }
-
-    bool hasRichlyEditableStyle(EditableType editableType = ContentIsEditable) const
+    // FIXME: Replace every use of this function by helpers in htmlediting.h
+    bool hasRichlyEditableStyle() const
     {
-        switch (editableType) {
-        case ContentIsEditable:
-            return hasEditableStyle(RichlyEditable, UserSelectAllIsAlwaysNonEditable);
-        case HasEditableAXRole:
-            return isEditableToAccessibility(RichlyEditable);
-        }
-        ASSERT_NOT_REACHED();
-        return false;
+        return computeEditability(UserSelectAllIsAlwaysNonEditable, ShouldUpdateStyle::DoNotUpdate) == Editability::CanEditRichly;
     }
 
+    enum class Editability { ReadOnly, CanEditPlainText, CanEditRichly };
+    enum class ShouldUpdateStyle { Update, DoNotUpdate };
+    WEBCORE_EXPORT Editability computeEditability(UserSelectAllTreatment, ShouldUpdateStyle) const;
+
     WEBCORE_EXPORT LayoutRect renderRect(bool* isReplaced);
     IntRect pixelSnappedRenderRect(bool* isReplaced) { return snappedIntRect(renderRect(isReplaced)); }
 
@@ -689,10 +677,6 @@ private:
     WEBCORE_EXPORT void removedLastRef();
     bool hasTreeSharedParent() const { return !!parentNode(); }
 
-    enum EditableLevel { Editable, RichlyEditable };
-    WEBCORE_EXPORT bool hasEditableStyle(EditableLevel, UserSelectAllTreatment = UserSelectAllIsAlwaysNonEditable) const;
-    WEBCORE_EXPORT bool isEditableToAccessibility(EditableLevel) const;
-
     virtual void refEventTarget() override;
     virtual void derefEventTarget() override;
 
index ad3d954..e33b8f6 100644 (file)
@@ -879,7 +879,7 @@ bool ApplyStyleCommand::removeInlineStyleFromElement(EditingStyle* style, PassRe
 {
     ASSERT(element);
 
-    if (!element->parentNode() || !element->parentNode()->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable))
+    if (!element->parentNode() || !isEditableNode(*element->parentNode()))
         return false;
 
     if (isStyledInlineElementToRemove(element.get())) {
@@ -1349,7 +1349,7 @@ void ApplyStyleCommand::surroundNodeRangeWithElement(PassRefPtr<Node> passedStar
     RefPtr<Node> node = startNode;
     while (node) {
         RefPtr<Node> next = node->nextSibling();
-        if (node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)) {
+        if (isEditableNode(*node)) {
             removeNode(node);
             appendNode(node, element);
         }
index a76f604..2ea96d5 100644 (file)
 
 #include "config.h"
 #include "DeleteFromTextNodeCommand.h"
-#include "Document.h"
-#include "ExceptionCodePlaceholder.h"
 
 #include "AXObjectCache.h"
+#include "Document.h"
+#include "ExceptionCodePlaceholder.h"
 #include "Text.h"
+#include "htmlediting.h"
 
 namespace WebCore {
 
@@ -48,7 +49,7 @@ void DeleteFromTextNodeCommand::doApply()
 {
     ASSERT(m_node);
 
-    if (!m_node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable))
+    if (!isEditableNode(*m_node))
         return;
 
     ExceptionCode ec = 0;
index 4d11f58..4d34fbd 100644 (file)
@@ -1453,7 +1453,7 @@ void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
         return;
 
     if (RenderView* view = node->document().renderView()) {
-        if (shouldRepaintCaret(view, node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)))
+        if (shouldRepaintCaret(view, isEditableNode(*node)))
             repaintCaretForLocalRect(node, localCaretRectWithoutUpdate());
     }
 }
index b24832c..d16b5d6 100644 (file)
@@ -51,9 +51,9 @@ InsertNodeBeforeCommand::InsertNodeBeforeCommand(PassRefPtr<Node> insertChild, P
 void InsertNodeBeforeCommand::doApply()
 {
     ContainerNode* parent = m_refChild->parentNode();
-    if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable && !parent->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)))
+    if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable && !isEditableNode(*parent)))
         return;
-    ASSERT(parent->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable));
+    ASSERT(isEditableNode(*parent));
 
     parent->insertBefore(m_insertChild.get(), m_refChild.get(), IGNORE_EXCEPTION);
 
@@ -63,7 +63,7 @@ void InsertNodeBeforeCommand::doApply()
 
 void InsertNodeBeforeCommand::doUnapply()
 {
-    if (!m_insertChild->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable))
+    if (!isEditableNode(*m_insertChild))
         return;
 
     // Need to notify this before actually deleting the text
index e5fa96b..31c54d1 100644 (file)
@@ -29,6 +29,7 @@
 #include "ExceptionCodePlaceholder.h"
 #include "Node.h"
 #include "RenderElement.h"
+#include "htmlediting.h"
 #include <wtf/Assertions.h>
 
 namespace WebCore {
@@ -46,9 +47,9 @@ void RemoveNodeCommand::doApply()
 {
     ContainerNode* parent = m_node->parentNode();
     if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable
-        && !parent->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable) && parent->renderer()))
+        && !isEditableNode(*parent) && parent->renderer()))
         return;
-    ASSERT(parent->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable) || !parent->renderer());
+    ASSERT(isEditableNode(*parent) || !parent->renderer());
 
     m_parent = parent;
     m_refChild = m_node->nextSibling();
index c99f5bf..986778c 100644 (file)
@@ -643,7 +643,9 @@ bool VisibleSelection::isContentEditable() const
 
 bool VisibleSelection::hasEditableStyle() const
 {
-    return isEditablePosition(start(), ContentIsEditable, DoNotUpdateStyle);
+    if (Node* containerNode = start().containerNode())
+        return containerNode->hasEditableStyle();
+    return false;
 }
 
 bool VisibleSelection::isContentRichlyEditable() const
index 375c329..7723ec0 100644 (file)
@@ -48,25 +48,25 @@ using namespace WTF::Unicode;
 
 static Node* previousLeafWithSameEditability(Node* node, EditableType editableType)
 {
-    bool editable = node->hasEditableStyle(editableType);
+    bool editable = hasEditableStyle(*node, editableType);
     node = previousLeafNode(node);
     while (node) {
-        if (editable == node->hasEditableStyle(editableType))
+        if (editable == hasEditableStyle(*node, editableType))
             return node;
         node = previousLeafNode(node);
     }
     return nullptr;
 }
 
-static Node* nextLeafWithSameEditability(Node* node, EditableType editableType = ContentIsEditable)
+static Node* nextLeafWithSameEditability(Node* node, EditableType editableType)
 {
     if (!node)
         return nullptr;
     
-    bool editable = node->hasEditableStyle(editableType);
+    bool editable = hasEditableStyle(*node, editableType);
     node = nextLeafNode(node);
     while (node) {
-        if (editable == node->hasEditableStyle(editableType))
+        if (editable == hasEditableStyle(*node, editableType))
             return node;
         node = nextLeafNode(node);
     }
@@ -935,6 +935,13 @@ static inline IntPoint absoluteLineDirectionPointToLocalPointInBlock(RootInlineB
     return IntPoint(root.blockDirectionPointInLine(), lineDirectionPoint - absoluteBlockPoint.y());
 }
 
+static Element* rootEditableOrDocumentElement(Node& node, EditableType editableType)
+{
+    if (hasEditableStyle(node, editableType))
+        return editableRootForPosition(firstPositionInOrBeforeNode(&node), editableType);
+    return node.document().documentElement();
+}
+
 VisiblePosition previousLinePosition(const VisiblePosition& visiblePosition, int lineDirectionPoint, EditableType editableType)
 {
     Position p = visiblePosition.deepEquivalent();
@@ -984,7 +991,7 @@ VisiblePosition previousLinePosition(const VisiblePosition& visiblePosition, int
     // Could not find a previous line. This means we must already be on the first line.
     // Move to the start of the content in this block, which effectively moves us
     // to the start of the line we're on.
-    Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
+    Element* rootElement = rootEditableOrDocumentElement(*node, editableType);
     if (!rootElement)
         return VisiblePosition();
     return VisiblePosition(firstPositionInNode(rootElement), DOWNSTREAM);
@@ -1042,7 +1049,7 @@ VisiblePosition nextLinePosition(const VisiblePosition& visiblePosition, int lin
     // Could not find a next line. This means we must already be on the last line.
     // Move to the end of the content in this block, which effectively moves us
     // to the end of the line we're on.
-    Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
+    Element* rootElement = rootEditableOrDocumentElement(*node, editableType);
     if (!rootElement)
         return VisiblePosition();
     return VisiblePosition(lastPositionInNode(rootElement), DOWNSTREAM);
index 23ec90b..31febfb 100644 (file)
@@ -118,7 +118,7 @@ Node* highestEditableRoot(const Position& position, EditableType editableType)
         node = node->parentNode();
         if (!node)
             break;
-        if (node->hasEditableStyle(editableType))
+        if (hasEditableStyle(*node, editableType))
             highestEditableRoot = node;
     }
 
@@ -141,17 +141,46 @@ Node* lowestEditableAncestor(Node* node)
     return 0;
 }
 
-bool isEditablePosition(const Position& p, EditableType editableType, EUpdateStyle updateStyle)
+static bool isEditableToAccessibility(const Node& node)
 {
-    Node* node = p.containerNode();
-    if (!node)
+    ASSERT(AXObjectCache::accessibilityEnabled());
+    ASSERT(node.document().existingAXObjectCache());
+
+    if (AXObjectCache* cache = node.document().existingAXObjectCache())
+        return cache->rootAXEditableElement(&node);
+
+    return false;
+}
+
+static bool computeEditability(const Node& node, EditableType editableType, Node::ShouldUpdateStyle shouldUpdateStyle)
+{
+    if (node.computeEditability(Node::UserSelectAllIsAlwaysNonEditable, shouldUpdateStyle) != Node::Editability::ReadOnly)
+        return true;
+
+    switch (editableType) {
+    case ContentIsEditable:
         return false;
-    if (updateStyle == UpdateStyle)
-        node->document().updateStyleIfNeeded();
-    else
-        ASSERT(updateStyle == DoNotUpdateStyle);
+    case HasEditableAXRole:
+        return isEditableToAccessibility(node);
+    }
+    ASSERT_NOT_REACHED();
+    return false;
+}
 
-    return node->hasEditableStyle(editableType);
+bool hasEditableStyle(const Node& node, EditableType editableType)
+{
+    return computeEditability(node, editableType, Node::ShouldUpdateStyle::DoNotUpdate);
+}
+
+bool isEditableNode(const Node& node)
+{
+    return computeEditability(node, ContentIsEditable, Node::ShouldUpdateStyle::Update);
+}
+
+bool isEditablePosition(const Position& position, EditableType editableType)
+{
+    Node* node = position.containerNode();
+    return node && computeEditability(*node, editableType, Node::ShouldUpdateStyle::Update);
 }
 
 bool isAtUnsplittableElement(const Position& pos)
@@ -161,13 +190,12 @@ bool isAtUnsplittableElement(const Position& pos)
 }
     
     
-bool isRichlyEditablePosition(const Position& p, EditableType editableType)
+bool isRichlyEditablePosition(const Position& position)
 {
-    Node* node = p.containerNode();
+    Node* node = position.containerNode();
     if (!node)
         return false;
-
-    return node->hasRichlyEditableStyle(editableType);
+    return node->hasRichlyEditableStyle();
 }
 
 Element* editableRootForPosition(const Position& p, EditableType editableType)
@@ -176,7 +204,15 @@ Element* editableRootForPosition(const Position& p, EditableType editableType)
     if (!node)
         return 0;
 
-    return node->rootEditableElement(editableType);
+    switch (editableType) {
+    case HasEditableAXRole:
+        if (AXObjectCache* cache = node->document().existingAXObjectCache())
+            return const_cast<Element*>(cache->rootAXEditableElement(node));
+        FALLTHROUGH;
+    case ContentIsEditable:
+        return node->rootEditableElement();
+    }
+    return 0;
 }
 
 // Finds the enclosing element until which the tree can be split.
index ce895e3..947c57c 100644 (file)
@@ -85,6 +85,9 @@ int caretMaxOffset(const Node*);
 
 // boolean functions on Node
 
+bool hasEditableStyle(const Node&, EditableType);
+bool isEditableNode(const Node&);
+
 // FIXME: editingIgnoresContent, canHaveChildrenForEditing, and isAtomicNode
 // should be renamed to reflect its usage.
 
@@ -164,9 +167,8 @@ int comparePositions(const Position&, const Position&);
 
 // boolean functions on Position
 
-enum EUpdateStyle { UpdateStyle, DoNotUpdateStyle };
-WEBCORE_EXPORT bool isEditablePosition(const Position&, EditableType = ContentIsEditable, EUpdateStyle = UpdateStyle);
-bool isRichlyEditablePosition(const Position&, EditableType = ContentIsEditable);
+WEBCORE_EXPORT bool isEditablePosition(const Position&, EditableType = ContentIsEditable);
+bool isRichlyEditablePosition(const Position&);
 bool isFirstVisiblePositionInSpecialElement(const Position&);
 bool isLastVisiblePositionInSpecialElement(const Position&);
 bool lineBreakExistsAtPosition(const Position&);