AXObjectCache cleared unnecessarily when non-top Document is detached.
https://bugs.webkit.org/show_bug.cgi?id=68636

Patch by Dominic Mazzoni <dmazzoni@google.com> on 2011-09-27
Reviewed by Chris Fleizach.

Source/WebCore:

Test: accessibility/deleting-iframe-destroys-axcache.html

* dom/Document.cpp:
(WebCore::Document::attach):
(WebCore::Document::detach):

LayoutTests:

* accessibility/deleting-iframe-destroys-axcache.html: Added.
* platform/mac/accessibility/deleting-iframe-destroys-axcache-expected.txt: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96127 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 55aa34e..6399959 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2011-09-27  Dominic Mazzoni  <dmazzoni@google.com>
+
+        AXObjectCache cleared unnecessarily when non-top Document is detached.
+        https://bugs.webkit.org/show_bug.cgi?id=68636
+
+        Reviewed by Chris Fleizach.
+
+        * accessibility/deleting-iframe-destroys-axcache.html: Added.
+        * platform/mac/accessibility/deleting-iframe-destroys-axcache-expected.txt: Added.
+
 2011-09-26  Ryosuke Niwa  <rniwa@webkit.org>
 
         dump-as-markup conversion: editing/pasteboard/merge-end-list.html and merge-end-table.html
diff --git a/LayoutTests/accessibility/deleting-iframe-destroys-axcache.html b/LayoutTests/accessibility/deleting-iframe-destroys-axcache.html
new file mode 100644
index 0000000..87563e2
--- /dev/null
+++ b/LayoutTests/accessibility/deleting-iframe-destroys-axcache.html
@@ -0,0 +1,107 @@
+<html>
+<head>
+<link rel="stylesheet" href="../fast/js/resources/js-test-style.css">
+<script src="../fast/js/resources/js-test-pre.js"></script>
+
+  <script>
+    if (window.layoutTestController)
+        layoutTestController.waitUntilDone();
+
+    function buildAccessibilityTree(accessibilityObject, indent) {
+        var str = "";
+        for (var i = 0; i < indent; i++)
+            str += "    ";
+        str += accessibilityObject.role;
+        str += " " + accessibilityObject.stringValue;
+
+        if (accessibilityObject.role == '')
+            str += accessibilityObject.allAttributes();
+
+        str += "\n";
+        document.getElementById("console").innerText += str;
+
+        if (accessibilityObject.stringValue.indexOf('End of test') >= 0)
+            return false;
+
+        var count = accessibilityObject.childrenCount;
+        for (var i = 0; i < count; ++i) {
+            if (!buildAccessibilityTree(accessibilityObject.childAtIndex(i), indent + 1))
+                return false;
+        }
+
+        return true;
+    }
+
+    function runTest()
+    {
+        description("This tests that deleting an iframe doesn't cause the accessibility cache to be destroyed and recreated.");
+
+        if (window.accessibilityController) {
+            window.root = accessibilityController.rootElement;
+            window.body = root.childAtIndex(0);
+            window.before = body.childAtIndex(0).childAtIndex(0);
+            window.iframe = body.childAtIndex(1).childAtIndex(0);
+            window.after = body.childAtIndex(2).childAtIndex(0);
+
+            window.frameBody = window.iframe.childAtIndex(0);
+            window.frameBodyRole = window.frameBody.role;
+            window.frameGroup = window.frameBody.childAtIndex(0);
+            window.frameGroupRole = window.frameGroup.role;
+            window.frameButton = window.frameGroup.childAtIndex(0);
+            window.frameButtonRole = window.frameButton.role;
+
+            document.getElementById("console").innerText += "\nBefore:\n";
+            buildAccessibilityTree(root, 0);
+
+            // Remove the iframe.
+            document.body.removeChild(document.getElementById("iframe"));
+
+            window.newRoot = accessibilityController.rootElement;
+            window.newBody = newRoot.childAtIndex(0);
+            window.newBefore = newBody.childAtIndex(0).childAtIndex(0);
+            window.newAfter = newBody.childAtIndex(1).childAtIndex(0);
+
+            document.getElementById("console").innerText += "\nAfter:\n";
+            buildAccessibilityTree(newRoot, 0);
+            document.getElementById("console").innerText += "\n";
+
+            // Make sure that the accessibility objects from the iframe's nodes
+            // are now invalid by checking that their role is changed - this
+            // is because they've been deleted.
+            shouldBeFalse("frameBodyRole == frameBody.role");
+            shouldBeFalse("frameGroupRole == frameGroup.role");
+            shouldBeFalse("frameButtonRole == frameButton.role");
+
+            // Make sure that the other nodes are unchanged.
+            shouldBeTrue("root.isEqual(newRoot)");
+            shouldBeTrue("body.isEqual(newBody)");
+            shouldBeTrue("before.isEqual(newBefore)");
+            shouldBeTrue("after.isEqual(newAfter)");
+        }
+
+        debug('<br /><span class="pass">TEST COMPLETE</span>');
+        if (window.layoutTestController)
+            layoutTestController.notifyDone();
+    }
+    
+    window.addEventListener('load', function() {
+        setTimeout(runTest, 10);
+    }, false);
+    
+  </script>
+</head>
+<body>
+
+<p>Before</p>
+
+<iframe id="iframe" src="data:text/html,<body><button>Click me</button></body>"></iframe>
+
+<p>After</p>
+
+<p>End of test</p>
+
+<p id="description"></p>
+<div id="console"></div>
+
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/accessibility/deleting-iframe-destroys-axcache-expected.txt b/LayoutTests/platform/mac/accessibility/deleting-iframe-destroys-axcache-expected.txt
new file mode 100644
index 0000000..5a36718
--- /dev/null
+++ b/LayoutTests/platform/mac/accessibility/deleting-iframe-destroys-axcache-expected.txt
@@ -0,0 +1,47 @@
+Before
+
+After
+
+End of test
+
+This tests that deleting an iframe doesn't cause the accessibility cache to be destroyed and recreated.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Before:
+AXRole: AXScrollArea 
+    AXRole: AXWebArea AXValue: 
+        AXRole: AXGroup AXValue: 
+            AXRole: AXStaticText AXValue: Before
+        AXRole: AXGroup AXValue: 
+            AXRole: AXScrollArea 
+                AXRole: AXWebArea AXValue: 
+                    AXRole: AXGroup AXValue: 
+                        AXRole: AXButton AXValue: 
+        AXRole: AXGroup AXValue: 
+            AXRole: AXStaticText AXValue: After
+        AXRole: AXGroup AXValue: 
+            AXRole: AXStaticText AXValue: End of test
+
+After:
+AXRole: AXScrollArea 
+    AXRole: AXWebArea AXValue: 
+        AXRole: AXGroup AXValue: 
+            AXRole: AXStaticText AXValue: Before
+        AXRole: AXGroup AXValue: 
+            AXRole: AXStaticText AXValue: After
+        AXRole: AXGroup AXValue: 
+            AXRole: AXStaticText AXValue: End of test
+
+PASS frameBodyRole == frameBody.role is false
+PASS frameGroupRole == frameGroup.role is false
+PASS frameButtonRole == frameButton.role is false
+PASS root.isEqual(newRoot) is true
+PASS body.isEqual(newBody) is true
+PASS before.isEqual(newBefore) is true
+PASS after.isEqual(newAfter) is true
+
+TEST COMPLETE
+
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 5ca35ed..a9ed907 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,16 @@
+2011-09-27  Dominic Mazzoni  <dmazzoni@google.com>
+
+        AXObjectCache cleared unnecessarily when non-top Document is detached.
+        https://bugs.webkit.org/show_bug.cgi?id=68636
+
+        Reviewed by Chris Fleizach.
+
+        Test: accessibility/deleting-iframe-destroys-axcache.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::attach):
+        (WebCore::Document::detach):
+
 2011-09-27  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r96108, r96111, r96113, and r96116.
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index aec22b0..1483cf0 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -1801,7 +1801,7 @@
 {
     ASSERT(!attached());
     ASSERT(!m_inPageCache);
-    ASSERT(!m_axObjectCache);
+    ASSERT(!m_axObjectCache || this != topDocument());
 
     if (!m_renderArena)
         m_renderArena = adoptPtr(new RenderArena);
@@ -1827,7 +1827,9 @@
     ASSERT(attached());
     ASSERT(!m_inPageCache);
 
-    clearAXObjectCache();
+    if (this == topDocument())
+        clearAXObjectCache();
+
     stopActiveDOMObjects();
     m_eventQueue->close();
 #if ENABLE(FULLSCREEN_API)