Bug 556004 - ###!!! ASSERTION: Getting the link state of an unregistered Link!: 'mRegistered', r=davidb, marcoz, a=davidb

This commit is contained in:
Alexander Surkov 2010-10-21 00:04:18 +09:00
parent 4b57cb09ac
commit 6121636fb9
7 changed files with 133 additions and 59 deletions

View File

@ -41,7 +41,7 @@
#include "nsCoreUtils.h"
#include "nsILink.h"
#include "nsIEventStateManager.h"
////////////////////////////////////////////////////////////////////////////////
// nsHTMLLinkAccessible
@ -82,20 +82,22 @@ nsHTMLLinkAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
*aState |= nsIAccessibleStates::STATE_SELECTABLE;
}
nsLinkState linkState = mContent->GetLinkState();
if (linkState == eLinkState_NotLink || linkState == eLinkState_Unknown) {
// This is a either named anchor (a link with also a name attribute) or
// it doesn't have any attributes. Check if 'click' event handler is
// registered, otherwise bail out.
PRBool isOnclick = nsCoreUtils::HasClickListener(mContent);
if (!isOnclick)
return NS_OK;
nsEventStates state = mContent->IntrinsicState();
if (state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
NS_EVENT_STATE_UNVISITED)) {
*aState |= nsIAccessibleStates::STATE_LINKED;
if (state.HasState(NS_EVENT_STATE_VISITED))
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
return NS_OK;
}
*aState |= nsIAccessibleStates::STATE_LINKED;
if (linkState == eLinkState_Visited)
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
// This is a either named anchor (a link with also a name attribute) or
// it doesn't have any attributes. Check if 'click' event handler is
// registered, otherwise bail out.
if (nsCoreUtils::HasClickListener(mContent))
*aState |= nsIAccessibleStates::STATE_LINKED;
return NS_OK;
}
@ -186,6 +188,7 @@ nsHTMLLinkAccessible::IsLinked()
if (IsDefunct())
return PR_FALSE;
nsLinkState linkState = mContent->GetLinkState();
return linkState != eLinkState_NotLink && linkState != eLinkState_Unknown;
nsEventStates state = mContent->IntrinsicState();
return state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
NS_EVENT_STATE_UNVISITED);
}

View File

@ -51,6 +51,7 @@ _TEST_FILES =\
test_general.html \
test_general.xul \
test_inputs.html \
test_link.html \
test_tree.xul \
test_treegrid.xul \
$(NULL)

View File

@ -19,18 +19,55 @@
src="../actions.js"></script>
<script type="application/javascript">
function getAnchorTargetDocumentAcc()
{
var thisTabDocAcc = getTabDocAccessible();
var thisDocTabPanelAcc = thisTabDocAcc.parent.parent;
var tabPanelsAcc = thisDocTabPanelAcc.parent;
var newDocTabPanelAcc = tabPanelsAcc.lastChild.firstChild;
return newDocTabPanelAcc.firstChild;
}
function linkChecker(aID)
{
this.type = EVENT_DOCUMENT_LOAD_COMPLETE;
this.__defineGetter__("target", getAnchorTargetDocumentAcc);
this.check = function linkChecker_check()
{
var anchorTargetWindow =
getAccessible(getAnchorTargetDocumentAcc(), [nsIAccessibleDocument]).
window;
anchorTargetWindow.close();
}
this.getID = function linkChecker_getID()
{
return "link '" + aID + "' states check ";
}
}
//gA11yEventDumpID = "eventdump"; // debug stuff
function doTest()
{
var actionsArray = [
{
ID: "link1",
actionName: "jump",
events: CLICK_EVENTS
events: CLICK_EVENTS,
eventSeq: [
new linkChecker("link1")
]
},
{
ID: "img1",
actionName: "click",
events: CLICK_EVENTS
targetID: "link1",
actionName: "jump",
events: CLICK_EVENTS,
eventSeq: [
new linkChecker("link1")
]
},
{
ID: "link2",
@ -39,7 +76,8 @@
},
{
ID: "img2",
actionName: "click",
targetID: "link2",
actionName: "jump",
events: CLICK_EVENTS
},
{
@ -49,7 +87,8 @@
},
{
ID: "img3",
actionName: "click",
targetID: "link3",
actionName: "jump",
events: CLICK_EVENTS
},
{
@ -59,7 +98,8 @@
},
{
ID: "img4",
actionName: "click",
targetID: "link4",
actionName: "jump",
events: CLICK_EVENTS
}
];
@ -83,7 +123,7 @@
<pre id="test">
</pre>
<a href="http://mozilla.org" id="link1">
<a href="about:mozilla" id="link1" target="_blank">
<img src="../moz.png" id="img1">
</a>
<a id="link2" onmousedown="">
@ -95,5 +135,7 @@
<a id="link4" onmouseup="">
<img src="../moz.png" id="img4">
</a>
<div id="eventdump"></div>
</body>
</html>

View File

@ -50,42 +50,6 @@ const nsIDOMXULElement = Components.interfaces.nsIDOMXULElement;
const nsIPropertyElement = Components.interfaces.nsIPropertyElement;
////////////////////////////////////////////////////////////////////////////////
// States
const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE;
const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
const STATE_INVALID = nsIAccessibleStates.STATE_INVALID;
const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
////////////////////////////////////////////////////////////////////////////////
// OS detect
const MAC = (navigator.platform.indexOf("Mac") != -1)? true : false;
@ -96,6 +60,8 @@ const WIN = (navigator.platform.indexOf("Win") != -1)? true : false;
////////////////////////////////////////////////////////////////////////////////
// Accessible general
const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
const kEmbedChar = String.fromCharCode(0xfffc);
/**
@ -274,6 +240,25 @@ function getRootAccessible(aAccOrElmOrID)
return acc ? acc.rootDocument.QueryInterface(nsIAccessible) : null;
}
/**
* Return tab document accessible the given accessible is contained by.
*/
function getTabDocAccessible(aAccOrElmOrID)
{
var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document,
[nsIAccessNode]);
var docAcc = acc.document.QueryInterface(nsIAccessible);
var containerDocAcc = docAcc.parent.QueryInterface(nsIAccessNode).document;
// Test is running is stand-alone mode.
if (acc.rootDocument == containerDocAcc)
return docAcc;
// In the case of running all tests together.
return containerDocAcc.QueryInterface(nsIAccessible);
}
/**
* Return application accessible.
*/

View File

@ -6,6 +6,46 @@
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// State constants
// const STATE_BUSY is defined in common.js
const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE;
const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
const STATE_INVALID = nsIAccessibleStates.STATE_INVALID;
const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
////////////////////////////////////////////////////////////////////////////////
// Test functions
/**
* Tests the states and extra states of the given accessible.
* Also tests for unwanted states and extra states.

View File

@ -21,11 +21,11 @@
<script type="application/javascript">
function doTest()
{
// strong roles
testStates("link1", STATE_LINKED);
testStates("link2", STATE_LINKED);
testStates("link3", STATE_LINKED);
testStates("link4", STATE_LINKED);
testStates("link5", 0, 0, STATE_LINKED);
SimpleTest.finish();
}
@ -52,6 +52,7 @@
<a id="link2" onclick="">link</a>
<a id="link3" onmousedown="">link</a>
<a id="link4" onmouseup="">link</a>
<a id="link5">not link</a>
</body>
</html>

View File

@ -12,6 +12,8 @@
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="nsIAccessible_selects.js"></script>