Bug 452161 – pyatspi insertText doesn't work in empty textboxes, r=aaronlev, MarcoZ

This commit is contained in:
Alexander Surkov 2008-08-28 22:48:41 +08:00
parent 151a371207
commit f9c6f47571
5 changed files with 350 additions and 5 deletions

View File

@ -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<nsIEditor> editor;
GetAssociatedEditor(getter_AddRefs(editor));
if (editor) {
PRBool isEmpty = PR_FALSE;
editor->GetDocumentIsEmpty(&isEmpty);
if (isEmpty) {
nsCOMPtr<nsIDOMElement> editorRootElm;
editor->GetRootElement(getter_AddRefs(editorRootElm));
nsCOMPtr<nsIDOMNode> editorRoot(do_QueryInterface(editorRootElm));
if (editorRoot) {
*aStartOffset = *aEndOffset = 0;
NS_ADDREF(*aStartNode = editorRoot);
NS_ADDREF(*aEndNode = editorRoot);
return NS_OK;
}
}
}
}
nsCOMPtr<nsIAccessible> startAcc, endAcc;
PRInt32 startOffset = aStartHTOffset, endOffset = aEndHTOffset;
nsIFrame *startFrame = nsnull, *endFrame = nsnull;

View File

@ -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 \

View File

@ -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);

View File

@ -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;
}

View File

@ -0,0 +1,95 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=452161
-->
<head>
<title>nsIAccessibleEditableText chrome tests</title>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/common.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/a11y/accessible/nsIAccessibleEditableText.js"></script>
<script type="application/javascript">
var gParagraphAcc;
function testEditable(aID)
{
var et = new nsEditableText(aID);
//////////////////////////////////////////////////////////////////////////
// insertText
et.insertText("hello", 0, "hello");
et.insertText("ma ", 0, "ma hello");
et.insertText("ma", 2, "mama hello");
et.insertText(" hello", 10, "mama hello hello");
// XXX: bug 452584
//////////////////////////////////////////////////////////////////////////
// setTextContents
// et.setTextContents("hello", "hello");
// et.setTextContents("olleh", "olleh");
// et.setTextContents("", "");
//////////////////////////////////////////////////////////////////////////
// deleteText
// et.deleteText(0, 5, "hello hello");
// et.deleteText(5, 6, "hellohello");
// et.deleteText(5, 10, "hello");
// et.deleteText(0, 5, "");
//////////////////////////////////////////////////////////////////////////
// copyNPasteText
// et.copyNPasteText(0, 0, 0, "");
// et.insertText("hello", 0, "hello");
// et.copyNPasteText(0, 1, 0, "hhello");
// et.copyNPasteText(5, 6, 6, "hhelloo");
// et.copyNPasteText(3, 4, 1, "hehelloo");
//////////////////////////////////////////////////////////////////////////
// // cutNPasteText
// et.cutNPasteText(0, 1, 1, "ehhelloo");
// et.cutNPasteText(1, 2, 0, "hehelloo");
// et.cutNPasteText(7, 8, 8, "hehelloo");
}
function doTest()
{
testEditable("input");
// testEditable("div"); XXX: bug 452599
var frame = document.getElementById("frame");
frame.contentDocument.designMode = "on";
testEditable(frame.contentDocument);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
title="nsIAccessibleEditableText chrome tests"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=452161">Mozilla Bug 452161</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<input id="input"/>
<div id="div" contentEditable="true"/>
<iframe id="frame"/>
</body>
</html>