CrashTracer: 1,382 crashes in Safari at com.apple.WebCore: WebCore::VisiblePosition...
authorcfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Sep 2010 17:59:32 +0000 (17:59 +0000)
committercfleizach@apple.com <cfleizach@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Sep 2010 17:59:32 +0000 (17:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=45927

Reviewed by Beth Dakin.

WebCore:

AXTextMarkers store pointers to Nodes without any retain or reference. If a Node is deallocated and then
a client tries to use a text marker that references that node, it leads to this crash.

The AXObjectCache instance now keeps a HashSet of Node's being used. When a node becomes deallocated, it removes itself
from the HashSet. When creating a VisiblePosition from an AXTextMarker, the cache can then check if the node is valid
before proceeding.

Test: platform/mac/accessibility/crash-invalid-text-marker-node.html

* accessibility/AXObjectCache.cpp:
(WebCore::AXObjectCache::visiblePositionForTextMarkerData):
(WebCore::AXObjectCache::textMarkerDataForVisiblePosition):
    Modify to check whether a node is valid before proceeeding.
* accessibility/AXObjectCache.h:
(WebCore::AXObjectCache::setNodeInUse):
(WebCore::AXObjectCache::removeNodeForUse):
(WebCore::AXObjectCache::isNodeInUse):
    Methods for managing whether a node is in use by text markers.
* accessibility/mac/AccessibilityObjectWrapper.mm:
(textMarkerForVisiblePosition):
(-[AccessibilityObjectWrapper textMarkerForVisiblePosition:]):
(visiblePositionForTextMarker):
(-[AccessibilityObjectWrapper visiblePositionForTextMarker:]):
(visiblePositionForStartOfTextMarkerRange):
(visiblePositionForEndOfTextMarkerRange):
(-[AccessibilityObjectWrapper doAXAttributedStringForTextMarkerRange:]):
(textMarkerRangeFromVisiblePositions):
(-[AccessibilityObjectWrapper textMarkerRangeFromVisiblePositions:endPosition:]):
(-[AccessibilityObjectWrapper visiblePositionRangeForTextMarkerRange:]):
(-[AccessibilityObjectWrapper textMarkerRangeForSelection]):
(-[AccessibilityObjectWrapper accessibilityAttributeValue:]):
(-[AccessibilityObjectWrapper doAXAttributedStringForRange:]):
(-[AccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
     Change these calls so that the axObjectCache() can be passed in to create the visible position.
* dom/Document.cpp:
(WebCore::Document::axObjectCacheExists):
* dom/Document.h:
* dom/Node.cpp:
(WebCore::Node::~Node):
     If accessibility is enabled, inform the axObjectCache() that this node is disappearing.

LayoutTests:

* platform/mac/accessibility/crash-invalid-text-marker-node-expected.txt: Added.
* platform/mac/accessibility/crash-invalid-text-marker-node.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/platform/mac/accessibility/crash-invalid-text-marker-node-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/accessibility/crash-invalid-text-marker-node.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/accessibility/AXObjectCache.cpp
WebCore/accessibility/AXObjectCache.h
WebCore/accessibility/mac/AccessibilityObjectWrapper.mm
WebCore/dom/Document.cpp
WebCore/dom/Document.h
WebCore/dom/Node.cpp

index 128251be95a9991633705ca66b82465128fb35a3..15b7a94c897006c79b877f85111d10f465f4efe9 100644 (file)
@@ -1,3 +1,13 @@
+2010-09-28  Chris Fleizach  <cfleizach@apple.com>
+
+        Reviewed by Beth Dakin.
+
+        CrashTracer: 1,382 crashes in Safari at com.apple.WebCore: WebCore::VisiblePosition::canonicalPosition + 78
+        https://bugs.webkit.org/show_bug.cgi?id=45927
+
+        * platform/mac/accessibility/crash-invalid-text-marker-node-expected.txt: Added.
+        * platform/mac/accessibility/crash-invalid-text-marker-node.html: Added.
+
 2010-09-28  Ryosuke Niwa  <rniwa@webkit.org>
 
         Reviewed by Kent Tamura.
diff --git a/LayoutTests/platform/mac/accessibility/crash-invalid-text-marker-node-expected.txt b/LayoutTests/platform/mac/accessibility/crash-invalid-text-marker-node-expected.txt
new file mode 100644 (file)
index 0000000..f39f0cb
--- /dev/null
@@ -0,0 +1,10 @@
+
+This protects against a crash when a text marker still holds a reference to a node that's been deallocated.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/mac/accessibility/crash-invalid-text-marker-node.html b/LayoutTests/platform/mac/accessibility/crash-invalid-text-marker-node.html
new file mode 100644 (file)
index 0000000..7af4075
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../../fast/js/resources/js-test-style.css">
+<script>
+var successfullyParsed = false;
+</script>
+<script src="../../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body id="body">
+
+<iframe id="iframe" width=100 height=100></iframe>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+
+    description("This protects against a crash when a text marker still holds a reference to a node that's been deallocated.");
+
+    // Add an element that a text marker can be retrieved from.
+    var contentDoc = document.getElementById("iframe").contentDocument; 
+    contentDoc.body.innerHTML = "<h1 tabindex='0'>content</h1>";
+
+    // Tab to the element. 
+    // Note: If the element has an "id" it won't get de-allocated in time, so .focus() can't be used.
+    eventSender.keyDown("\t");
+
+    // get a marker that will become invalid when the node disappears.
+    var axDiv = accessibilityController.focusedElement;
+    var textMarkerRange = axDiv.textMarkerRangeForElement(axDiv);
+    var invalidMarker = axDiv.startTextMarkerForTextMarkerRange(textMarkerRange);
+
+</script>
+
+<script>
+     // Write new content to cause all content to disappear.
+     contentDoc.body.innerHTML = "<h2>new content</h2>";
+</script>
+
+<script>
+    // Access the invalid marker (it should not crash).
+    document.getElementById("body").focus();
+    var body = accessibilityController.focusedElement;
+
+    body.accessibilityElementForTextMarker(invalidMarker);
+
+    successfullyParsed = true;
+</script>
+
+<script src="../../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index b2603b9e29985df7d96ea01420c1aba7645e8780..6d652bf207e669dd02b613f26c88f99cf908cd0a 100644 (file)
@@ -1,3 +1,51 @@
+2010-09-28  Chris Fleizach  <cfleizach@apple.com>
+
+        Reviewed by Beth Dakin.
+
+        CrashTracer: 1,382 crashes in Safari at com.apple.WebCore: WebCore::VisiblePosition::canonicalPosition + 78
+        https://bugs.webkit.org/show_bug.cgi?id=45927
+
+        AXTextMarkers store pointers to Nodes without any retain or reference. If a Node is deallocated and then
+        a client tries to use a text marker that references that node, it leads to this crash.
+
+        The AXObjectCache instance now keeps a HashSet of Node's being used. When a node becomes deallocated, it removes itself
+        from the HashSet. When creating a VisiblePosition from an AXTextMarker, the cache can then check if the node is valid
+        before proceeding.
+
+        Test: platform/mac/accessibility/crash-invalid-text-marker-node.html
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::AXObjectCache::visiblePositionForTextMarkerData):
+        (WebCore::AXObjectCache::textMarkerDataForVisiblePosition):
+            Modify to check whether a node is valid before proceeeding.
+        * accessibility/AXObjectCache.h:
+        (WebCore::AXObjectCache::setNodeInUse):
+        (WebCore::AXObjectCache::removeNodeForUse):
+        (WebCore::AXObjectCache::isNodeInUse):
+            Methods for managing whether a node is in use by text markers.
+        * accessibility/mac/AccessibilityObjectWrapper.mm:
+        (textMarkerForVisiblePosition):
+        (-[AccessibilityObjectWrapper textMarkerForVisiblePosition:]):
+        (visiblePositionForTextMarker):
+        (-[AccessibilityObjectWrapper visiblePositionForTextMarker:]):
+        (visiblePositionForStartOfTextMarkerRange):
+        (visiblePositionForEndOfTextMarkerRange):
+        (-[AccessibilityObjectWrapper doAXAttributedStringForTextMarkerRange:]):
+        (textMarkerRangeFromVisiblePositions):
+        (-[AccessibilityObjectWrapper textMarkerRangeFromVisiblePositions:endPosition:]):
+        (-[AccessibilityObjectWrapper visiblePositionRangeForTextMarkerRange:]):
+        (-[AccessibilityObjectWrapper textMarkerRangeForSelection]):
+        (-[AccessibilityObjectWrapper accessibilityAttributeValue:]):
+        (-[AccessibilityObjectWrapper doAXAttributedStringForRange:]):
+        (-[AccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+             Change these calls so that the axObjectCache() can be passed in to create the visible position.
+        * dom/Document.cpp:
+        (WebCore::Document::axObjectCacheExists):
+        * dom/Document.h:
+        * dom/Node.cpp:
+        (WebCore::Node::~Node):
+             If accessibility is enabled, inform the axObjectCache() that this node is disappearing.
+
 2010-09-28  Chris Rogers  <crogers@google.com>
 
         Reviewed by Kenneth Russell.
index a58b324d740dc42a60b4919314877030695710ef..30cce3ac6442b0374b6abb082d1743203e9242e1 100644 (file)
@@ -505,9 +505,12 @@ void AXObjectCache::handleAriaRoleChanged(RenderObject* renderer)
         static_cast<AccessibilityRenderObject*>(obj)->updateAccessibilityRole();
 }
 #endif
-    
+
 VisiblePosition AXObjectCache::visiblePositionForTextMarkerData(TextMarkerData& textMarkerData)
 {
+    if (!isNodeInUse(textMarkerData.node))
+        return VisiblePosition();
+    
     VisiblePosition visiblePos = VisiblePosition(textMarkerData.node, textMarkerData.offset, textMarkerData.affinity);
     Position deepPos = visiblePos.deepEquivalent();
     if (deepPos.isNull())
@@ -559,7 +562,9 @@ void AXObjectCache::textMarkerDataForVisiblePosition(TextMarkerData& textMarkerD
     textMarkerData.axID = obj.get()->axObjectID();
     textMarkerData.node = domNode;
     textMarkerData.offset = deepPos.deprecatedEditingOffset();
-    textMarkerData.affinity = visiblePos.affinity();    
+    textMarkerData.affinity = visiblePos.affinity();   
+    
+    cache->setNodeInUse(domNode);
 }
     
 } // namespace WebCore
index 7189a35e835c5f24a9b43e1f9073ff890c88d29b..2ee56eef8fc6c90063c793d993c818ba2ba49ff6 100644 (file)
@@ -100,9 +100,14 @@ public:
     AXID platformGenerateAXID() const;
     AccessibilityObject* objectFromAXID(AXID id) const { return m_objects.get(id).get(); }
 
+    // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid.
+    void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); }
+    void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); }
+    bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); }
+    
     // Text marker utilities.
-    static void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&);
-    static VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
+    void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&);
+    VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&);
 
     enum AXNotification {
         AXActiveDescendantChanged,
@@ -141,6 +146,7 @@ protected:
 private:
     HashMap<AXID, RefPtr<AccessibilityObject> > m_objects;
     HashMap<RenderObject*, AXID> m_renderObjectMapping;
+    HashSet<Node*> m_textMarkerNodes;
     static bool gAccessibilityEnabled;
     static bool gAccessibilityEnhancedUserInterfaceEnabled;
     
index 2e7758ef487f60845ec379c43ccb4150e7e100f8..cb983eb948ddcacc6cb9e2941ffeadc1a3b1bfe6 100644 (file)
@@ -230,35 +230,49 @@ typedef unsigned NSUInteger;
     return NSAccessibilityUnignoredDescendant(widget->platformWidget());
 }
 
-static WebCoreTextMarker* textMarkerForVisiblePosition(const VisiblePosition& visiblePos)
+static WebCoreTextMarker* textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
 {
+    ASSERT(cache);
+    
     TextMarkerData textMarkerData;
-    AXObjectCache::textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
+    cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
     if (!textMarkerData.axID)
         return nil;
     
     return [[WebCoreViewFactory sharedFactory] textMarkerWithBytes:&textMarkerData length:sizeof(textMarkerData)];
 }
 
-static VisiblePosition visiblePositionForTextMarker(WebCoreTextMarker* textMarker)
+- (WebCoreTextMarker *)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
+{
+    return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
+}
+
+static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, WebCoreTextMarker* textMarker)
 {
+    ASSERT(cache);
+
     if (!textMarker)
         return VisiblePosition();
     TextMarkerData textMarkerData;
     if (![[WebCoreViewFactory sharedFactory] getBytes:&textMarkerData fromTextMarker:textMarker length:sizeof(textMarkerData)])
         return VisiblePosition();
     
-    return AXObjectCache::visiblePositionForTextMarkerData(textMarkerData);
+    return cache->visiblePositionForTextMarkerData(textMarkerData);
 }
 
-static VisiblePosition visiblePositionForStartOfTextMarkerRange(WebCoreTextMarkerRange* textMarkerRange)
+- (VisiblePosition)visiblePositionForTextMarker:(WebCoreTextMarker *)textMarker
 {
-    return visiblePositionForTextMarker([[WebCoreViewFactory sharedFactory] startOfTextMarkerRange:textMarkerRange]);
+    return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
 }
 
-static VisiblePosition visiblePositionForEndOfTextMarkerRange(WebCoreTextMarkerRange* textMarkerRange)
+static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, WebCoreTextMarkerRange* textMarkerRange)
 {
-    return visiblePositionForTextMarker([[WebCoreViewFactory sharedFactory] endOfTextMarkerRange:textMarkerRange]);
+    return visiblePositionForTextMarker(cache, [[WebCoreViewFactory sharedFactory] startOfTextMarkerRange:textMarkerRange]);
+}
+
+static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, WebCoreTextMarkerRange* textMarkerRange)
+{
+    return visiblePositionForTextMarker(cache, [[WebCoreViewFactory sharedFactory] endOfTextMarkerRange:textMarkerRange]);
 }
 
 static WebCoreTextMarkerRange* textMarkerRangeFromMarkers(WebCoreTextMarker* textMarker1, WebCoreTextMarker* textMarker2)
@@ -528,11 +542,11 @@ static NSString* nsStringForReplacedNode(Node* replacedNode)
         return nil;
     
     // extract the start and end VisiblePosition
-    VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(textMarkerRange);
+    VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
     if (startVisiblePosition.isNull())
         return nil;
 
-    VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(textMarkerRange);
+    VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
     if (endVisiblePosition.isNull())
         return nil;
 
@@ -578,13 +592,18 @@ static NSString* nsStringForReplacedNode(Node* replacedNode)
     return [attrString autorelease];
 }
 
-static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePosition startPosition, VisiblePosition endPosition)
+static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)
 {
-    WebCoreTextMarker* startTextMarker = textMarkerForVisiblePosition(startPosition);
-    WebCoreTextMarker* endTextMarker   = textMarkerForVisiblePosition(endPosition);
+    WebCoreTextMarker* startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
+    WebCoreTextMarker* endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
     return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
 }
 
+- (WebCoreTextMarkerRange *)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition
+{
+    return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
+}
+
 - (NSArray*)accessibilityActionNames
 {
     if (![self updateObjectBackingStore])
@@ -990,7 +1009,8 @@ static WebCoreTextMarkerRange* textMarkerRangeFromVisiblePositions(VisiblePositi
 {
     if (!textMarkerRange)
         return VisiblePositionRange();
-    return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(textMarkerRange), visiblePositionForEndOfTextMarkerRange(textMarkerRange));
+    AXObjectCache* cache = m_object->axObjectCache();
+    return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
 }
 
 - (NSArray*)renderWidgetChildren
@@ -1036,7 +1056,7 @@ static NSMutableArray* convertToNSArray(const AccessibilityObject::Accessibility
     VisibleSelection selection = m_object->selection();
     if (selection.isNone())
         return nil;
-    return textMarkerRangeFromVisiblePositions(selection.visibleStart(), selection.visibleEnd());
+    return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
 }
 
 - (NSValue*)position
@@ -1788,9 +1808,9 @@ static NSString* roleValueToNSString(AccessibilityRole value)
             return nil;
         
         if ([attributeName isEqualToString: @"AXStartTextMarker"])
-            return textMarkerForVisiblePosition(startOfDocument(renderer->document()));
+            return [self textMarkerForVisiblePosition:startOfDocument(renderer->document())];
         if ([attributeName isEqualToString: @"AXEndTextMarker"])
-            return textMarkerForVisiblePosition(endOfDocument(renderer->document()));
+            return [self textMarkerForVisiblePosition:endOfDocument(renderer->document())];
 
         if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
             return [NSNumber numberWithInt:blockquoteLevel(renderer)];
@@ -2254,7 +2274,7 @@ static RenderObject* rendererForView(NSView* view)
 {
     PlainTextRange textRange = PlainTextRange(range.location, range.length);
     VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);
-    return [self doAXAttributedStringForTextMarkerRange:textMarkerRangeFromVisiblePositions(visiblePosRange.start, visiblePosRange.end)];
+    return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];
 }
 
 // The RTF representation of the text associated with this accessibility object that is
@@ -2316,7 +2336,7 @@ static RenderObject* rendererForView(NSView* view)
     
     // dispatch
     if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         AccessibilityObject* axObject = m_object->accessibilityObjectForPosition(visiblePos);
         if (!axObject)
             return nil;
@@ -2325,17 +2345,17 @@ static RenderObject* rendererForView(NSView* view)
 
     if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
         VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange();
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXLineForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
         VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine([number intValue]);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) {
@@ -2345,7 +2365,7 @@ static RenderObject* rendererForView(NSView* view)
 
     if ([attribute isEqualToString:@"AXTextMarkerForPosition"]) {
         IntPoint webCorePoint = IntPoint(point);
-        return pointSet ? textMarkerForVisiblePosition(m_object->visiblePositionForPoint(webCorePoint)) : nil;
+        return pointSet ? [self textMarkerForVisiblePosition:m_object->visiblePositionForPoint(webCorePoint)] : nil;
     }
 
     if ([attribute isEqualToString:@"AXBoundsForTextMarkerRange"]) {
@@ -2384,102 +2404,102 @@ static RenderObject* rendererForView(NSView* view)
             || ![[WebCoreViewFactory sharedFactory] objectIsTextMarker:textMarker2])
             return nil;
 
-        VisiblePosition visiblePos1 = visiblePositionForTextMarker(textMarker1);
-        VisiblePosition visiblePos2 = visiblePositionForTextMarker(textMarker2);
+        VisiblePosition visiblePos1 = [self visiblePositionForTextMarker:(textMarker1)];
+        VisiblePosition visiblePos2 = [self visiblePositionForTextMarker:(textMarker2)];
         VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->nextVisiblePosition(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->nextVisiblePosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->previousVisiblePosition(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->previousVisiblePosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXSentenceTextMarkerRangeForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXParagraphTextMarkerRangeForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->nextWordEnd(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->nextWordEnd(visiblePos)];
     }
     
     if ([attribute isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->previousWordStart(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->previousWordStart(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->nextLineEndPosition(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->nextLineEndPosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->previousLineStartPosition(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->previousLineStartPosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXNextSentenceEndTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->nextSentenceEndPosition(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->nextSentenceEndPosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXPreviousSentenceStartTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->previousSentenceStartPosition(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->previousSentenceStartPosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXNextParagraphEndTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->nextParagraphEndPosition(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->nextParagraphEndPosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXPreviousParagraphStartTextMarkerForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
-        return textMarkerForVisiblePosition(m_object->previousParagraphStartPosition(visiblePos));
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
+        return [self textMarkerForVisiblePosition:m_object->previousParagraphStartPosition(visiblePos)];
     }
 
     if ([attribute isEqualToString:@"AXStyleTextMarkerRangeForTextMarker"]) {
-        VisiblePosition visiblePos = visiblePositionForTextMarker(textMarker);
+        VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
         VisiblePositionRange vpRange = m_object->styleRangeForPosition(visiblePos);
-        return (id)textMarkerRangeFromVisiblePositions(vpRange.start, vpRange.end);
+        return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
     }
 
     if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
@@ -2493,12 +2513,12 @@ static RenderObject* rendererForView(NSView* view)
     // Used only by DumpRenderTree (so far).
     if ([attribute isEqualToString:@"AXStartTextMarkerForTextMarkerRange"]) {
         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
-        return textMarkerForVisiblePosition(visiblePosRange.start);
+        return [self textMarkerForVisiblePosition:visiblePosRange.start];
     }
 
     if ([attribute isEqualToString:@"AXEndTextMarkerForTextMarkerRange"]) {
         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
-        return textMarkerForVisiblePosition(visiblePosRange.end);
+        return [self textMarkerForVisiblePosition:visiblePosRange.end];
     }
     
     if (m_object->isDataTable()) {
index 0bda797a638cc603efc24060eb0f41302ef435ce..9a923f407c63517fa324d27d4b889035db240793 100644 (file)
@@ -1782,6 +1782,18 @@ void Document::clearAXObjectCache()
         doc->clearAXObjectCache();
 }
 
+bool Document::axObjectCacheExists() const
+{
+    if (m_axObjectCache)
+        return true;
+    
+    Document* doc = topDocument();
+    if (doc != this)
+        return doc->axObjectCacheExists();
+    
+    return false;
+}
+    
 AXObjectCache* Document::axObjectCache() const
 {
     // The only document that actually has a AXObjectCache is the top-level
index d5021af861d6b037db6c8df67ba1b430202fa332..fa14e3d39a7dbe794c834b6936efa8103f698b77 100644 (file)
@@ -526,6 +526,7 @@ public:
 
     void clearAXObjectCache();
     AXObjectCache* axObjectCache() const;
+    bool axObjectCacheExists() const;
     
     // to get visually ordered hebrew and arabic pages right
     void setVisuallyOrdered();
index 547fd0480810d5ee68a0dbaf047efe46dbabaa46..53395a875e22637e925a57c272db482be8a53004 100644 (file)
@@ -25,6 +25,7 @@
 #include "config.h"
 #include "Node.h"
 
+#include "AXObjectCache.h"
 #include "Attr.h"
 #include "Attribute.h"
 #include "CSSParser.h"
@@ -381,6 +382,9 @@ Node::~Node()
     if (renderer())
         detach();
 
+    if (AXObjectCache::accessibilityEnabled() && m_document && m_document->axObjectCacheExists())
+        m_document->axObjectCache()->removeNodeForUse(this);
+    
     if (m_previous)
         m_previous->setNextSibling(0);
     if (m_next)