diff --git a/accessible/src/html/nsHyperTextAccessible.cpp b/accessible/src/html/nsHyperTextAccessible.cpp index 3846dfd87ee8..371701cb2ef6 100644 --- a/accessible/src/html/nsHyperTextAccessible.cpp +++ b/accessible/src/html/nsHyperTextAccessible.cpp @@ -735,6 +735,30 @@ nsHyperTextAccessible::HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset, NS_ENSURE_ARG_POINTER(aEndOffset); *aEndOffset = -1; + // If the given offsets are 0 and associated editor is empty then return + // collapsed range with editor root element as range container. + if (aStartHTOffset == 0 && aEndHTOffset == 0) { + nsCOMPtr editor; + GetAssociatedEditor(getter_AddRefs(editor)); + if (editor) { + PRBool isEmpty = PR_FALSE; + editor->GetDocumentIsEmpty(&isEmpty); + if (isEmpty) { + nsCOMPtr editorRootElm; + editor->GetRootElement(getter_AddRefs(editorRootElm)); + + nsCOMPtr editorRoot(do_QueryInterface(editorRootElm)); + if (editorRoot) { + *aStartOffset = *aEndOffset = 0; + NS_ADDREF(*aStartNode = editorRoot); + NS_ADDREF(*aEndNode = editorRoot); + + return NS_OK; + } + } + } + } + nsCOMPtr startAcc, endAcc; PRInt32 startOffset = aStartHTOffset, endOffset = aEndHTOffset; nsIFrame *startFrame = nsnull, *endFrame = nsnull; diff --git a/accessible/tests/mochitest/Makefile.in b/accessible/tests/mochitest/Makefile.in index 716e74f688f2..1d48dd75b11f 100644 --- a/accessible/tests/mochitest/Makefile.in +++ b/accessible/tests/mochitest/Makefile.in @@ -48,9 +48,11 @@ include $(topsrcdir)/config/rules.mk _TEST_FILES =\ moz.png \ longdesc_src.html \ + common.js \ nsIAccessible_actions.js \ nsIAccessible_name.css \ nsIAccessible_name.xbl \ + nsIAccessibleEditableText.js \ test_aria_activedescendant.html \ test_aria_role_article.html \ test_bug368835.xul \ @@ -62,16 +64,17 @@ _TEST_FILES =\ test_nsIAccessible_actions.xul \ test_nsIAccessible_name.html \ test_nsIAccessible_name.xul \ + test_nsIAccessibleDocument.html \ + test_nsIAccessibleEditableText.html \ + test_nsIAccessibleHyperLink.html \ + test_nsIAccessibleHyperLink.xul \ + test_nsIAccessibleHyperText.html \ + test_nsIAccessibleImage.html \ test_nsIAccessibleTable_1.html \ test_nsIAccessibleTable_2.html \ test_nsIAccessibleTable_3.html \ test_nsIAccessibleTable_4.html \ test_nsIAccessibleTable_listboxes.xul \ - test_nsIAccessibleDocument.html \ - test_nsIAccessibleHyperLink.html \ - test_nsIAccessibleHyperLink.xul \ - test_nsIAccessibleHyperText.html \ - test_nsIAccessibleImage.html \ test_nsOuterDocAccessible.html \ test_textattrs.html \ test_textboxes.html \ diff --git a/accessible/tests/mochitest/common.js b/accessible/tests/mochitest/common.js new file mode 100644 index 000000000000..2c08774fb127 --- /dev/null +++ b/accessible/tests/mochitest/common.js @@ -0,0 +1,118 @@ +//////////////////////////////////////////////////////////////////////////////// +// Interfaces + +const nsIAccessibleRetrieval = Components.interfaces.nsIAccessibleRetrieval; + +const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent; +const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates; +const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole; +const nsIAccessibleTypes = Components.interfaces.nsIAccessibleTypes; + +const nsIAccessibleRelation = Components.interfaces.nsIAccessibleRelation; + +const nsIAccessNode = Components.interfaces.nsIAccessNode; +const nsIAccessible = Components.interfaces.nsIAccessible; + +const nsIAccessibleDocument = Components.interfaces.nsIAccessibleDocument; + +const nsIAccessibleText = Components.interfaces.nsIAccessibleText; +const nsIAccessibleEditableText = Components.interfaces.nsIAccessibleEditableText; + +const nsIAccessibleHyperLink = Components.interfaces.nsIAccessibleHyperLink; +const nsIAccessibleHyperText = Components.interfaces.nsIAccessibleHyperText; + +const nsIAccessibleImage = Components.interfaces.nsIAccessibleImage; +const nsIAccessibleSelectable = Components.interfaces.nsIAccessibleSelectable; +const nsIAccessibleTable = Components.interfaces.nsIAccessibleTable; +const nsIAccessibleValue = Components.interfaces.nsIAccessibleValue; + +const nsIObserverService = Components.interfaces.nsIObserverService; + +const nsIDOMNode = Components.interfaces.nsIDOMNode; + +//////////////////////////////////////////////////////////////////////////////// +// General + +/** + * nsIAccessibleRetrieval, initialized when test is loaded. + */ +var gAccRetrieval = null; + +/** + * Return accessible for the given ID attribute or DOM element. + * + * @param aElmOrID [in] the ID attribute or DOM element to get an accessible + * for + * @param aInterfaces [in, optional] the accessible interface or the array of + * accessible interfaces to query it/them from obtained + * accessible + * @param aElmObj [out, optional] object to store DOM element which + * accessible is created for + */ +function getAccessible(aElmOrID, aInterfaces, aElmObj) +{ + var elm = null; + + if (aElmOrID instanceof nsIDOMNode) { + elm = aElmOrID; + } else { + var elm = document.getElementById(aElmOrID); + if (!elm) { + ok(false, "Can't get DOM element for " + aID); + return null; + } + } + + if (aElmObj && (typeof aElmObj == "object")) + aElmObj.value = elm; + + var acc = null; + try { + acc = gAccRetrieval.getAccessibleFor(elm); + } catch (e) { + } + + if (!acc) { + ok(false, "Can't get accessible for " + aID); + return null; + } + + if (!aInterfaces) + return acc; + + if (aInterfaces instanceof Array) { + for (var index = 0; index < aInterfaces.length; index++) { + try { + acc.QueryInterface(aInterfaces[index]); + } catch (e) { + ok(false, "Can't query " + aInterfaces[index] + " for " + aID); + return null; + } + } + return acc; + } + + try { + acc.QueryInterface(aInterfaces); + } catch (e) { + ok(false, "Can't query " + aInterfaces + " for " + aID); + return null; + } + + return acc; +} + +//////////////////////////////////////////////////////////////////////////////// +// Private +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// General + +function initialize() +{ + gAccRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"]. + getService(nsIAccessibleRetrieval); +} + +addLoadEvent(initialize); diff --git a/accessible/tests/mochitest/nsIAccessibleEditableText.js b/accessible/tests/mochitest/nsIAccessibleEditableText.js new file mode 100644 index 000000000000..52ea3d4fab0d --- /dev/null +++ b/accessible/tests/mochitest/nsIAccessibleEditableText.js @@ -0,0 +1,105 @@ +function nsEditableText(aElmOrID) +{ + this.setTextContents = function setTextContents(aStr) + { + try { + this.mAcc.setTextContents(aStr); + + is(this.getValue(), aStr, + "setTextContents: Can't set " + aStr + + " to element with ID '" + this.mID + "'"); + } catch (e) { + ok(false, + "setTextContents: Can't set " + aStr + + "to element with ID '" + this.mID + + "', value '" + this.getValue() + "', exception" + e); + } + } + + this.insertText = function insertText(aStr, aPos, aResStr) + { + try { + this.mAcc.insertText(aStr, aPos); + + is(this.getValue(), aResStr, + "insertText: Can't insert " + aStr + " at " + aPos + + " to element with ID '" + this.mID + "'"); + } catch (e) { + ok(false, + "insertText: Can't insert " + aStr + " at " + aPos + + " to element with ID '" + this.mID + + "', value '" + this.getValue() + "', exception " + e); + } + } + + this.copyNPasteText = function copyNPasteText(aStartPos, aEndPos, + aPos, aResStr) + { + try { + this.mAcc.copyText(aStartPos, aEndPos); + this.mAcc.pasteText(aPos); + + is(this.getValue(), aResStr, + "copyText & pasteText: Can't copy text from " + aStartPos + + " to " + aEndPos + " and paste to " + aPos + + " for element with ID '" + this.mID + "'"); + } catch (e) { + ok(false, + "copyText & pasteText: Can't copy text from " + aStartPos + + " to " + aEndPos + " and paste to " + aPos + + " for element with ID '" + this.mID + + "', value '" + this.getValue() + "', exception " + e); + } + } + + this.cutNPasteText = function copyNPasteText(aStartPos, aEndPos, + aPos, aResStr) + { + try { + this.mAcc.cutText(aStartPos, aEndPos); + this.mAcc.pasteText(aPos); + + is(this.getValue(), aResStr, + "cutText & pasteText: Can't cut text from " + aStartPos + + " to " + aEndPos + " and paste to " + aPos + + " for element with ID '" + this.mID + "'"); + } catch (e) { + ok(false, + "cutText & pasteText: Can't cut text from " + aStartPos + + " to " + aEndPos + " and paste to " + aPos + + " for element with ID '" + this.mID + + "', value '" + this.getValue() + "', exception " + e); + } + } + + this.deleteText = function deleteText(aStartPos, aEndPos, aResStr) + { + try { + this.mAcc.deleteText(aStartPos, aEndPos); + + is(this.getValue(), aResStr, + "deleteText: Can't delete text from " + aStartPos + + " to " + aEndPos + " for element with ID '" + this.mID + "'"); + } catch (e) { + ok(false, + "deleteText: Can't delete text from " + aStartPos + + " to " + aEndPos + " for element with ID '" + this.mID + + "', value " + this.getValue() + ", exception " + e); + } + } + + this.getValue = function getValue() + { + if (this.mElm instanceof Components.interfaces.nsIDOMNSEditableElement) + return this.mElm.value; + if (this.mElm instanceof Components.interfaces.nsIDOMHTMLDocument) + return this.mElm.body.textContent; + return this.mElm.textContent; + } + + var elmObj = { value: null }; + this.mAcc = getAccessible(aElmOrID, nsIAccessibleEditableText, elmObj); + + this.mElm = elmObj.value; + this.mID = aElmOrID; +} diff --git a/accessible/tests/mochitest/test_nsIAccessibleEditableText.html b/accessible/tests/mochitest/test_nsIAccessibleEditableText.html new file mode 100644 index 000000000000..d5c69f317bdf --- /dev/null +++ b/accessible/tests/mochitest/test_nsIAccessibleEditableText.html @@ -0,0 +1,95 @@ + + + + + nsIAccessibleEditableText chrome tests + + + + + + + + + + + + Mozilla Bug 452161 +

+ +
+  
+ + + +
+ +