Bug 707654 - embeds relation on root accessible can return not content document, r=davidb
authorAlexander Surkov <surkov.alexander@gmail.com>
Tue, 31 Jan 2012 15:40:06 +0900
changeset 87045 c75743aa5bcef7738a5869d7e4bd379b92d24cdf
parent 87044 3e14b079b2306333da0ddd7b2fdab9ae5efadab7
child 87046 5a8ff4828791d9aa2d487b0902db8ef9764fe548
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdavidb
bugs707654
milestone12.0a1
Bug 707654 - embeds relation on root accessible can return not content document, r=davidb
accessible/src/base/nsRootAccessible.cpp
accessible/src/base/nsRootAccessible.h
accessible/tests/mochitest/relations/Makefile.in
accessible/tests/mochitest/relations/test_embeds.xul
accessible/tests/mochitest/relations/test_general.html
accessible/tests/mochitest/relations/test_general.xul
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -569,84 +569,42 @@ nsRootAccessible::Shutdown()
 {
   // Called manually or by nsAccessNode::LastRelease()
   if (!mWeakShell)
     return;  // Already shutdown
 
   nsDocAccessibleWrap::Shutdown();
 }
 
-// nsRootAccessible protected member
-already_AddRefed<nsIDocShellTreeItem>
-nsRootAccessible::GetContentDocShell(nsIDocShellTreeItem *aStart)
-{
-  if (!aStart) {
-    return nsnull;
-  }
-
-  PRInt32 itemType;
-  aStart->GetItemType(&itemType);
-  if (itemType == nsIDocShellTreeItem::typeContent) {
-    nsDocAccessible *accDoc = nsAccUtils::GetDocAccessibleFor(aStart);
-
-    // Hidden documents don't have accessibles (like SeaMonkey's sidebar),
-    // they are of no interest for a11y.
-    if (!accDoc)
-      return nsnull;
-
-    // If ancestor chain of accessibles is not completely visible,
-    // don't use this one. This happens for example if it's inside
-    // a background tab (tabbed browsing)
-    nsAccessible* parent = accDoc->Parent();
-    while (parent) {
-      if (parent->State() & states::INVISIBLE)
-        return nsnull;
-
-      if (parent == this)
-        break; // Don't check past original root accessible we started with
-
-      parent = parent->Parent();
-    }
-
-    NS_ADDREF(aStart);
-    return aStart;
-  }
-  nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aStart));
-  if (treeNode) {
-    PRInt32 subDocuments;
-    treeNode->GetChildCount(&subDocuments);
-    for (PRInt32 count = 0; count < subDocuments; count ++) {
-      nsCOMPtr<nsIDocShellTreeItem> treeItemChild, contentTreeItem;
-      treeNode->GetChildAt(count, getter_AddRefs(treeItemChild));
-      NS_ENSURE_TRUE(treeItemChild, nsnull);
-      contentTreeItem = GetContentDocShell(treeItemChild);
-      if (contentTreeItem) {
-        NS_ADDREF(aStart = contentTreeItem);
-        return aStart;
-      }
-    }
-  }
-  return nsnull;
-}
-
 // nsIAccessible method
 Relation
 nsRootAccessible::RelationByType(PRUint32 aType)
 {
   if (!mDocument || aType != nsIAccessibleRelation::RELATION_EMBEDS)
     return nsDocAccessibleWrap::RelationByType(aType);
 
-  nsCOMPtr<nsIDocShellTreeItem> treeItem =
-    nsCoreUtils::GetDocShellTreeItemFor(mDocument);
-  nsCOMPtr<nsIDocShellTreeItem> contentTreeItem = GetContentDocShell(treeItem);
-  // there may be no content area, so we need a null check
-  if (!contentTreeItem)
-    return Relation();
+  nsIDOMWindow* rootWindow = mDocument->GetWindow();
+  if (rootWindow) {
+    nsCOMPtr<nsIDOMWindow> contentWindow;
+    rootWindow->GetContent(getter_AddRefs(contentWindow));
+    if (contentWindow) {
+      nsCOMPtr<nsIDOMDocument> contentDOMDocument;
+      contentWindow->GetDocument(getter_AddRefs(contentDOMDocument));
+      nsCOMPtr<nsIDocument> contentDocumentNode =
+        do_QueryInterface(contentDOMDocument);
+      if (contentDocumentNode) {
+        nsDocAccessible* contentDocument =
+          GetAccService()->GetDocAccessible(contentDocumentNode);
+        if (contentDocument)
+          return Relation(contentDocument);
+      }
+    }
+  }
 
-  return Relation(nsAccUtils::GetDocAccessibleFor(contentTreeItem));
+  return Relation();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Protected members
 
 void
 nsRootAccessible::HandlePopupShownEvent(nsAccessible* aAccessible)
 {
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -122,18 +122,17 @@ protected:
 #ifdef MOZ_XUL
     void HandleTreeRowCountChangedEvent(nsIDOMEvent* aEvent,
                                         nsXULTreeAccessible* aAccessible);
     void HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
                                     nsXULTreeAccessible* aAccessible);
 
     PRUint32 GetChromeFlags();
 #endif
-    already_AddRefed<nsIDocShellTreeItem>
-           GetContentDocShell(nsIDocShellTreeItem *aStart);
+
     nsRefPtr<nsCaretAccessible> mCaretAccessible;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsRootAccessible, NS_ROOTACCESSIBLE_IMPL_CID)
 
 inline nsRootAccessible*
 nsAccessible::AsRoot()
 {
--- a/accessible/tests/mochitest/relations/Makefile.in
+++ b/accessible/tests/mochitest/relations/Makefile.in
@@ -43,16 +43,17 @@ VPATH		= @srcdir@
 relativesrcdir  = accessible/relations
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 # test_tabbrowser.xul disabled for misusing <tabbrowser> (bug 715857)
 
 _TEST_FILES =\
+		test_embeds.xul \
 		test_general.html \
 		test_general.xul \
 		test_tree.xul \
 		test_update.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/relations/test_embeds.xul
@@ -0,0 +1,152 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Embeds relation tests">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../role.js"></script>
+  <script type="application/javascript"
+          src="../states.js"></script>
+  <script type="application/javascript"
+          src="../events.js"></script>
+  <script type="application/javascript"
+          src="../relations.js"></script>
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Helpers
+
+    function tabBrowser()
+    {
+      return gBrowserWnd.gBrowser;
+    }
+
+    function currentBrowser()
+    {
+      return tabBrowser().selectedBrowser;
+    }
+
+    function currentTabDocument()
+    {
+      return currentBrowser().contentDocument;
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function loadURI(aURI)
+    {
+      this.invoke = function loadURI_invoke()
+      {
+        tabBrowser().loadURI(aURI);
+      }
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, currentBrowser)
+      ];
+
+      this.finalCheck = function loadURI_finalCheck()
+      {
+        testRelation(gBrowserWnd.document, RELATION_EMBEDS,
+                     getAccessible(currentTabDocument()));
+      }
+
+      this.getID = function loadURI_getID()
+      {
+        return "load uri " + aURI;
+      }
+    }
+
+    function loadOneTab(aURI)
+    {
+      this.invoke = function loadOneTab_invoke()
+      {
+        tabBrowser().loadOneTab(aURI, null, null, null, false);
+      }
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, currentBrowser)
+      ];
+
+      this.finalCheck = function loadURI_finalCheck()
+      {
+        testRelation(gBrowserWnd.document, RELATION_EMBEDS,
+                     getAccessible(currentTabDocument()));
+      }
+
+      this.getID = function loadOneTab_getID()
+      {
+        return "load uri '" + aURI + "' in new tab";
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Testing
+
+    var gBrowserWnd = null;
+    function loadBrowser()
+    {
+      gBrowserWnd = window.openDialog("chrome://browser/content/", "_blank",
+                                      "chrome,all,dialog=no", "about:");
+
+      addA11yLoadEvent(startTests, gBrowserWnd);
+    }
+
+    function startTests()
+    {
+      // Wait for tab load.
+      var browser = currentBrowser();
+      addA11yLoadEvent(doTests, browser.contentWindow);
+    }
+
+    //gA11yEventDumpToConsole = true; // debug
+
+    var gQueue = null;
+    function doTests()
+    {
+      testRelation(gBrowserWnd.document, RELATION_EMBEDS,
+                   getAccessible(currentTabDocument()));
+
+      gQueue = new eventQueue();
+
+      gQueue.push(new loadURI("about:about"));
+      gQueue.push(new loadOneTab("about:mozilla"));
+
+      gQueue.onFinish = function()
+      {
+        gBrowserWnd.close();
+      }
+      gQueue.invoke();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addLoadEvent(loadBrowser);
+  ]]>
+  </script>
+
+  <vbox flex="1" style="overflow: auto;">
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=707654"
+       title="Embeds relation on root accessible can return not content document">
+      Mozilla Bug 707654
+    </a>
+    <p id="display"></p>
+    <div id="content" style="display: none">
+    </div>
+    <pre id="test">
+    </pre>
+  </body>
+  </vbox>
+</window>
--- a/accessible/tests/mochitest/relations/test_general.html
+++ b/accessible/tests/mochitest/relations/test_general.html
@@ -121,29 +121,16 @@
       testRelation("caption", RELATION_LABEL_FOR, "table");
       testRelation("table", RELATION_LABELLED_BY, "caption");
 
       // 'labelled by'/'label for' relation for html:fieldset and
       // html:legend
       testRelation("legend", RELATION_LABEL_FOR, "fieldset");
       testRelation("fieldset", RELATION_LABELLED_BY, "legend");
 
-      // 'embeds' relation for root accessible
-      var docAcc = null;
-      var parentOfDocAcc = null;
-      var parentDocAcc = getAccessible(document);
-      do {
-        docAcc = parentDocAcc;
-        parentOfDocAcc = getAccessible(docAcc.parent, [nsIAccessNode]);
-        parentDocAcc = getAccessible(parentOfDocAcc.document,
-                                     [nsIAccessible]);
-      } while (getRole(parentDocAcc) != ROLE_CHROME_WINDOW)
-
-      testRelation(parentDocAcc, RELATION_EMBEDS, docAcc);
-
       // finish test
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 
--- a/accessible/tests/mochitest/relations/test_general.xul
+++ b/accessible/tests/mochitest/relations/test_general.xul
@@ -98,29 +98,16 @@
       // aria-flowto, multiple relations
       testRelation("flowto1", RELATION_FLOWS_TO, ["flowfrom1", "flowfrom2"]);
       testRelation("flowfrom1", RELATION_FLOWS_FROM, "flowto1");
       testRelation("flowfrom2", RELATION_FLOWS_FROM, "flowto1");
 
       // 'default button' relation
       testRelation("textbox", RELATION_DEFAULT_BUTTON, "submit");
 
-      // 'embeds' relation for root accessible
-      var docAcc = null;
-      var parentOfDocAcc = null;
-      var parentDocAcc = getAccessible(document);
-      do {
-        docAcc = parentDocAcc;
-        parentOfDocAcc = getAccessible(docAcc.parent, [nsIAccessNode]);
-        parentDocAcc = getAccessible(parentOfDocAcc.document,
-                                     [nsIAccessible]);
-      } while (getRole(parentDocAcc) != ROLE_CHROME_WINDOW)
-
-      testRelation(parentDocAcc, RELATION_EMBEDS, docAcc);
-
       // 'labelled by'/'label for' relation for xul:goupbox and xul:label of
       // xul:caption
       var groupboxAcc = getAccessible("groupbox");
       var labelAcc = groupboxAcc.firstChild;
       testRelation(labelAcc, RELATION_LABEL_FOR, groupboxAcc);
       testRelation(groupboxAcc, RELATION_LABELLED_BY, labelAcc);
 
       // 'labelled by'/'label for' relations for xul:tab and xul:tabpanel