зеркало из https://github.com/mozilla/gecko-dev.git
Bug 606082 - update accessible tree when root element is changed, r=marcoz, davidb, bz, a=blocking
This commit is contained in:
Родитель
c22068623c
Коммит
a015a8fcc2
|
@ -156,7 +156,7 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual nsINode* GetNode() const { return mContent; }
|
virtual nsINode* GetNode() const { return mContent; }
|
||||||
nsIContent* GetContent() const { return mContent; }
|
nsIContent* GetContent() const { return mContent; }
|
||||||
nsIDocument* GetDocumentNode() const
|
virtual nsIDocument* GetDocumentNode() const
|
||||||
{ return mContent ? mContent->GetOwnerDoc() : nsnull; }
|
{ return mContent ? mContent->GetOwnerDoc() : nsnull; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -477,55 +477,69 @@ nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
|
||||||
nsIContent* aStartChild,
|
nsIContent* aStartChild,
|
||||||
nsIContent* aEndChild)
|
nsIContent* aEndChild)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_A11Y
|
#ifdef DEBUG_CONTENTMUTATION
|
||||||
nsAutoString tag;
|
nsAutoString tag;
|
||||||
aStartChild->Tag()->ToString(tag);
|
aStartChild->Tag()->ToString(tag);
|
||||||
nsIAtom* id = aStartChild->GetID();
|
|
||||||
nsCAutoString strid;
|
nsIAtom* atomid = aStartChild->GetID();
|
||||||
if (id)
|
nsCAutoString id;
|
||||||
id->ToUTF8String(strid);
|
if (atomid)
|
||||||
|
atomid->ToUTF8String(id);
|
||||||
|
|
||||||
nsAutoString ctag;
|
nsAutoString ctag;
|
||||||
|
nsCAutoString cid;
|
||||||
|
nsIAtom* catomid = nsnull;
|
||||||
|
if (aContainer) {
|
||||||
aContainer->Tag()->ToString(ctag);
|
aContainer->Tag()->ToString(ctag);
|
||||||
nsIAtom* cid = aContainer->GetID();
|
catomid = aContainer->GetID();
|
||||||
nsCAutoString strcid;
|
if (catomid)
|
||||||
if (cid)
|
catomid->ToUTF8String(cid);
|
||||||
cid->ToUTF8String(strcid);
|
}
|
||||||
|
|
||||||
printf("\ncontent inserted: %s@id='%s', container: %s@id='%s', end node: %p\n\n",
|
printf("\ncontent inserted: %s@id='%s', container: %s@id='%s', end node: %p\n\n",
|
||||||
NS_ConvertUTF16toUTF8(tag).get(), strid.get(),
|
NS_ConvertUTF16toUTF8(tag).get(), id.get(),
|
||||||
NS_ConvertUTF16toUTF8(ctag).get(), strcid.get(), aEndChild);
|
NS_ConvertUTF16toUTF8(ctag).get(), cid.get(), aEndChild);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// XXX: bug 606082. aContainer is null when root element is inserted into
|
|
||||||
// document, we need to handle this and update the tree, also we need to
|
|
||||||
// update a content node of the document accessible.
|
|
||||||
if (aContainer) {
|
|
||||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||||
if (docAccessible)
|
if (docAccessible)
|
||||||
docAccessible->UpdateTree(aContainer, aStartChild, aEndChild, PR_TRUE);
|
docAccessible->UpdateTree(aContainer, aStartChild, aEndChild, PR_TRUE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
|
nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
|
||||||
nsIContent* aContainer,
|
nsIContent* aContainer,
|
||||||
nsIContent* aChild)
|
nsIContent* aChild)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_A11Y
|
#ifdef DEBUG_CONTENTMUTATION
|
||||||
nsAutoString id;
|
nsAutoString tag;
|
||||||
aChild->Tag()->ToString(id);
|
aChild->Tag()->ToString(tag);
|
||||||
printf("\ncontent removed: %s\n", NS_ConvertUTF16toUTF8(id).get());
|
|
||||||
|
nsIAtom* atomid = aChild->GetID();
|
||||||
|
nsCAutoString id;
|
||||||
|
if (atomid)
|
||||||
|
atomid->ToUTF8String(id);
|
||||||
|
|
||||||
|
nsAutoString ctag;
|
||||||
|
nsCAutoString cid;
|
||||||
|
nsIAtom* catomid = nsnull;
|
||||||
|
if (aContainer) {
|
||||||
|
aContainer->Tag()->ToString(ctag);
|
||||||
|
catomid = aContainer->GetID();
|
||||||
|
if (catomid)
|
||||||
|
catomid->ToUTF8String(cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\ncontent removed: %s@id='%s', container: %s@id='%s'\n\n",
|
||||||
|
NS_ConvertUTF16toUTF8(tag).get(), id.get(),
|
||||||
|
NS_ConvertUTF16toUTF8(ctag).get(), cid.get());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// XXX: bug 606082. aContainer is null when root element is inserted into
|
|
||||||
// document, we need to handle this and update the tree, perhaps destroy
|
|
||||||
// the document accessible.
|
|
||||||
if (aContainer) {
|
|
||||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||||
if (docAccessible)
|
if (docAccessible)
|
||||||
docAccessible->UpdateTree(aContainer, aChild, aChild->GetNextSibling(),
|
docAccessible->UpdateTree(aContainer, aChild, aChild->GetNextSibling(),
|
||||||
PR_FALSE);
|
PR_FALSE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
||||||
|
|
|
@ -285,8 +285,12 @@ nsDocAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
||||||
return NS_OK_DEFUNCT_OBJECT;
|
return NS_OK_DEFUNCT_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aExtraState)
|
if (aExtraState) {
|
||||||
*aExtraState = 0;
|
// The root content of the document might be removed so that mContent is
|
||||||
|
// out of date.
|
||||||
|
*aExtraState = (mContent->GetCurrentDoc() == mDocument) ?
|
||||||
|
0 : nsIAccessibleStates::EXT_STATE_STALE;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
|
nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
|
||||||
|
@ -1346,22 +1350,49 @@ nsDocAccessible::UpdateTree(nsIContent* aContainerNode,
|
||||||
// Since this information may be not correct then we need to fire some events
|
// Since this information may be not correct then we need to fire some events
|
||||||
// regardless the document loading state.
|
// regardless the document loading state.
|
||||||
|
|
||||||
|
// Update the whole tree of this document accessible when the container is
|
||||||
|
// null (document element is inserted or removed).
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||||
nsIEventStateManager* esm = presShell->GetPresContext()->EventStateManager();
|
nsIEventStateManager* esm = presShell->GetPresContext()->EventStateManager();
|
||||||
PRBool fireAllEvents = PR_TRUE;//IsContentLoaded() || esm->IsHandlingUserInputExternal();
|
PRBool fireAllEvents = PR_TRUE;//IsContentLoaded() || esm->IsHandlingUserInputExternal();
|
||||||
|
|
||||||
// We don't create new accessibles on content removal.
|
// XXX: bug 608887 reconsider accessible tree update logic because
|
||||||
nsAccessible* container = aIsInsert ?
|
// 1) elements appended outside the HTML body don't get accessibles;
|
||||||
GetAccService()->GetAccessibleOrContainer(aContainerNode, mWeakShell) :
|
// 2) the document having elements that should be accessible may function
|
||||||
GetAccService()->GetCachedAccessibleOrContainer(aContainerNode);
|
// without body.
|
||||||
|
nsAccessible* container = nsnull;
|
||||||
if (aIsInsert) {
|
if (aIsInsert) {
|
||||||
|
container = aContainerNode ?
|
||||||
|
GetAccService()->GetAccessibleOrContainer(aContainerNode, mWeakShell) :
|
||||||
|
this;
|
||||||
|
|
||||||
|
// The document children were changed; the root content might be affected.
|
||||||
|
if (container == this) {
|
||||||
|
nsIContent* rootContent = nsCoreUtils::GetRoleContent(mDocument);
|
||||||
|
|
||||||
|
// No root content (for example HTML document element was inserted but no
|
||||||
|
// body). Nothing to update.
|
||||||
|
if (!rootContent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// New root content has been inserted, update it and update the tree.
|
||||||
|
if (rootContent != mContent)
|
||||||
|
mContent = rootContent;
|
||||||
|
}
|
||||||
|
|
||||||
// XXX: Invalidate parent-child relations for container accessible and its
|
// XXX: Invalidate parent-child relations for container accessible and its
|
||||||
// children because there's no good way to find insertion point of new child
|
// children because there's no good way to find insertion point of new child
|
||||||
// accessibles into accessible tree. We need to invalidate children even
|
// accessibles into accessible tree. We need to invalidate children even
|
||||||
// there's no inserted accessibles in the end because accessible children
|
// there's no inserted accessibles in the end because accessible children
|
||||||
// are created while parent recaches child accessibles.
|
// are created while parent recaches child accessibles.
|
||||||
container->InvalidateChildren();
|
container->InvalidateChildren();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Don't create new accessibles on content removal.
|
||||||
|
container = aContainerNode ?
|
||||||
|
GetAccService()->GetCachedAccessibleOrContainer(aContainerNode) :
|
||||||
|
this;
|
||||||
}
|
}
|
||||||
|
|
||||||
EIsFromUserInput fromUserInput = esm->IsHandlingUserInputExternal() ?
|
EIsFromUserInput fromUserInput = esm->IsHandlingUserInputExternal() ?
|
||||||
|
|
|
@ -108,6 +108,7 @@ public:
|
||||||
virtual nsIFrame* GetFrame();
|
virtual nsIFrame* GetFrame();
|
||||||
virtual PRBool IsDefunct();
|
virtual PRBool IsDefunct();
|
||||||
virtual nsINode* GetNode() const { return mDocument; }
|
virtual nsINode* GetNode() const { return mDocument; }
|
||||||
|
virtual nsIDocument* GetDocumentNode() const { return mDocument; }
|
||||||
|
|
||||||
// nsAccessible
|
// nsAccessible
|
||||||
virtual PRUint32 NativeRole();
|
virtual PRUint32 NativeRole();
|
||||||
|
|
|
@ -38,6 +38,7 @@ const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
|
||||||
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
|
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
|
||||||
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
|
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
|
||||||
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
|
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
|
||||||
|
const EXT_STATE_STALE = nsIAccessibleStates.EXT_STATE_STALE;
|
||||||
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
|
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
|
||||||
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
|
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
|
||||||
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
|
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
testStates(docAcc, 0, EXT_STATE_EDITABLE);
|
testStates(docAcc, 0, EXT_STATE_EDITABLE);
|
||||||
testStates("article", 0, EXT_STATE_EDITABLE);
|
testStates("article", 0, EXT_STATE_EDITABLE);
|
||||||
|
testStates("article", 0, EXT_STATE_EDITABLE);
|
||||||
testStates("editable_article", 0, EXT_STATE_EDITABLE);
|
testStates("editable_article", 0, EXT_STATE_EDITABLE);
|
||||||
|
|
||||||
document.designMode = "off";
|
document.designMode = "off";
|
||||||
|
|
|
@ -46,6 +46,7 @@ include $(DEPTH)/config/autoconf.mk
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
_TEST_FILES =\
|
_TEST_FILES =\
|
||||||
|
test_doc.html \
|
||||||
test_list_editabledoc.html \
|
test_list_editabledoc.html \
|
||||||
test_list.html \
|
test_list.html \
|
||||||
test_recreation.html \
|
test_recreation.html \
|
||||||
|
|
|
@ -0,0 +1,370 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Test document root content mutations</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="../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">
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
function getDocNode(aID)
|
||||||
|
{
|
||||||
|
return getNode(aID).contentDocument;
|
||||||
|
}
|
||||||
|
function getDocChildNode(aID)
|
||||||
|
{
|
||||||
|
return getDocNode(aID).body.firstChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rootContentReplaced(aID, aTextName)
|
||||||
|
{
|
||||||
|
this.eventSeq = [
|
||||||
|
new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
|
||||||
|
new invokerChecker(EVENT_REORDER, getDocNode, aID)
|
||||||
|
];
|
||||||
|
|
||||||
|
this.finalCheck = function rootContentReplaced_finalCheck()
|
||||||
|
{
|
||||||
|
var tree = {
|
||||||
|
role: ROLE_DOCUMENT,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
role: ROLE_TEXT_LEAF,
|
||||||
|
name: aTextName
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
testAccessibleTree(getDocNode(aID), tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rootContentRemoved(aID)
|
||||||
|
{
|
||||||
|
this.eventSeq = [
|
||||||
|
new invokerChecker(EVENT_HIDE, null),
|
||||||
|
new invokerChecker(EVENT_REORDER, getDocNode, aID)
|
||||||
|
];
|
||||||
|
|
||||||
|
this.preinvoke = function rootContentRemoved_preinvoke()
|
||||||
|
{
|
||||||
|
// Set up target for hide event before we invoke.
|
||||||
|
var text = getAccessible(getAccessible(getDocNode(aID)).firstChild,
|
||||||
|
[nsIAccessNode]).DOMNode;
|
||||||
|
this.eventSeq[0].target = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.finalCheck = function rootContentRemoved_finalCheck()
|
||||||
|
{
|
||||||
|
var tree = {
|
||||||
|
role: ROLE_DOCUMENT,
|
||||||
|
states: {
|
||||||
|
// Out of date root content involves stale state presence.
|
||||||
|
states: 0,
|
||||||
|
extraStates: EXT_STATE_STALE
|
||||||
|
},
|
||||||
|
children: [ ]
|
||||||
|
};
|
||||||
|
testAccessibleTree(getDocNode(aID), tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rootContentInserted(aID, aTextName)
|
||||||
|
{
|
||||||
|
this.eventSeq = [
|
||||||
|
new invokerChecker(EVENT_SHOW, getDocChildNode, aID),
|
||||||
|
new invokerChecker(EVENT_REORDER, getDocNode, aID)
|
||||||
|
];
|
||||||
|
|
||||||
|
this.finalCheck = function rootContentInserted_finalCheck()
|
||||||
|
{
|
||||||
|
var tree = {
|
||||||
|
role: ROLE_DOCUMENT,
|
||||||
|
states: {
|
||||||
|
states: 0,
|
||||||
|
extraStates: 0,
|
||||||
|
absentStates: 0,
|
||||||
|
absentExtraStates: EXT_STATE_STALE
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
role: ROLE_TEXT_LEAF,
|
||||||
|
name: aTextName
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
testAccessibleTree(getDocNode(aID), tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Invokers
|
||||||
|
|
||||||
|
function writeIFrameDoc(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentReplaced(aID, "hello");
|
||||||
|
|
||||||
|
this.invoke = function writeIFrameDoc_invoke()
|
||||||
|
{
|
||||||
|
var docNode = getDocNode(aID);
|
||||||
|
|
||||||
|
// We can't use open/write/close outside of iframe document because of
|
||||||
|
// security error.
|
||||||
|
var script = docNode.createElement("script");
|
||||||
|
script.textContent = "document.open(); document.write('hello'); document.close();";
|
||||||
|
docNode.body.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function writeIFrameDoc_getID()
|
||||||
|
{
|
||||||
|
return "write document";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace HTML element.
|
||||||
|
*/
|
||||||
|
function replaceIFrameHTMLElm(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentReplaced(aID, "New Wave");
|
||||||
|
|
||||||
|
this.invoke = function replaceIFrameHTMLElm_invoke()
|
||||||
|
{
|
||||||
|
var docNode = getDocNode(aID);
|
||||||
|
var newHTMLNode = docNode.createElement("html");
|
||||||
|
var newBodyNode = docNode.createElement("body");
|
||||||
|
var newTextNode = docNode.createTextNode("New Wave");
|
||||||
|
newBodyNode.appendChild(newTextNode);
|
||||||
|
newHTMLNode.appendChild(newBodyNode);
|
||||||
|
docNode.replaceChild(newHTMLNode, docNode.documentElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function replaceIFrameBody_getID()
|
||||||
|
{
|
||||||
|
return "replace HTML element";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace HTML body.
|
||||||
|
*/
|
||||||
|
function replaceIFrameBody(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentReplaced(aID, "New Hello");
|
||||||
|
|
||||||
|
this.invoke = function replaceIFrameBody_invoke()
|
||||||
|
{
|
||||||
|
var docNode = getDocNode(aID);
|
||||||
|
var newBodyNode = docNode.createElement("body");
|
||||||
|
var newTextNode = docNode.createTextNode("New Hello");
|
||||||
|
newBodyNode.appendChild(newTextNode);
|
||||||
|
docNode.documentElement.replaceChild(newBodyNode, docNode.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.finalCheck = function replaceIFrameBody_finalCheck()
|
||||||
|
{
|
||||||
|
var tree = {
|
||||||
|
role: ROLE_DOCUMENT,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
role: ROLE_TEXT_LEAF,
|
||||||
|
name: "New Hello"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
testAccessibleTree(getDocNode(aID), tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function replaceIFrameBody_getID()
|
||||||
|
{
|
||||||
|
return "replace body";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open/close document pair.
|
||||||
|
*/
|
||||||
|
function openIFrameDoc(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentRemoved(aID);
|
||||||
|
|
||||||
|
this.invoke = function openIFrameDoc_invoke()
|
||||||
|
{
|
||||||
|
this.preinvoke();
|
||||||
|
|
||||||
|
// Open document.
|
||||||
|
var docNode = getDocNode(aID);
|
||||||
|
var script = docNode.createElement("script");
|
||||||
|
script.textContent = "function closeMe() { document.write('Works?'); document.close(); } window.closeMe = closeMe; document.open();";
|
||||||
|
docNode.body.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function openIFrameDoc_getID()
|
||||||
|
{
|
||||||
|
return "open document";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeIFrameDoc(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentInserted(aID, "Works?");
|
||||||
|
|
||||||
|
this.invoke = function closeIFrameDoc_invoke()
|
||||||
|
{
|
||||||
|
// Write and close document.
|
||||||
|
getDocNode(aID).write('Works?'); getDocNode(aID).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function closeIFrameDoc_getID()
|
||||||
|
{
|
||||||
|
return "close document";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove/insert HTML element pair.
|
||||||
|
*/
|
||||||
|
function removeHTMLFromIFrameDoc(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentRemoved(aID);
|
||||||
|
|
||||||
|
this.invoke = function removeHTMLFromIFrameDoc_invoke()
|
||||||
|
{
|
||||||
|
this.preinvoke();
|
||||||
|
|
||||||
|
// Remove HTML element.
|
||||||
|
var docNode = getDocNode(aID);
|
||||||
|
docNode.removeChild(docNode.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function removeHTMLFromIFrameDoc_getID()
|
||||||
|
{
|
||||||
|
return "remove HTML element";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertHTMLToIFrameDoc(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentInserted(aID, "Haha");
|
||||||
|
|
||||||
|
this.invoke = function insertHTMLToIFrameDoc_invoke()
|
||||||
|
{
|
||||||
|
// Insert HTML element.
|
||||||
|
var docNode = getDocNode(aID);
|
||||||
|
var html = docNode.createElement("html");
|
||||||
|
var body = docNode.createElement("body");
|
||||||
|
var text = docNode.createTextNode("Haha");
|
||||||
|
body.appendChild(text);
|
||||||
|
html.appendChild(body);
|
||||||
|
docNode.appendChild(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function insertHTMLToIFrameDoc_getID()
|
||||||
|
{
|
||||||
|
return "insert HTML element document";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove/insert HTML body pair.
|
||||||
|
*/
|
||||||
|
function removeBodyFromIFrameDoc(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentRemoved(aID);
|
||||||
|
|
||||||
|
this.invoke = function removeBodyFromIFrameDoc_invoke()
|
||||||
|
{
|
||||||
|
this.preinvoke();
|
||||||
|
|
||||||
|
// Remove body element.
|
||||||
|
var docNode = getDocNode(aID);
|
||||||
|
docNode.documentElement.removeChild(docNode.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function removeBodyFromIFrameDoc_getID()
|
||||||
|
{
|
||||||
|
return "remove body element";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function insertBodyToIFrameDoc(aID)
|
||||||
|
{
|
||||||
|
this.__proto__ = new rootContentInserted(aID, "Yo ho ho i butylka roma!");
|
||||||
|
|
||||||
|
this.invoke = function insertBodyToIFrameDoc_invoke()
|
||||||
|
{
|
||||||
|
// Insert body element.
|
||||||
|
var docNode = getDocNode(aID);
|
||||||
|
var body = docNode.createElement("body");
|
||||||
|
var text = docNode.createTextNode("Yo ho ho i butylka roma!");
|
||||||
|
body.appendChild(text);
|
||||||
|
docNode.documentElement.appendChild(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getID = function insertBodyToIFrameDoc_getID()
|
||||||
|
{
|
||||||
|
return "insert body element";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Test
|
||||||
|
|
||||||
|
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||||
|
|
||||||
|
var gQueue = null;
|
||||||
|
|
||||||
|
function doTest()
|
||||||
|
{
|
||||||
|
gQueue = new eventQueue();
|
||||||
|
|
||||||
|
gQueue.push(new writeIFrameDoc("iframe"));
|
||||||
|
gQueue.push(new replaceIFrameHTMLElm("iframe"));
|
||||||
|
gQueue.push(new replaceIFrameBody("iframe"));
|
||||||
|
gQueue.push(new openIFrameDoc("iframe"));
|
||||||
|
gQueue.push(new closeIFrameDoc("iframe"));
|
||||||
|
gQueue.push(new removeHTMLFromIFrameDoc("iframe"));
|
||||||
|
gQueue.push(new insertHTMLToIFrameDoc("iframe"));
|
||||||
|
gQueue.push(new removeBodyFromIFrameDoc("iframe"));
|
||||||
|
gQueue.push(new insertBodyToIFrameDoc("iframe"));
|
||||||
|
|
||||||
|
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
addA11yLoadEvent(doTest);
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<a target="_blank"
|
||||||
|
title="Update accessible tree when root element is changed"
|
||||||
|
href="https://bugzilla.mozilla.org/show_bug.cgi?id=606082">Mozilla Bug 606082</a>
|
||||||
|
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none"></div>
|
||||||
|
<pre id="test">
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<iframe id="iframe"></iframe>
|
||||||
|
|
||||||
|
<div id="eventdump"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -6898,6 +6898,17 @@ nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aContainer,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ACCESSIBILITY
|
||||||
|
if (mPresShell->IsAccessibilityActive()) {
|
||||||
|
nsCOMPtr<nsIAccessibilityService> accService =
|
||||||
|
do_GetService("@mozilla.org/accessibilityService;1");
|
||||||
|
if (accService) {
|
||||||
|
accService->ContentRangeInserted(mPresShell, aContainer,
|
||||||
|
aStartChild, aEndChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче