Bug 638106 - CKEditor document should be editable, r=davidb, a=final+
authorAlexander Surkov <surkov.alexander@gmail.com>
Thu, 03 Mar 2011 14:41:46 +0800
changeset 63310 7570423a050f
parent 63309 c046188bb2f9
child 63311 f76fac273005
push idunknown
push userunknown
push dateunknown
reviewersdavidb, final
bugs638106
milestone2.0b13pre
Bug 638106 - CKEditor document should be editable, r=davidb, a=final+
accessible/src/base/NotificationController.cpp
accessible/src/base/nsDocAccessible.cpp
accessible/src/msaa/nsDocAccessibleWrap.cpp
accessible/tests/mochitest/states.js
accessible/tests/mochitest/states/Makefile.in
accessible/tests/mochitest/states/test_doc.html
accessible/tests/mochitest/states/test_frames.html
accessible/tests/mochitest/states/z_frames_update.html
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -214,19 +214,18 @@ NotificationController::WillRefresh(mozi
       return;
 
 #ifdef DEBUG_NOTIFICATIONS
     printf("\ninitial tree created, document: %p, document node: %p\n",
            mDocument.get(), mDocument->GetDocumentNode());
 #endif
 
     mTreeConstructedState = eTreeConstructed;
-    mDocument->CacheChildrenInSubtree(mDocument);
+    mDocument->NotifyOfInitialUpdate();
 
-    mDocument->NotifyOfInitialUpdate();
     NS_ASSERTION(mContentInsertions.Length() == 0,
                  "Pending content insertions while initial accessible tree isn't created!");
   }
 
   // Process content inserted notifications to update the tree. Process other
   // notifications like DOM events and then flush event queue. If any new
   // notifications are queued during this processing then they will be processed
   // on next refresh. If notification processing queues up new events then they
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1498,16 +1498,25 @@ nsDocAccessible::CacheChildren()
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Protected members
 
 void
 nsDocAccessible::NotifyOfInitialUpdate()
 {
+  // The content element may be changed before the initial update and then we
+  // miss the notification (since content tree change notifications are ignored
+  // prior to initial update). Make sure the content element is valid.
+  nsIContent* contentElm = nsCoreUtils::GetRoleContent(mDocument);
+  if (contentElm && mContent != contentElm)
+    mContent = contentElm;
+
+  // Build initial tree.
+  CacheChildrenInSubtree(this);
 }
 
 void
 nsDocAccessible::AddDependentIDsFor(nsAccessible* aRelProvider,
                                     nsIAtom* aRelAttr)
 {
   for (PRUint32 idx = 0; idx < kRelationAttrsLen; idx++) {
     nsIAtom* relAttr = *kRelationAttrs[idx];
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -278,16 +278,18 @@ nsDocAccessibleWrap::GetNativeWindow() c
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsDocAccessible protected
 
 void
 nsDocAccessibleWrap::NotifyOfInitialUpdate()
 {
+  nsDocAccessible::NotifyOfInitialUpdate();
+
   if (nsWinUtils::IsWindowEmulationEnabled()) {
     // Create window for tab document.
     if (nsWinUtils::IsTabDocument(mDocument)) {
       nsRootAccessible* rootDocument = RootAccessible();
 
       PRBool isActive = PR_TRUE;
       PRInt32 x = CW_USEDEFAULT, y = CW_USEDEFAULT, width = 0, height = 0;
       if (nsWinUtils::IsWindowEmulationEnabled(kDolphinModuleHandle)) {
--- a/accessible/tests/mochitest/states.js
+++ b/accessible/tests/mochitest/states.js
@@ -54,23 +54,24 @@ const EXT_STATE_VERTICAL = nsIAccessible
  * In addition, the function performs a few plausibility checks derived from the
  * sstates and extra states passed in.
  *
  * @param aAccOrElmOrID      The accessible, DOM element or ID to be tested.
  * @param aState             The state bits that are wanted.
  * @param aExtraState        The extra state bits that are wanted.
  * @param aAbsentState       State bits that are not wanted.
  * @param aAbsentExtraState  Extra state bits that are not wanted.
+ * @param aTestName          The test name.
  */
 function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
-                    aAbsentExtraState)
+                    aAbsentExtraState, aTestName)
 {
   var [state, extraState] = getStates(aAccOrElmOrID);
 
-  var id = prettyName(aAccOrElmOrID);
+  var id = prettyName(aAccOrElmOrID) + (aTestName ? " [" + aTestName + "]": "");
 
   // Primary test.
   isState(state & aState, aState, false,
           "wrong state bits for " + id + "!");
 
   if (aExtraState)
     isState(extraState & aExtraState, aExtraState, true,
             "wrong extra state bits for " + id + "!");
--- a/accessible/tests/mochitest/states/Makefile.in
+++ b/accessible/tests/mochitest/states/Makefile.in
@@ -40,30 +40,29 @@ DEPTH		= ../../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible/states
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
-# temporarily disabled test (bug 562328)
-#  test_frames.html \
-
 _TEST_FILES =\
 		test_aria.html \
 		test_aria_imgmap.html \
 		test_doc.html \
 		test_docarticle.html \
 		test_editablebody.html \
+		test_frames.html \
 		test_inputs.html \
 		test_inputs.xul \
 		test_link.html \
 		test_popup.xul \
 		test_tree.xul \
 		z_frames.html \
 		z_frames_article.html \
 		z_frames_checkbox.html \
 		z_frames_textbox.html \
+		z_frames_update.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
--- a/accessible/tests/mochitest/states/test_doc.html
+++ b/accessible/tests/mochitest/states/test_doc.html
@@ -79,10 +79,11 @@
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <p id="p">hello</p>
 
   <div id="document" role="document">document</div>
   <div id="editable_document" role="document" contentEditable="true">editable document</doc>
+
 </body>
 </html>
--- a/accessible/tests/mochitest/states/test_frames.html
+++ b/accessible/tests/mochitest/states/test_frames.html
@@ -18,52 +18,65 @@
 
   <script type="application/javascript">
     function doTest()
     {
       frameDoc = document.getElementById("frame_doc").contentDocument;
       frameDocArticle = document.getElementById("frame_doc_article").contentDocument;
       frameDocCheckbox = document.getElementById("frame_doc_checkbox").contentDocument;
       frameDocTextbox = document.getElementById("frame_doc_textbox").contentDocument;
-      
-      testStates(frameDoc, STATE_READONLY);
-      testStates(frameDocArticle, STATE_READONLY);
-      testStates(frameDocCheckbox, 0, 0, STATE_READONLY);
-      testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE);
+
+      testStates(frameDoc, STATE_READONLY, 0, 0, 0, "test1: frameDoc");
+      testStates(frameDocArticle, STATE_READONLY, 0, 0, 0, "test1: frameDocArticle");
+      testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test1: frameDocCheckbox");
+      testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, 0, 0, "test1: frameDocTextbox");
 
       frameDoc.designMode = "on";
-      testStates(frameDoc,  0, EXT_STATE_EDITABLE);
-      testStates(frameDocArticle, STATE_READONLY);
-      testStates(frameDocCheckbox, 0, 0, STATE_READONLY);
-      testStates(frameDocTextbox,  0, EXT_STATE_EDITABLE);
+      testStates(frameDoc,  0, EXT_STATE_EDITABLE, 0, 0, "test2: frameDoc");
+      testStates(frameDocArticle, STATE_READONLY, 0, 0, 0, "test2: frameDocArticle");
+      testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test2: frameDocCheckbox");
+      testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, 0, 0, "test2: frameDocTextbox");
 
       frameDocArticle.designMode = "on";
-      testStates(frameDocArticle, 0, EXT_STATE_EDITABLE);
+      testStates(frameDocArticle, 0, EXT_STATE_EDITABLE, 0, 0, "test3: frameDocArticle");
 
       frameDocCheckbox.designMode = "on";
-      testStates(frameDocCheckbox, 0, 0, STATE_READONLY);
-      
+      testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test4: frameDocCheckbox");
+
+      // Replace iframe document body before the document accessible tree is
+      // created. Check the states are updated for new body.
+      var frameUpdateDoc =
+        document.getElementById("frame_updatedoc").contentDocument;
+      testStates(frameUpdateDoc, 0, EXT_STATE_EDITABLE,
+                 STATE_READONLY, EXT_STATE_STALE, "test5: frameUpdateDoc");
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 
 <body>
 
   <a target="_blank"
-    href="https://bugzilla.mozilla.org/show_bug.cgi?id=467387"
-    title="Expose non-editable documents as readonly, regardless of role">
-     Mozilla Bug 467387
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=467387"
+     title="Expose non-editable documents as readonly, regardless of role">
+    Mozilla Bug 467387
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=638106"
+     title="CKEditor document should be editable">
+    Mozilla Bug 638106
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
-  
+
   <iframe id="frame_doc" src="z_frames.html"></iframe>
   <iframe id="frame_doc_article" src="z_frames_article.html"></iframe>
   <iframe id="frame_doc_checkbox" src="z_frames_checkbox.html"></iframe>
   <iframe id="frame_doc_textbox" src="z_frames_textbox.html"></iframe>
+  <iframe id="frame_updatedoc" src="z_frames_update.html"></iframe>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/states/z_frames_update.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<script>
+function replaceBody()
+{
+  var accRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+    getService(Components.interfaces.nsIAccessibleRetrieval);
+  accRetrieval.getAccessibleFor(document);
+
+  var newBody = document.createElement("body");
+  newBody.setAttribute("contentEditable", "true");
+  newBody.textContent = "New Hello";
+  document.documentElement.replaceChild(newBody, document.body);
+  getComputedStyle(newBody, "").color;
+}
+</script>
+</head>
+<body onload="replaceBody();">
+OLD hello
+</body>
+</html>
+