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: https://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 d5880513daf7b7589bebee1fae672ce3b1f31cd7..2bbf063ccc18a22439048201f8e70d63d1538e43 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 f83ea7d4a87efcfd1bf1e0f7bb300bd49a43aa40..bfa927726546390c5e4d9fd74c20c92258e398c6 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 d0932220c131bc87ad88af9fbaa21d7cd015a380..7dfecbd5e5ea62c407bb5d8d17a25316fa1b35af 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 ebf46187fb7fad48ab8848e9ab040454f8c95081..f44876474d43b28859ebadd05428dfa2e29d2899 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 dcce27a0204de481216ec7e3ba6d2b463c6d4745..2465b06efbd6e96b11df8d897e19fbb71f85cd66 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 ad3d9543edf9450c82e78a83a43274d1c97a9bc2..e33b8f61db243f88fa6329afe32970095bb72879 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 a76f60492304e186be06557db11087d0cf2303d7..2ea96d55cafd3dac334880c55d2c91001e1612af 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 4d11f5823d28ccc1a5384ad6bd12c03b4cb0601a..4d34fbd359255b05d4ed4269619f6a2bfd57c919 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 b24832cf062146bb3831b42a0d50398282174ba0..d16b5d61e1db4c2773972611f2a26515c28754a2 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 e5fa96bb6ddb7d32814fb73eb825c63382e3e755..31c54d1e882e2d46540408e45060c49d908bbec6 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 c99f5bf8ddc0c01d338a9d31a82d079e311d2458..986778c568b246118d1a3da27c948ceeb8197d77 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 375c3296b0591e68699c7088231beeae608b9970..7723ec0cd850430cf5e03b2e7558c484dfa06c69 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 23ec90bed08fd16e753cc2cbd12c4dbce6bf6798..31febfb8a274a724373c8b3627248f8ba0538ee1 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 ce895e32734c17fe9ea7483fd6998cd4c6292bdf..947c57c307c2ddfa5c305cd12cc9055bca12b4a2 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&);