Merge mozilla-central to tracemonkey

This commit is contained in:
Robert Sayre 2009-06-27 11:19:19 -07:00
Родитель 3c2efd0a5e 57cfb0b344
Коммит f28cd0f53f
360 изменённых файлов: 27665 добавлений и 2788 удалений

Просмотреть файл

@ -59,7 +59,6 @@ XPIDLSRCS = \
nsIAccessibleRole.idl \
nsIAccessibleStates.idl \
nsIAccessibleDocument.idl \
nsPIAccessibleDocument.idl \
nsIAccessibleProvider.idl \
nsIAccessibleSelectable.idl \
nsIAccessNode.idl \

Просмотреть файл

@ -54,9 +54,7 @@
*
* There are no nsIAccessibleRole enums for the following landmark roles:
* banner, contentinfo, main, navigation, note, search, secondary, seealso, breadcrumbs
*/
static const nsStateMapEntry kEndEntry = {nsnull, 0, 0}; // To fill in array of state mappings
*/
nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
{
@ -67,8 +65,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"alertdialog",
@ -77,8 +74,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"application",
@ -87,8 +83,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"article",
@ -97,8 +92,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_READONLY,
kEndEntry
nsIAccessibleStates::STATE_READONLY
},
{
"button",
@ -108,9 +102,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eClickAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_pressed, kBoolState, nsIAccessibleStates::STATE_PRESSED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_pressed, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
kEndEntry
eARIAPressed
},
{
"checkbox",
@ -119,11 +111,9 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eCheckUncheckAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_CHECKABLE,
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
kNoReqStates,
eARIACheckableMixed,
eARIAReadonly
},
{
"columnheader",
@ -133,10 +123,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eSortAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
eARIASelected,
eARIAReadonly
},
{
"combobox",
@ -146,9 +134,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eOpenCloseAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_COLLAPSED | nsIAccessibleStates::STATE_HASPOPUP,
// Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
eARIAAutoComplete,
eARIAReadonly
},
{
"dialog",
@ -157,8 +144,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"document",
@ -167,8 +153,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_READONLY,
kEndEntry
nsIAccessibleStates::STATE_READONLY
},
{
"grid",
@ -178,9 +163,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_FOCUSABLE,
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
eARIAMultiSelectable,
eARIAReadonly
},
{
"gridcell",
@ -190,10 +174,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
eARIASelected,
eARIAReadonly
},
{
"group",
@ -202,8 +184,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"heading",
@ -212,8 +193,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"img",
@ -222,8 +202,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"label",
@ -232,8 +211,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"link",
@ -242,8 +220,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eJumpAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_LINKED,
kEndEntry
nsIAccessibleStates::STATE_LINKED
},
{
"list",
@ -253,8 +230,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_READONLY,
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
kEndEntry
eARIAMultiSelectable
},
{
"listbox",
@ -264,9 +240,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
kEndEntry
eARIAMultiSelectable,
eARIAReadonly
},
{
"listitem",
@ -276,12 +251,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction, // XXX: should depend on state, parent accessible
eNoLiveAttr,
nsIAccessibleStates::STATE_READONLY,
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
kEndEntry
eARIASelected,
eARIACheckedMixed
},
{
"log",
@ -290,8 +261,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
ePoliteLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"marquee",
@ -300,8 +270,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eOffLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"math",
@ -310,8 +279,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"menu",
@ -321,8 +289,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction, // XXX: technically accessibles of menupopup role haven't
// any action, but menu can be open or close.
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"menubar",
@ -331,8 +298,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"menuitem",
@ -342,10 +308,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eClickAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
kEndEntry
eARIACheckedMixed
},
{
"menuitemcheckbox",
@ -354,10 +317,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eClickAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_CHECKABLE,
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED},
kEndEntry
kNoReqStates,
eARIACheckableMixed
},
{
"menuitemradio",
@ -366,9 +327,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eClickAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_CHECKABLE,
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED },
kEndEntry
kNoReqStates,
eARIACheckableBool
},
{
"option",
@ -378,12 +338,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eSelectAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
kEndEntry
eARIASelected,
eARIACheckedMixed
},
{
"presentation",
@ -392,8 +348,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"progressbar",
@ -402,8 +357,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eHasValueMinMax,
eNoAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_READONLY,
kEndEntry
nsIAccessibleStates::STATE_READONLY
},
{
"radio",
@ -412,9 +366,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eSelectAction,
eNoLiveAttr,
nsIAccessibleStates::STATE_CHECKABLE,
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED},
kEndEntry
kNoReqStates,
eARIACheckableBool
},
{
"radiogroup",
@ -423,8 +376,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"region",
@ -433,8 +385,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"row",
@ -444,9 +395,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
kEndEntry
eARIASelected
},
{
"rowheader",
@ -456,10 +405,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eSortAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
eARIASelected,
eARIAReadonly
},
{
"section",
@ -468,8 +415,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"separator",
@ -478,8 +424,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"slider",
@ -489,8 +434,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
eARIAReadonly
},
{
"spinbutton",
@ -500,8 +444,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
eARIAReadonly
},
{
"status",
@ -510,8 +453,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
ePoliteLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"tab",
@ -520,8 +462,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eSwitchAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"tablist",
@ -530,8 +471,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
ePoliteLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"tabpanel",
@ -540,8 +480,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"textbox",
@ -551,12 +490,9 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eActivateAction,
eNoLiveAttr,
kNoReqStates,
// Manually map EXT_STATE_SINGLE_LINE and EXT_STATE_MULTI_LINE FROM aria-multiline
// Manually map EXT_STATE_SUPPORTS_AUTOCOMPLETION aria-autocomplete
{&nsAccessibilityAtoms::aria_autocomplete, "list", nsIAccessibleStates::STATE_HASPOPUP},
{&nsAccessibilityAtoms::aria_autocomplete, "both", nsIAccessibleStates::STATE_HASPOPUP},
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
kEndEntry
eARIAAutoComplete,
eARIAMultiline,
eARIAReadonlyOrEditable
},
{
"timer",
@ -565,8 +501,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eOffLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"toolbar",
@ -575,8 +510,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"tooltip",
@ -585,8 +519,7 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
},
{
"tree",
@ -596,9 +529,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
kEndEntry
eARIAReadonly,
eARIAMultiSelectable
},
{
"treegrid",
@ -608,9 +540,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
eNoAction,
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_readonly, kBoolState, nsIAccessibleStates::STATE_READONLY},
{&nsAccessibilityAtoms::aria_multiselectable, kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
kEndEntry
eARIAReadonly,
eARIAMultiSelectable
},
{
"treeitem",
@ -621,12 +552,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
// on states
eNoLiveAttr,
kNoReqStates,
{&nsAccessibilityAtoms::aria_selected, kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_selected, "false", nsIAccessibleStates::STATE_SELECTABLE},
{&nsAccessibilityAtoms::aria_checked, kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_checked, "mixed", nsIAccessibleStates::STATE_MIXED | nsIAccessibleStates::STATE_CHECKABLE},
{&nsAccessibilityAtoms::aria_checked, "false", nsIAccessibleStates::STATE_CHECKABLE},
kEndEntry
eARIASelected,
eARIACheckedMixed
}
};
@ -639,8 +566,7 @@ nsRoleMapEntry nsARIAMap::gLandmarkRoleMap = {
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
};
nsRoleMapEntry nsARIAMap::gEmptyRoleMap = {
@ -650,8 +576,89 @@ nsRoleMapEntry nsARIAMap::gEmptyRoleMap = {
eNoValue,
eNoAction,
eNoLiveAttr,
kNoReqStates,
kEndEntry
kNoReqStates
};
nsStateMapEntry nsARIAMap::gWAIStateMap[] = {
// eARIANone
nsStateMapEntry(),
// eARIAAutoComplete
nsStateMapEntry(&nsAccessibilityAtoms::aria_autocomplete,
"inline", 0, nsIAccessibleStates::EXT_STATE_SUPPORTS_AUTOCOMPLETION,
"list", nsIAccessibleStates::STATE_HASPOPUP, nsIAccessibleStates::EXT_STATE_SUPPORTS_AUTOCOMPLETION,
"both", nsIAccessibleStates::STATE_HASPOPUP, nsIAccessibleStates::EXT_STATE_SUPPORTS_AUTOCOMPLETION),
// eARIABusy
nsStateMapEntry(&nsAccessibilityAtoms::aria_busy,
"true", nsIAccessibleStates::STATE_BUSY, 0,
"error", nsIAccessibleStates::STATE_INVALID, 0),
// eARIACheckableBool
nsStateMapEntry(&nsAccessibilityAtoms::aria_checked, kBoolType,
nsIAccessibleStates::STATE_CHECKABLE,
nsIAccessibleStates::STATE_CHECKED, 0,
0, 0, PR_TRUE),
// eARIACheckableMixed
nsStateMapEntry(&nsAccessibilityAtoms::aria_checked, kMixedType,
nsIAccessibleStates::STATE_CHECKABLE,
nsIAccessibleStates::STATE_CHECKED, 0,
0, 0, PR_TRUE),
// eARIACheckedMixed
nsStateMapEntry(&nsAccessibilityAtoms::aria_checked, kMixedType,
nsIAccessibleStates::STATE_CHECKABLE,
nsIAccessibleStates::STATE_CHECKED, 0),
// eARIADisabled
nsStateMapEntry(&nsAccessibilityAtoms::aria_disabled, kBoolType, 0,
nsIAccessibleStates::STATE_UNAVAILABLE, 0),
// eARIAExpanded
nsStateMapEntry(&nsAccessibilityAtoms::aria_expanded, kBoolType, 0,
nsIAccessibleStates::STATE_EXPANDED, 0,
nsIAccessibleStates::STATE_COLLAPSED, 0),
// eARIAHasPopup
nsStateMapEntry(&nsAccessibilityAtoms::aria_haspopup, kBoolType, 0,
nsIAccessibleStates::STATE_HASPOPUP, 0),
// eARIAInvalid
nsStateMapEntry(&nsAccessibilityAtoms::aria_invalid, kBoolType, 0,
nsIAccessibleStates::STATE_INVALID, 0),
// eARIAMultiline
nsStateMapEntry(&nsAccessibilityAtoms::aria_multiline, kBoolType, 0,
0, nsIAccessibleStates::EXT_STATE_MULTI_LINE,
0, nsIAccessibleStates::EXT_STATE_SINGLE_LINE, PR_TRUE),
// eARIAMultiSelectable
nsStateMapEntry(&nsAccessibilityAtoms::aria_multiselectable, kBoolType, 0,
nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE, 0),
// eARIAPressed
nsStateMapEntry(&nsAccessibilityAtoms::aria_pressed, kMixedType,
nsIAccessibleStates::STATE_CHECKABLE,
nsIAccessibleStates::STATE_PRESSED, 0),
// eARIAReadonly
nsStateMapEntry(&nsAccessibilityAtoms::aria_readonly, kBoolType, 0,
nsIAccessibleStates::STATE_READONLY, 0),
// eARIAReadonlyOrEditable
nsStateMapEntry(&nsAccessibilityAtoms::aria_readonly, kBoolType, 0,
nsIAccessibleStates::STATE_READONLY, 0,
0, nsIAccessibleStates::EXT_STATE_EDITABLE, PR_TRUE),
// eARIARequired
nsStateMapEntry(&nsAccessibilityAtoms::aria_required, kBoolType, 0,
nsIAccessibleStates::STATE_REQUIRED, 0),
// eARIASelected
nsStateMapEntry(&nsAccessibilityAtoms::aria_selected, kBoolType,
nsIAccessibleStates::STATE_SELECTABLE,
nsIAccessibleStates::STATE_SELECTED, 0)
};
/**
@ -659,16 +666,14 @@ nsRoleMapEntry nsARIAMap::gEmptyRoleMap = {
* The following state rules are applied to any accessible element,
* whether there is an ARIA role or not:
*/
nsStateMapEntry nsARIAMap::gWAIUnivStateMap[] = {
{&nsAccessibilityAtoms::aria_required, kBoolState, nsIAccessibleStates::STATE_REQUIRED},
{&nsAccessibilityAtoms::aria_invalid, kBoolState, nsIAccessibleStates::STATE_INVALID},
{&nsAccessibilityAtoms::aria_haspopup, kBoolState, nsIAccessibleStates::STATE_HASPOPUP},
{&nsAccessibilityAtoms::aria_busy, "true", nsIAccessibleStates::STATE_BUSY},
{&nsAccessibilityAtoms::aria_busy, "error", nsIAccessibleStates::STATE_INVALID},
{&nsAccessibilityAtoms::aria_disabled, kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
{&nsAccessibilityAtoms::aria_expanded, kBoolState, nsIAccessibleStates::STATE_EXPANDED},
{&nsAccessibilityAtoms::aria_expanded, "false", nsIAccessibleStates::STATE_COLLAPSED},
kEndEntry
eStateMapEntryID nsARIAMap::gWAIUnivStateMap[] = {
eARIARequired,
eARIAInvalid,
eARIAHasPopup,
eARIABusy,
eARIADisabled,
eARIAExpanded,
eARIANone
};
@ -709,3 +714,144 @@ nsAttributeCharacteristics nsARIAMap::gWAIUnivAttrMap[] = {
};
PRUint32 nsARIAMap::gWAIUnivAttrMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIUnivAttrMap);
////////////////////////////////////////////////////////////////////////////////
// nsStateMapEntry
nsStateMapEntry:: nsStateMapEntry(nsIAtom **aAttrName, eStateValueType aType,
PRUint32 aPermanentState,
PRUint32 aTrueState, PRUint32 aTrueExtraState,
PRUint32 aFalseState, PRUint32 aFalseExtraState,
PRBool aDefinedIfAbsent) :
attributeName(aAttrName), isToken(PR_TRUE), permanentState(aPermanentState)
{
value1 = "false";
state1 = aFalseState;
extraState1 = aFalseExtraState;
if (aType == kMixedType) {
value2 = "mixed";
state2 = nsIAccessibleStates::STATE_MIXED;
extraState2 = 0;
}
defaultState = aTrueState;
defaultExtraState = aTrueExtraState;
definedIfAbsent = aDefinedIfAbsent;
}
nsStateMapEntry::nsStateMapEntry(nsIAtom **aAttrName,
const char *aValue1,
PRUint32 aState1, PRUint32 aExtraState1,
const char *aValue2,
PRUint32 aState2, PRUint32 aExtraState2,
const char *aValue3,
PRUint32 aState3, PRUint32 aExtraState3) :
attributeName(aAttrName), isToken(PR_FALSE), permanentState(0),
value1(aValue1), state1(aState1), extraState1(aExtraState1),
value2(aValue2), state2(aState2), extraState2(aExtraState2),
value3(aValue3), state3(aState3), extraState3(aExtraState3),
defaultState(0), defaultExtraState(0), definedIfAbsent(PR_FALSE)
{
}
PRBool
nsStateMapEntry::MapToStates(nsIContent *aContent,
PRUint32 *aState, PRUint32 *aExtraState,
eStateMapEntryID aStateMapEntryID)
{
// Return true if we should continue.
if (aStateMapEntryID == eARIANone)
return PR_FALSE;
const nsStateMapEntry& entry = nsARIAMap::gWAIStateMap[aStateMapEntryID];
if (entry.isToken) {
// If attribute is considered as defined when it's absent then let's act
// attribute value is "false" supposedly.
PRBool hasAttr = aContent->HasAttr(kNameSpaceID_None, *entry.attributeName);
if (entry.definedIfAbsent && !hasAttr) {
if (entry.permanentState)
*aState |= entry.permanentState;
if (entry.state1)
*aState |= entry.state1;
if (aExtraState && entry.extraState1)
*aExtraState |= entry.extraState1;
return PR_TRUE;
}
// We only have attribute state mappings for NMTOKEN (and boolean) based
// ARIA attributes. According to spec, a value of "undefined" is to be
// treated equivalent to "", or the absence of the attribute. We bail out
// for this case here.
// Note: If this method happens to be called with a non-token based
// attribute, for example: aria-label="" or aria-label="undefined", we will
// bail out and not explore a state mapping, which is safe.
if (!hasAttr ||
aContent->AttrValueIs(kNameSpaceID_None, *entry.attributeName,
nsAccessibilityAtoms::_empty, eCaseMatters) ||
aContent->AttrValueIs(kNameSpaceID_None, *entry.attributeName,
nsAccessibilityAtoms::_undefined, eCaseMatters)) {
if (entry.permanentState)
*aState &= ~entry.permanentState;
return PR_TRUE;
}
if (entry.permanentState)
*aState |= entry.permanentState;
}
nsAutoString attrValue;
if (!aContent->GetAttr(kNameSpaceID_None, *entry.attributeName, attrValue))
return PR_TRUE;
// Apply states for matched value. If no values was matched then apply default
// states.
PRBool applyDefaultStates = PR_TRUE;
if (entry.value1) {
if (attrValue.EqualsASCII(entry.value1)) {
applyDefaultStates = PR_FALSE;
if (entry.state1)
*aState |= entry.state1;
if (aExtraState && entry.extraState1)
*aExtraState |= entry.extraState1;
} else if (entry.value2) {
if (attrValue.EqualsASCII(entry.value2)) {
applyDefaultStates = PR_FALSE;
if (entry.state2)
*aState |= entry.state2;
if (aExtraState && entry.extraState2)
*aExtraState |= entry.extraState2;
} else if (entry.value3) {
if (attrValue.EqualsASCII(entry.value3)) {
applyDefaultStates = PR_FALSE;
if (entry.state3)
*aState |= entry.state3;
if (aExtraState && entry.extraState3)
*aExtraState |= entry.extraState3;
}
}
}
}
if (applyDefaultStates) {
if (entry.defaultState)
*aState |= entry.defaultState;
if (entry.defaultExtraState && aExtraState)
*aExtraState |= entry.defaultExtraState;
}
return PR_TRUE;
}

Просмотреть файл

@ -43,14 +43,35 @@
#include "prtypes.h"
#include "nsAccessibilityAtoms.h"
// Is nsIAccessible value supported for this role or not?
#include "nsIContent.h"
////////////////////////////////////////////////////////////////////////////////
// Value constants
/**
* Used to define if role requires to expose nsIAccessibleValue.
*/
enum EValueRule
{
/**
* nsIAccessibleValue isn't exposed.
*/
eNoValue,
eHasValueMinMax // Supports value, min and max from aria-valuenow, aria-valuemin and aria-valuemax
/**
* nsIAccessibleValue is implemented, supports value, min and max from
* aria-valuenow, aria-valuemin and aria-valuemax.
*/
eHasValueMinMax
};
// Should we expose action based on the ARIA role?
////////////////////////////////////////////////////////////////////////////////
// Action constants
/**
* Used to define if the role requires to expose action.
*/
enum EActionRule
{
eNoAction,
@ -65,6 +86,13 @@ enum EActionRule
eSwitchAction
};
////////////////////////////////////////////////////////////////////////////////
// Live region constants
/**
* Used to define if role exposes default value of aria-live attribute.
*/
enum ELiveAttrRule
{
eNoLiveAttr,
@ -72,11 +100,23 @@ enum ELiveAttrRule
ePoliteLiveAttr
};
// Role mapping rule
////////////////////////////////////////////////////////////////////////////////
// Role constants
/**
* ARIA role overrides role from native markup.
*/
const PRBool kUseMapRole = PR_TRUE;
/**
* ARIA role doesn't override the role from native markup.
*/
const PRBool kUseNativeRole = PR_FALSE;
// ARIA attribute characteristic masks, grow as needed
////////////////////////////////////////////////////////////////////////////////
// ARIA attribute characteristic masks
/**
* This mask indicates the attribute should not be exposed as an object
@ -92,29 +132,132 @@ const PRUint8 ATTR_BYPASSOBJ = 0x0001;
*/
const PRUint8 ATTR_VALTOKEN = 0x0010;
// Used for an nsStateMapEntry if a given state attribute supports "true" and "false"
#define kBoolState 0
// Used in nsRoleMapEntry.state if no nsIAccessibleStates are automatic for a given role
#define kNoReqStates 0
// For this name and value pair, what is the nsIAccessibleStates mapping.
// nsStateMapEntry.state
struct nsStateMapEntry
{
nsIAtom** attributeName; // nsnull indicates last entry in map
const char* attributeValue; // magic value of kBoolState (0) means supports "true" and "false"
PRUint32 state; // If match, this is the nsIAccessibleStates to map to
};
// Small footprint storage of persistent aria attribute characteristics
/**
* Small footprint storage of persistent aria attribute characteristics.
*/
struct nsAttributeCharacteristics
{
nsIAtom** attributeName;
const PRUint8 characteristics;
};
// For each ARIA role, this maps the nsIAccessible information
////////////////////////////////////////////////////////////////////////////////
// State map entry
/**
* Used in nsRoleMapEntry.state if no nsIAccessibleStates are automatic for
* a given role.
*/
#define kNoReqStates 0
enum eStateValueType
{
kBoolType,
kMixedType
};
/**
* ID for state map entry, used in nsRoleMapEntry.
*/
enum eStateMapEntryID
{
eARIANone,
eARIAAutoComplete,
eARIABusy,
eARIACheckableBool,
eARIACheckableMixed,
eARIACheckedMixed,
eARIADisabled,
eARIAExpanded,
eARIAHasPopup,
eARIAInvalid,
eARIAMultiline,
eARIAMultiSelectable,
eARIAPressed,
eARIAReadonly,
eARIAReadonlyOrEditable,
eARIARequired,
eARIASelected
};
class nsStateMapEntry
{
public:
/**
* Used to create stub.
*/
nsStateMapEntry() {}
/**
* Used for ARIA attributes having boolean or mixed values.
*/
nsStateMapEntry(nsIAtom **aAttrName, eStateValueType aType,
PRUint32 aPermanentState,
PRUint32 aTrueState, PRUint32 aTrueExtraState,
PRUint32 aFalseState = 0, PRUint32 aFalseExtraState = 0,
PRBool aDefinedIfAbsent = PR_FALSE);
/**
* Used for ARIA attributes having enumerated values.
*/
nsStateMapEntry(nsIAtom **aAttrName,
const char *aValue1, PRUint32 aState1, PRUint32 aExtraState1,
const char *aValue2, PRUint32 aState2, PRUint32 aExtraState2,
const char *aValue3 = 0, PRUint32 aState3 = 0,
PRUint32 aExtraState3 = 0);
/**
* Maps ARIA state map pointed by state map entry ID to accessible states.
*
* @param aContent [in] node of the accessible
* @param aState [in/out] accessible states
* @param aExtraState [in/out] accessible extra states
* @param aStateMapEntryID [in] state map entry ID
* @return true if state map entry ID is valid
*/
static PRBool MapToStates(nsIContent *aContent,
PRUint32 *aState, PRUint32 *aExtraState,
eStateMapEntryID aStateMapEntryID);
private:
// ARIA attribute name
nsIAtom** attributeName;
// Indicates if attribute is token (can be undefined)
PRBool isToken;
// State applied always if attribute is defined
PRUint32 permanentState;
// States applied if attribute value is matched to the stored value
const char* value1;
PRUint32 state1;
PRUint32 extraState1;
const char* value2;
PRUint32 state2;
PRUint32 extraState2;
const char* value3;
PRUint32 state3;
PRUint32 extraState3;
// States applied if no stored values above are matched
PRUint32 defaultState;
PRUint32 defaultExtraState;
// Permanent and false states are applied if attribute is absent
PRBool definedIfAbsent;
};
////////////////////////////////////////////////////////////////////////////////
// Role map entry
/**
* For each ARIA role, this maps the nsIAccessible information.
*/
struct nsRoleMapEntry
{
// ARIA role: string representation such as "button"
@ -144,16 +287,15 @@ struct nsRoleMapEntry
// Currently you cannot have unlimited mappings, because
// a variable sized array would not allow the use of
// C++'s struct initialization feature.
nsStateMapEntry attributeMap1;
nsStateMapEntry attributeMap2;
nsStateMapEntry attributeMap3;
nsStateMapEntry attributeMap4;
nsStateMapEntry attributeMap5;
nsStateMapEntry attributeMap6;
nsStateMapEntry attributeMap7;
nsStateMapEntry attributeMap8;
eStateMapEntryID attributeMap1;
eStateMapEntryID attributeMap2;
eStateMapEntryID attributeMap3;
};
////////////////////////////////////////////////////////////////////////////////
// ARIA map
/**
* These are currently initialized (hardcoded) in nsARIAMap.cpp,
* and provide the mappings for WAI-ARIA roles and properties using the
@ -180,11 +322,16 @@ struct nsARIAMap
*/
static nsRoleMapEntry gEmptyRoleMap;
/**
* State map of ARIA state attributes.
*/
static nsStateMapEntry gWAIStateMap[];
/**
* State map of ARIA states applied to any accessible not depending on
* the role.
*/
static nsStateMapEntry gWAIUnivStateMap[];
static eStateMapEntryID gWAIUnivStateMap[];
/**
* Map of attribute to attribute characteristics.

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsAccessibleEventData.h"
#include "nsHyperTextAccessible.h"
#include "nsHTMLTableAccessible.h"
#include "nsDocAccessible.h"
#include "nsAccessibilityAtoms.h"
#include "nsAccessibleTreeWalker.h"
#include "nsAccessible.h"
@ -747,6 +748,26 @@ nsAccUtils::QueryAccessibleTable(nsIAccessibleTable *aAccessibleTable)
return accessible;
}
already_AddRefed<nsDocAccessible>
nsAccUtils::QueryAccessibleDocument(nsIAccessible *aAccessible)
{
nsDocAccessible* accessible = nsnull;
if (aAccessible)
CallQueryInterface(aAccessible, &accessible);
return accessible;
}
already_AddRefed<nsDocAccessible>
nsAccUtils::QueryAccessibleDocument(nsIAccessibleDocument *aAccessibleDocument)
{
nsDocAccessible* accessible = nsnull;
if (aAccessibleDocument)
CallQueryInterface(aAccessibleDocument, &accessible);
return accessible;
}
#ifdef DEBUG_A11Y
PRBool

Просмотреть файл

@ -55,6 +55,7 @@
class nsAccessNode;
class nsAccessible;
class nsHTMLTableAccessible;
class nsDocAccessible;
class nsAccUtils
{
@ -340,7 +341,19 @@ public:
*/
static already_AddRefed<nsHTMLTableAccessible>
QueryAccessibleTable(nsIAccessibleTable *aAccessibleTable);
/**
* Query nsDocAccessible from the given nsIAccessible.
*/
static already_AddRefed<nsDocAccessible>
QueryAccessibleDocument(nsIAccessible *aAccessible);
/**
* Query nsDocAccessible from the given nsIAccessibleDocument.
*/
static already_AddRefed<nsDocAccessible>
QueryAccessibleDocument(nsIAccessibleDocument *aAccessibleDocument);
#ifdef DEBUG_A11Y
/**
* Detect whether the given accessible object implements nsIAccessibleText,

Просмотреть файл

@ -42,7 +42,6 @@
#include "nsHashtable.h"
#include "nsIAccessibilityService.h"
#include "nsIAccessibleDocument.h"
#include "nsPIAccessibleDocument.h"
#include "nsIDocShell.h"
#include "nsIDocShellTreeItem.h"
#include "nsIDocument.h"
@ -192,10 +191,10 @@ nsAccessNode::Init()
void* uniqueID;
GetUniqueID(&uniqueID);
nsCOMPtr<nsPIAccessibleDocument> privateDocAccessible =
do_QueryInterface(docAccessible);
NS_ASSERTION(privateDocAccessible, "No private docaccessible for docaccessible");
privateDocAccessible->CacheAccessNode(uniqueID, this);
nsRefPtr<nsDocAccessible> docAcc =
nsAccUtils::QueryAccessibleDocument(docAccessible);
NS_ASSERTION(docAcc, "No nsDocAccessible for document accessible!");
docAcc->CacheAccessNode(uniqueID, this);
// Make sure an ancestor in real content is cached
// so that nsDocAccessible::RefreshNodes() can find the anonymous subtree to release when

Просмотреть файл

@ -43,8 +43,7 @@
* This class wraps up the creation (and destruction) of the standard
* set of atoms used in the accessibility module. These objects
* are created when the are needed by accessibility is being used and they
* are destroyed when the last nsRootAccessible is destroyed via
* nsRootAccessible::ShutdownAll()
* are destroyed when the last nsRootAccessible is destroyed.
*/
class nsAccessibilityAtoms {

Просмотреть файл

@ -242,9 +242,11 @@ NS_IMETHODIMP nsAccessibilityService::ProcessDocLoadEvent(nsITimer *aTimer, void
nsCOMPtr<nsIAccessible> accessible;
GetAccessibleFor(docNode, getter_AddRefs(accessible));
nsCOMPtr<nsPIAccessibleDocument> privDocAccessible = do_QueryInterface(accessible);
NS_ENSURE_STATE(privDocAccessible);
privDocAccessible->FireDocLoadEvents(aEventType);
nsRefPtr<nsDocAccessible> docAcc =
nsAccUtils::QueryAccessibleDocument(accessible);
NS_ENSURE_STATE(docAcc);
docAcc->FireDocLoadEvents(aEventType);
return NS_OK;
}
@ -307,12 +309,12 @@ NS_IMETHODIMP nsAccessibilityService::OnLocationChange(nsIWebProgress *aWebProgr
nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
nsAccessNode::GetDocAccessibleFor(domDocRootNode);
nsCOMPtr<nsPIAccessibleDocument> privateAccessibleDoc =
do_QueryInterface(accessibleDoc);
if (!privateAccessibleDoc) {
return NS_OK;
}
return privateAccessibleDoc->FireAnchorJumpEvent();
nsRefPtr<nsDocAccessible> docAcc =
nsAccUtils::QueryAccessibleDocument(accessibleDoc);
if (docAcc)
docAcc->FireAnchorJumpEvent();
return NS_OK;
}
/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
@ -2040,12 +2042,12 @@ NS_IMETHODIMP nsAccessibilityService::InvalidateSubtreeFor(nsIPresShell *aShell,
NS_ENSURE_ARG_POINTER(aShell);
nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
nsAccessNode::GetDocAccessibleFor(aShell->GetDocument());
nsCOMPtr<nsPIAccessibleDocument> privateAccessibleDoc =
do_QueryInterface(accessibleDoc);
if (!privateAccessibleDoc) {
return NS_OK;
}
return privateAccessibleDoc->InvalidateCacheSubtree(aChangeContent, aEvent);
nsRefPtr<nsDocAccessible> docAcc =
nsAccUtils::QueryAccessibleDocument(accessibleDoc);
if (docAcc)
docAcc->InvalidateCacheSubtree(aChangeContent, aEvent);
return NS_OK;
}
//////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -281,7 +281,7 @@ nsAccessible::GetName(nsAString& aName)
nsCOMPtr<nsIXBLAccessible> xblAccessible(do_QueryInterface(mDOMNode));
if (xblAccessible) {
nsresult rv = xblAccessible->GetAccessibleName(aName);
xblAccessible->GetAccessibleName(aName);
if (!aName.IsEmpty())
return NS_OK;
}
@ -1891,45 +1891,6 @@ nsAccessible::GroupPosition(PRInt32 *aGroupLevel,
return NS_OK;
}
PRBool nsAccessible::MappedAttrState(nsIContent *aContent, PRUint32 *aStateInOut,
nsStateMapEntry *aStateMapEntry)
{
// Return true if we should continue
if (!aStateMapEntry->attributeName) {
return PR_FALSE; // Stop looking -- no more states
}
// We only have attribute state mappings for NMTOKEN (and boolean) based
// ARIA attributes. According to spec, a value of "undefined" is to be
// treated equivalent to "", or the absence of the attribute. We bail out
// for this case here.
// Note: If this method happens to be called with a non-token based
// attribute, for example: aria-label="" or aria-label="undefined", we will
// bail out and not explore a state mapping, which is safe.
if (!nsAccUtils::HasDefinedARIAToken(aContent, *aStateMapEntry->attributeName)) {
return PR_TRUE;
}
nsAutoString attribValue;
if (aContent->GetAttr(kNameSpaceID_None, *aStateMapEntry->attributeName, attribValue)) {
if (aStateMapEntry->attributeValue == kBoolState) {
// No attribute value map specified in state map entry indicates state cleared
if (attribValue.EqualsLiteral("false") ||
attribValue.EqualsLiteral("mixed")) {
*aStateInOut &= ~aStateMapEntry->state;
}
else {
*aStateInOut |= aStateMapEntry->state;
}
}
else if (NS_ConvertUTF16toUTF8(attribValue).Equals(aStateMapEntry->attributeValue)) {
*aStateInOut |= aStateMapEntry->state;
}
}
return PR_TRUE;
}
NS_IMETHODIMP
nsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
{
@ -1947,7 +1908,7 @@ nsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
NS_ENSURE_A11Y_SUCCESS(rv, rv);
// Apply ARIA states to be sure accessible states will be overriden.
GetARIAState(aState);
GetARIAState(aState, aExtraState);
if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_PAGETAB) {
if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
@ -2019,33 +1980,6 @@ nsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
rv = GetRole(&role);
NS_ENSURE_SUCCESS(rv, rv);
if (role == nsIAccessibleRole::ROLE_ENTRY ||
role == nsIAccessibleRole::ROLE_COMBOBOX) {
nsCOMPtr<nsIContent> content = nsCoreUtils::GetRoleContent(mDOMNode);
NS_ENSURE_STATE(content);
nsAutoString autocomplete;
if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_autocomplete, autocomplete) &&
(autocomplete.EqualsIgnoreCase("inline") ||
autocomplete.EqualsIgnoreCase("list") ||
autocomplete.EqualsIgnoreCase("both"))) {
*aExtraState |= nsIAccessibleStates::EXT_STATE_SUPPORTS_AUTOCOMPLETION;
}
// XXX We can remove this hack once we support RDF-based role & state maps
if (mRoleMapEntry && mRoleMapEntry->role == nsIAccessibleRole::ROLE_ENTRY) {
PRBool isMultiLine = content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::aria_multiline,
nsAccessibilityAtoms::_true, eCaseMatters);
*aExtraState |= isMultiLine ? nsIAccessibleStates::EXT_STATE_MULTI_LINE :
nsIAccessibleStates::EXT_STATE_SINGLE_LINE;
if (0 == (*aState & nsIAccessibleStates::STATE_READONLY))
*aExtraState |= nsIAccessibleStates::EXT_STATE_EDITABLE; // Not readonly
else // We're readonly: make sure editable state wasn't set by impl class
*aExtraState &= ~nsIAccessibleStates::EXT_STATE_EDITABLE;
}
}
// For some reasons DOM node may have not a frame. We tract such accessibles
// as invisible.
nsIFrame *frame = GetFrame();
@ -2077,7 +2011,7 @@ nsAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
}
nsresult
nsAccessible::GetARIAState(PRUint32 *aState)
nsAccessible::GetARIAState(PRUint32 *aState, PRUint32 *aExtraState)
{
// Test for universal states first
nsIContent *content = nsCoreUtils::GetRoleContent(mDOMNode);
@ -2086,7 +2020,8 @@ nsAccessible::GetARIAState(PRUint32 *aState)
}
PRUint32 index = 0;
while (MappedAttrState(content, aState, &nsARIAMap::gWAIUnivStateMap[index])) {
while (nsStateMapEntry::MapToStates(content, aState, aExtraState,
nsARIAMap::gWAIUnivStateMap[index])) {
++ index;
}
@ -2126,14 +2061,12 @@ nsAccessible::GetARIAState(PRUint32 *aState)
// Note: the readonly bitflag will be overridden later if content is editable
*aState |= mRoleMapEntry->state;
if (MappedAttrState(content, aState, &mRoleMapEntry->attributeMap1) &&
MappedAttrState(content, aState, &mRoleMapEntry->attributeMap2) &&
MappedAttrState(content, aState, &mRoleMapEntry->attributeMap3) &&
MappedAttrState(content, aState, &mRoleMapEntry->attributeMap4) &&
MappedAttrState(content, aState, &mRoleMapEntry->attributeMap5) &&
MappedAttrState(content, aState, &mRoleMapEntry->attributeMap6) &&
MappedAttrState(content, aState, &mRoleMapEntry->attributeMap7)) {
MappedAttrState(content, aState, &mRoleMapEntry->attributeMap8);
if (nsStateMapEntry::MapToStates(content, aState, aExtraState,
mRoleMapEntry->attributeMap1) &&
nsStateMapEntry::MapToStates(content, aState, aExtraState,
mRoleMapEntry->attributeMap2)) {
nsStateMapEntry::MapToStates(content, aState, aExtraState,
mRoleMapEntry->attributeMap3);
}
return NS_OK;

Просмотреть файл

@ -148,8 +148,9 @@ public:
* method.
*
* @param [in/out] where to fill the states into.
* @param [in/out] where to fill the extra states into
*/
virtual nsresult GetARIAState(PRUint32 *aState);
virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
/**
* Returns the accessible name provided by native markup. It doesn't take
@ -279,7 +280,6 @@ public:
}
protected:
PRBool MappedAttrState(nsIContent *aContent, PRUint32 *aStateInOut, nsStateMapEntry *aStateMapEntry);
virtual nsIFrame* GetBoundsFrame();
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
PRBool IsVisible(PRBool *aIsOffscreen);

Просмотреть файл

@ -385,6 +385,9 @@ nsAccEvent::ApplyEventRules(nsCOMArray<nsIAccessibleEvent> &aEventsToFire)
}
}
} break; // case eRemoveDupes
default:
break; // case eAllowDupes, eDoNotEmit
} // switch
} // for (tail)
}

Просмотреть файл

@ -201,7 +201,7 @@ nsCoreUtils::GetDOMNodeFromDOMPoint(nsIDOMNode *aNode, PRUint32 aOffset)
nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
if (content && content->IsNodeOfType(nsINode::eELEMENT)) {
PRInt32 childCount = static_cast<PRInt32>(content->GetChildCount());
PRUint32 childCount = content->GetChildCount();
NS_ASSERTION(aOffset >= 0 && aOffset <= childCount,
"Wrong offset of the DOM point!");

Просмотреть файл

@ -150,6 +150,18 @@ ElementTraverser(const void *aKey, nsIAccessNode *aAccessNode,
return PL_DHASH_NEXT;
}
// What we want is: NS_INTERFACE_MAP_ENTRY(self) for static IID accessors,
// but some of our classes have an ambiguous base class of nsISupports which
// prevents this from working (the default macro converts it to nsISupports,
// then addrefs it, then returns it). Therefore, we expand the macro here and
// change it so that it works. Yuck.
#define NS_INTERFACE_MAP_STATIC_AMBIGUOUS(_class) \
if (aIID.Equals(NS_GET_IID(_class))) { \
NS_ADDREF(this); \
*aInstancePtr = this; \
return NS_OK; \
} else
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocAccessible)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
@ -163,14 +175,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDocAccessible, nsAccessible)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDocAccessible)
NS_INTERFACE_MAP_STATIC_AMBIGUOUS(nsDocAccessible)
NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument)
NS_INTERFACE_MAP_ENTRY(nsPIAccessibleDocument)
NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_ENTRY(nsIScrollPositionListener)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleDocument)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleDocument)
NS_INTERFACE_MAP_END_INHERITING(nsHyperTextAccessible)
NS_IMPL_ADDREF_INHERITED(nsDocAccessible, nsHyperTextAccessible)
@ -328,16 +340,16 @@ nsDocAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
}
nsresult
nsDocAccessible::GetARIAState(PRUint32 *aState)
nsDocAccessible::GetARIAState(PRUint32 *aState, PRUint32 *aExtraState)
{
// Combine with states from outer doc
NS_ENSURE_ARG_POINTER(aState);
nsresult rv = nsAccessible::GetARIAState(aState);
nsresult rv = nsAccessible::GetARIAState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsAccessible> parent = nsAccUtils::QueryAccessible(mParent);
if (parent) // Allow iframe/frame etc. to have final state override via ARIA
return parent->GetARIAState(aState);
return parent->GetARIAState(aState, aExtraState);
return rv;
}
@ -553,7 +565,7 @@ NS_IMETHODIMP nsDocAccessible::GetCachedAccessNode(void *aUniqueID, nsIAccessNod
return NS_OK;
}
NS_IMETHODIMP
void
nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode)
{
// If there is an access node for the given unique ID then let's shutdown it.
@ -568,7 +580,6 @@ nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode)
}
PutCacheEntry(mAccessNodeCache, aUniqueID, aAccessNode);
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::GetParent(nsIAccessible **aParent)
@ -692,6 +703,15 @@ nsDocAccessible::GetFrame()
return root;
}
PRBool
nsDocAccessible::IsDefunct()
{
if (nsHyperTextAccessibleWrap::IsDefunct())
return PR_TRUE;
return !mDocument;
}
void nsDocAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aRelativeFrame)
{
*aRelativeFrame = GetFrame();
@ -822,11 +842,12 @@ nsresult nsDocAccessible::RemoveEventListeners()
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::FireAnchorJumpEvent()
void
nsDocAccessible::FireAnchorJumpEvent()
{
if (!mIsContentLoaded || !mDocument) {
return NS_OK;
}
if (!mIsContentLoaded || !mDocument)
return;
nsCOMPtr<nsISupports> container = mDocument->GetContainer();
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(container));
nsCAutoString theURL;
@ -854,15 +875,13 @@ NS_IMETHODIMP nsDocAccessible::FireAnchorJumpEvent()
mIsAnchorJumped = PR_TRUE;
lastAnchor.Assign(currentAnchor);
}
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
void
nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
{
if (!mDocument || !mWeakShell) {
return NS_OK; // Document has been shut down
}
if (IsDefunct())
return;
PRBool isFinished =
(aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
@ -871,15 +890,16 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
mIsContentLoaded = isFinished;
if (isFinished) {
if (mIsLoadCompleteFired)
return NS_OK;
return;
mIsLoadCompleteFired = PR_TRUE;
}
nsCOMPtr<nsIDocShellTreeItem> treeItem =
nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
if (!treeItem) {
return NS_OK;
}
if (!treeItem)
return;
nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
@ -928,7 +948,6 @@ NS_IMETHODIMP nsDocAccessible::FireDocLoadEvents(PRUint32 aEventType)
nsAccUtils::FireAccEvent(aEventType, this);
}
return NS_OK;
}
void nsDocAccessible::ScrollTimerCallback(nsITimer *aTimer, void *aClosure)
@ -1569,14 +1588,14 @@ nsDocAccessible::FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent)
// so that event gets fired via FlushEventsCallback
NS_ADDREF_THIS(); // Kung fu death grip to prevent crash in callback
mFireEventTimer->InitWithFuncCallback(FlushEventsCallback,
static_cast<nsPIAccessibleDocument*>(this),
0, nsITimer::TYPE_ONE_SHOT);
this, 0, nsITimer::TYPE_ONE_SHOT);
}
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
void
nsDocAccessible::FlushPendingEvents()
{
mInFlushPendingEvents = PR_TRUE;
PRUint32 length = mEventsToFire.Count();
@ -1685,12 +1704,12 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
if (accessible) {
if (eventType == nsIAccessibleEvent::EVENT_INTERNAL_LOAD) {
nsCOMPtr<nsPIAccessibleDocument> docAccessible =
do_QueryInterface(accessible);
NS_ASSERTION(docAccessible, "No doc accessible for doc load event");
if (docAccessible) {
docAccessible->FireDocLoadEvents(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
}
nsRefPtr<nsDocAccessible> docAcc =
nsAccUtils::QueryAccessibleDocument(accessible);
NS_ASSERTION(docAcc, "No doc accessible for doc load event");
if (docAcc)
docAcc->FireDocLoadEvents(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
}
else if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
nsCOMPtr<nsIAccessibleText> accessibleText = do_QueryInterface(accessible);
@ -1759,12 +1778,11 @@ NS_IMETHODIMP nsDocAccessible::FlushPendingEvents()
nsAccEvent::ResetLastInputState();
mInFlushPendingEvents = PR_FALSE;
return NS_OK;
}
void nsDocAccessible::FlushEventsCallback(nsITimer *aTimer, void *aClosure)
{
nsPIAccessibleDocument *accessibleDoc = static_cast<nsPIAccessibleDocument*>(aClosure);
nsDocAccessible *accessibleDoc = static_cast<nsDocAccessible*>(aClosure);
NS_ASSERTION(accessibleDoc, "How did we get here without an accessible document?");
if (accessibleDoc) {
// A lot of crashes were happening here, so now we're reffing the doc
@ -1880,8 +1898,9 @@ void nsDocAccessible::RefreshNodes(nsIDOMNode *aStartNode)
mAccessNodeCache.Remove(uniqueID);
}
NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
PRUint32 aChangeEventType)
void
nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
PRUint32 aChangeEventType)
{
PRBool isHiding =
aChangeEventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE ||
@ -1908,11 +1927,12 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
// instead of just the accessible tree, although that would be faster
// Otherwise we might miss the nsAccessNode's that are not nsAccessible's.
NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(mDOMNode,);
nsCOMPtr<nsIDOMNode> childNode = aChild ? do_QueryInterface(aChild) : mDOMNode;
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(presShell,);
if (!mIsContentLoaded) {
// Still loading document
@ -1925,10 +1945,12 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
// Leave early, and ensure mAccChildCount stays uninitialized instead of 0,
// which it is if anyone asks for its children right now.
InvalidateChildren();
return NS_OK;
return;
}
nsIEventStateManager *esm = presShell->GetPresContext()->EventStateManager();
NS_ENSURE_TRUE(esm, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(esm,);
if (!esm->IsHandlingUserInputExternal()) {
// Changes during page load, but not caused by user input
// Just invalidate accessible hierarchy and return,
@ -1942,7 +1964,7 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
nsRefPtr<nsAccessible> containerAcc =
nsAccUtils::QueryAccessible(containerAccessible);
containerAcc->InvalidateChildren();
return NS_OK;
return;
}
// else: user input, so we must fall through and for full handling,
// e.g. fire the mutation events. Note: user input could cause DOM_CREATE
@ -1998,7 +2020,7 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
// This often happens when visibility is cleared for node,
// which hides an entire subtree -- we get notified for each
// node in the subtree and need to collate the hide events ourselves.
return NS_OK;
return;
}
}
}
@ -2010,7 +2032,8 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
// Fire an event if the accessible existed for node being hidden, otherwise
// for the first line accessible descendants. Fire before the accessible(s) away.
nsresult rv = FireShowHideEvents(childNode, PR_FALSE, removalEventType, PR_TRUE, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_SUCCESS(rv,);
if (childNode != mDOMNode) { // Fire text change unless the node being removed is for this doc
// When a node is hidden or removed, the text in an ancestor hyper text will lose characters
// At this point we still have the frame and accessible for this node if there was one
@ -2102,11 +2125,9 @@ NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
new nsAccReorderEvent(containerAccessible, isAsynch,
isUnconditionalEvent,
aChild ? childNode.get() : nsnull);
NS_ENSURE_TRUE(reorderEvent, NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(reorderEvent,);
FireDelayedAccessibleEvent(reorderEvent);
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -41,7 +41,6 @@
#include "nsHyperTextAccessibleWrap.h"
#include "nsIAccessibleDocument.h"
#include "nsPIAccessibleDocument.h"
#include "nsIDocument.h"
#include "nsIDocumentObserver.h"
#include "nsIEditor.h"
@ -56,9 +55,16 @@ class nsIScrollableView;
const PRUint32 kDefaultCacheSize = 256;
#define NS_DOCACCESSIBLE_IMPL_CID \
{ /* 0ed1be1d-52a7-4bfd-b4f5-0de7caed4617 */ \
0x0ed1be1d, \
0x52a7, \
0x4bfd, \
{ 0xb4, 0xf5, 0x0d, 0xe7, 0xca, 0xed, 0x46, 0x17 } \
}
class nsDocAccessible : public nsHyperTextAccessibleWrap,
public nsIAccessibleDocument,
public nsPIAccessibleDocument,
public nsIDocumentObserver,
public nsIObserver,
public nsIScrollPositionListener,
@ -68,73 +74,119 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDocAccessible, nsAccessible)
NS_DECL_NSIACCESSIBLEDOCUMENT
NS_DECL_NSPIACCESSIBLEDOCUMENT
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOCACCESSIBLE_IMPL_CID)
NS_DECL_NSIOBSERVER
public:
nsDocAccessible(nsIDOMNode *aNode, nsIWeakReference* aShell);
virtual ~nsDocAccessible();
public:
nsDocAccessible(nsIDOMNode *aNode, nsIWeakReference* aShell);
virtual ~nsDocAccessible();
// nsIAccessible
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetDescription(nsAString& aDescription);
NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
NS_IMETHOD GetParent(nsIAccessible **aParent);
NS_IMETHOD TakeFocus(void);
// nsIAccessible
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetDescription(nsAString& aDescription);
NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
NS_IMETHOD GetParent(nsIAccessible **aParent);
NS_IMETHOD TakeFocus(void);
// ----- nsIScrollPositionListener ---------------------------
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {}
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
// nsIScrollPositionListener
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView,
nscoord aX, nscoord aY);
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {}
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView,
nscoord aX, nscoord aY);
// nsIDocumentObserver
NS_DECL_NSIDOCUMENTOBSERVER
// nsIDocumentObserver
NS_DECL_NSIDOCUMENTOBSERVER
static void FlushEventsCallback(nsITimer *aTimer, void *aClosure);
// nsAccessNode
virtual nsresult Init();
virtual nsresult Shutdown();
virtual nsIFrame* GetFrame();
virtual PRBool IsDefunct();
// nsAccessNode
virtual nsresult Init();
virtual nsresult Shutdown();
virtual nsIFrame* GetFrame();
// nsAccessible
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
virtual nsresult GetARIAState(PRUint32 *aState);
virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
// nsIAccessibleText
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
// nsIAccessibleText
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
/**
* Non-virtual method to fire a delayed event after a 0 length timeout
*
* @param aEvent - the nsIAccessibleEvent event type
* @param aDOMNode - DOM node the accesible event should be fired for
* @param aAllowDupes - eAllowDupes: more than one event of the same type is allowed.
* eCoalesceFromSameSubtree: if two events are in the same subtree,
* only the event on ancestor is used
* eRemoveDupes (default): events of the same type are discarded
* (the last one is used)
*
* @param aIsAsynch - set to PR_TRUE if this is not being called from code
* synchronous with a DOM event
*/
nsresult FireDelayedToolkitEvent(PRUint32 aEvent, nsIDOMNode *aDOMNode,
nsAccEvent::EEventRule aAllowDupes = nsAccEvent::eRemoveDupes,
PRBool aIsAsynch = PR_FALSE);
// nsDocAccessible
/**
* Fire accessible event in timeout.
*
* @param aEvent - the event to fire
*/
nsresult FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent);
/**
* Non-virtual method to fire a delayed event after a 0 length timeout.
*
* @param aEvent [in] the nsIAccessibleEvent event type
* @param aDOMNode [in] DOM node the accesible event should be fired for
* @param aAllowDupes [in] rule to process an event (see EEventRule constants)
* @param aIsAsynch [in] set to PR_TRUE if this is not being called from
* code synchronous with a DOM event
*/
nsresult FireDelayedToolkitEvent(PRUint32 aEvent, nsIDOMNode *aDOMNode,
nsAccEvent::EEventRule aAllowDupes = nsAccEvent::eRemoveDupes,
PRBool aIsAsynch = PR_FALSE);
void ShutdownChildDocuments(nsIDocShellTreeItem *aStart);
/**
* Fire accessible event after timeout.
*
* @param aEvent [in] the event to fire
*/
nsresult FireDelayedAccessibleEvent(nsIAccessibleEvent *aEvent);
/**
* Find the accessible object in the accessibility cache that corresponds to
* the given node or the first ancestor of it that has an accessible object
* associated with it. Clear that accessible object's parent's cache of
* accessible children and remove the accessible object and any descendants
* from the accessible cache. Fires proper events. New accessible objects will
* be created and cached again on demand.
*
* @param aContent [in] the child that is changing
* @param aEvent [in] the event from nsIAccessibleEvent that caused
* the change.
*/
void InvalidateCacheSubtree(nsIContent *aContent, PRUint32 aEvent);
/**
* Cache access node.
*
* @param aUniquID [in] the unique identifier of accessible
* @param aAccessNode [in] accessible to cache
*/
void CacheAccessNode(void *aUniqueID, nsIAccessNode *aAccessNode);
/**
* Fires pending events.
*/
void FlushPendingEvents();
/**
* Fire document load events.
*
* @param aEventType [in] nsIAccessibleEvent constant
*/
virtual void FireDocLoadEvents(PRUint32 aEventType);
/**
* Process the case when anchor was clicked.
*/
virtual void FireAnchorJumpEvent();
/**
* Used to flush pending events, called after timeout. See FlushPendingEvents.
*/
static void FlushEventsCallback(nsITimer *aTimer, void *aClosure);
protected:
/**
* Iterates through sub documents and shut them down.
*/
void ShutdownChildDocuments(nsIDocShellTreeItem *aStart);
protected:
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
virtual nsresult AddEventListeners();
virtual nsresult RemoveEventListeners();
@ -230,4 +282,7 @@ protected:
static nsIAtom *gLastFocusedFrameType;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsDocAccessible,
NS_DOCACCESSIBLE_IMPL_CID)
#endif

Просмотреть файл

@ -1070,27 +1070,26 @@ nsRootAccessible::GetRelationByType(PRUint32 aRelationType,
return NS_OK;
}
NS_IMETHODIMP nsRootAccessible::FireDocLoadEvents(PRUint32 aEventType)
void
nsRootAccessible::FireDocLoadEvents(PRUint32 aEventType)
{
if (!mDocument || !mWeakShell) {
return NS_OK; // Document has been shut down
}
if (IsDefunct())
return;
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
nsCoreUtils::GetDocShellTreeItemFor(mDOMNode);
NS_ASSERTION(docShellTreeItem, "No doc shell tree item for document");
NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
if (!docShellTreeItem)
return;
PRInt32 contentType;
docShellTreeItem->GetItemType(&contentType);
if (contentType == nsIDocShellTreeItem::typeContent) {
return nsDocAccessibleWrap::FireDocLoadEvents(aEventType); // Content might need to fire event
}
if (contentType == nsIDocShellTreeItem::typeContent)
nsDocAccessibleWrap::FireDocLoadEvents(aEventType); // Content might need to fire event
// Root chrome: don't fire event
mIsContentLoaded = (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
return NS_OK;
}
nsresult

Просмотреть файл

@ -69,33 +69,32 @@ class nsRootAccessible : public nsDocAccessibleWrap,
{
NS_DECL_ISUPPORTS_INHERITED
public:
nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell);
virtual ~nsRootAccessible();
public:
nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell);
virtual ~nsRootAccessible();
// nsIAccessible
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetParent(nsIAccessible * *aParent);
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
nsIAccessibleRelation **aRelation);
// nsIAccessible
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetParent(nsIAccessible * *aParent);
NS_IMETHOD GetRelationByType(PRUint32 aRelationType,
nsIAccessibleRelation **aRelation);
// ----- nsPIAccessibleDocument -----------------------
NS_IMETHOD FireDocLoadEvents(PRUint32 aEventType);
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
// ----- nsIDOMEventListener --------------------------
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
// nsAccessNode
virtual nsresult Init();
virtual nsresult Shutdown();
// nsAccessNode
virtual nsresult Init();
virtual nsresult Shutdown();
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
// nsAccessible
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
// nsDocAccessible
virtual void FireDocLoadEvents(PRUint32 aEventType);
void ShutdownAll();
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ROOTACCESSIBLE_IMPL_CID)
// nsRootAccessible
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ROOTACCESSIBLE_IMPL_CID)
/**
* Fire an accessible focus event for the current focusAccssible

Просмотреть файл

@ -296,7 +296,7 @@ nsHTMLButtonAccessible::GetRoleInternal(PRUint32 *aRole)
nsresult
nsHTMLButtonAccessible::GetNameInternal(nsAString& aName)
{
nsresult rv = nsAccessible::GetNameInternal(aName);
nsAccessible::GetNameInternal(aName);
if (!aName.IsEmpty())
return NS_OK;

Просмотреть файл

@ -1389,7 +1389,7 @@ NS_IMETHODIMP nsHTMLTableAccessible::IsProbablyForLayout(PRBool *aIsProbablyForL
PRUint32 length;
nodeList->GetLength(&length);
nsAutoString color, lastRowColor;
for (PRInt32 rowCount = 0; rowCount < length; rowCount ++) {
for (PRUint32 rowCount = 0; rowCount < length; rowCount ++) {
nsCOMPtr<nsIDOMNode> rowNode;
nodeList->Item(rowCount, getter_AddRefs(rowNode));

Просмотреть файл

@ -161,7 +161,8 @@ __try {
return E_FAIL;
}
NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
void
nsDocAccessibleWrap::FireAnchorJumpEvent()
{
// Staying on the same page, jumping to a named anchor
// Fire EVENT_SCROLLING_START on first leaf accessible -- because some
@ -171,19 +172,19 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
// we have to move forward in the document to get one
nsDocAccessible::FireAnchorJumpEvent();
if (!mIsAnchorJumped)
return NS_OK;
return;
nsCOMPtr<nsIDOMNode> focusNode;
if (mIsAnchor) {
nsCOMPtr<nsISelectionController> selCon(do_QueryReferent(mWeakShell));
if (!selCon) {
return NS_OK;
}
if (!selCon)
return;
nsCOMPtr<nsISelection> domSel;
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
if (!domSel) {
return NS_OK;
}
if (!domSel)
return;
domSel->GetFocusNode(getter_AddRefs(focusNode));
}
else {
@ -193,8 +194,6 @@ NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
nsCOMPtr<nsIAccessible> accessible = GetFirstAvailableAccessible(focusNode, PR_TRUE);
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_SCROLLING_START,
accessible);
return NS_OK;
}
STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)

Просмотреть файл

@ -92,7 +92,7 @@ public:
/* [optional][in] */ VARIANT varChild,
/* [retval][out] */ BSTR __RPC_FAR *pszValue);
NS_IMETHOD FireAnchorJumpEvent();
virtual void FireAnchorJumpEvent();
};
#endif

Просмотреть файл

@ -872,6 +872,18 @@ already_AddRefed<nsIDOMNode> nsXULTextFieldAccessible::GetInputField()
return inputField;
}
nsresult
nsXULTextFieldAccessible::GetARIAState(PRUint32 *aState, PRUint32 *aExtraState)
{
nsresult rv = nsHyperTextAccessibleWrap::GetARIAState(aState, aExtraState);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
nsStateMapEntry::MapToStates(content, aState, aExtraState, eARIAAutoComplete);
return NS_OK;
}
nsresult
nsXULTextFieldAccessible::GetStateInternal(PRUint32 *aState,
PRUint32 *aExtraState)

Просмотреть файл

@ -204,6 +204,7 @@ public:
NS_IMETHOD GetAssociatedEditor(nsIEditor **aEditor);
// nsAccessible
virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
virtual nsresult GetRoleInternal(PRUint32 *aRole);
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
virtual PRBool GetAllowsAnonChildAccessibles();

Просмотреть файл

@ -48,7 +48,7 @@ include $(topsrcdir)/config/rules.mk
_TEST_FILES =\
letters.gif \
moz.png \
$(topsrcdir)/content/media/video/test/bug461281.ogg \
$(topsrcdir)/content/media/test/bug461281.ogg \
longdesc_src.html \
actions.js \
attributes.js \

Просмотреть файл

@ -49,6 +49,7 @@ 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;
@ -57,12 +58,14 @@ 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;
@ -71,9 +74,8 @@ const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
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_INVALID = nsIAccessibleStates.STATE_INVALID;
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
const EXT_STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
@ -108,7 +110,7 @@ function addA11yLoadEvent(aFunc)
var accDoc = getAccessible(document);
var state = {};
accDoc.getState(state, {});
if (state.value & nsIAccessibleStates.STATE_BUSY)
if (state.value & STATE_BUSY)
return waitForDocLoad();
aFunc.call();
@ -326,9 +328,12 @@ function statesToString(aStates, aExtraStates)
var list = gAccRetrieval.getStringStates(aStates, aExtraStates);
var str = "";
for (var index = 0; index < list.length; index++)
for (var index = 0; index < list.length - 1; index++)
str += list.item(index) + ", ";
if (list.length != 0)
str += list.item(index)
return str;
}

Просмотреть файл

@ -1,3 +1,11 @@
////////////////////////////////////////////////////////////////////////////////
// Helper functions for accessible states testing.
//
// requires:
// common.js
//
////////////////////////////////////////////////////////////////////////////////
/**
* Tests the states and extra states of the given accessible.
* Also tests for unwanted states and extra states.
@ -17,55 +25,73 @@ function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
var id = prettyName(aAccOrElmOrID);
is(state & aState, aState,
"wrong state bits for " + id + "!");
// Primary test.
isState(state & aState, aState, false,
"wrong state bits for " + id + "!");
if (aExtraState)
is(extraState & aExtraState, aExtraState,
"wrong extra state bits for " + id + "!");
isState(extraState & aExtraState, aExtraState, true,
"wrong extra state bits for " + id + "!");
if (aAbsentState)
is(state & aAbsentState, 0,
"state bits should not be present in ID " + id + "!");
isState(state & aAbsentState, 0, false,
"state bits should not be present in ID " + id + "!");
if (aAbsentExtraState)
is(extraState & aAbsentExtraState, 0,
"extraState bits should not be present in ID " + id + "!");
isState(extraState & aAbsentExtraState, 0, true,
"extraState bits should not be present in ID " + id + "!");
// Additional test.
// readonly/editable
if (state & STATE_READONLY)
is(extraState & EXT_STATE_EDITABLE, 0,
"Read-only " + id + " cannot be editable!");
isState(extraState & EXT_STATE_EDITABLE, 0, true,
"Read-only " + id + " cannot be editable!");
if (extraState & EXT_STATE_EDITABLE)
is(state & STATE_READONLY, 0,
"Editable " + id + " cannot be readonly!");
isState(state & STATE_READONLY, 0, true,
"Editable " + id + " cannot be readonly!");
// multiline/singleline
if (extraState & EXT_STATE_MULTI_LINE)
isState(extraState & EXT_STATE_SINGLE_LINE, 0, true,
"Multiline " + id + " cannot be singleline!");
if (extraState & EXT_STATE_SINGLE_LINE)
isState(extraState & EXT_STATE_MULTI_LINE, 0, true,
"Singleline " + id + " cannot be multiline!");
// expanded/collapsed/expandable
if (state & STATE_COLLAPSED || state & STATE_EXPANDED)
is(extraState & EXT_STATE_EXPANDABLE, EXT_STATE_EXPANDABLE,
"Collapsed or expanded " + id + " should be expandable!");
isState(extraState & EXT_STATE_EXPANDABLE, EXT_STATE_EXPANDABLE, true,
"Collapsed or expanded " + id + " should be expandable!");
if (state & STATE_COLLAPSED)
is(state & STATE_EXPANDED, 0,
"Collapsed " + id + " cannot be expanded!");
isState(state & STATE_EXPANDED, 0, false,
"Collapsed " + id + " cannot be expanded!");
if (state & STATE_EXPANDED)
is(state & STATE_COLLAPSED, 0,
"Expanded " + id + " cannot be collapsed!");
isState(state & STATE_COLLAPSED, 0, false,
"Expanded " + id + " cannot be collapsed!");
// checked/mixed/checkable
if (state & STATE_CHECKED || state & STATE_MIXED)
is(state & STATE_CHECKABLE, STATE_CHECKABLE,
"Checked or mixed element must be checkable!");
isState(state & STATE_CHECKABLE, STATE_CHECKABLE, false,
"Checked or mixed element must be checkable!");
if (state & STATE_CHECKED)
is(state & STATE_MIXED, 0, "Checked element cannot be state mixed!");
isState(state & STATE_MIXED, 0, false,
"Checked element cannot be state mixed!");
if (state & STATE_MIXED)
is(state & STATE_CHECKED, 0, "Mixed element cannot be state checked!");
isState(state & STATE_CHECKED, 0, false,
"Mixed element cannot be state checked!");
// unavailable
if ((state & STATE_UNAVAILABLE)
&& (getRole(aAccOrElmOrID) != ROLE_GROUPING))
is(state & STATE_FOCUSABLE, STATE_FOCUSABLE,
"Disabled " + id + " must be focusable!");
isState(state & STATE_FOCUSABLE, STATE_FOCUSABLE, false,
"Disabled " + id + " must be focusable!");
}
/**
@ -122,3 +148,31 @@ function getStates(aAccOrElmOrID)
return [state.value, extraState.value];
}
////////////////////////////////////////////////////////////////////////////////
// Private implementation details
/**
* Analogy of SimpleTest.is function used to compare states.
*/
function isState(aState1, aState2, aIsExtraStates, aMsg)
{
if (aState1 == aState2) {
ok(true, aMsg);
return;
}
var got = "0";
if (aState1) {
got = statesToString(aIsExtraStates ? 0 : aState1,
aIsExtraStates ? aState1 : 0);
}
var expected = "0";
if (aState2) {
expected = statesToString(aIsExtraStates ? 0 : aState2,
aIsExtraStates ? aState2 : 0);
}
ok(false, aMsg + "got '" + got + "', expected '" + expected + "'");
}

Просмотреть файл

@ -22,25 +22,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
<script type="application/javascript">
function doTest()
{
// test (treeitem) selectable and selected states
testStates("treeitem_selected_true", (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_false", STATE_SELECTABLE, 0, STATE_SELECTED);
testStates("treeitem_selected_empty", 0, 0, (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_undefined", 0, 0, (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_absent", 0, 0, (STATE_SELECTABLE | STATE_SELECTED));
// test aria-pressed state mapping to roles PUSHBUTTON vs TOGGLEBUTTON
testRole("button_pressed_true", ROLE_TOGGLE_BUTTON);
testRole("button_pressed_false", ROLE_TOGGLE_BUTTON);
testRole("button_pressed_empty", ROLE_PUSHBUTTON);
testRole("button_pressed_undefined", ROLE_PUSHBUTTON);
testRole("button_pressed_absent", ROLE_PUSHBUTTON);
// test (menuitem) checkable and checked states
testStates("menuitem_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitem_checked_empty", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_undefined", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_absent", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
// test button aria-pressed states
testStates("button_pressed_true", STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_false", STATE_CHECKABLE, 0, STATE_PRESSED);
testStates("button_pressed_empty", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_undefined", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_absent", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
// test (checkbox) checkable and checked states
testStates("checkbox_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("checkbox_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("checkbox_checked_empty", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("checkbox_checked_undefined", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("checkbox_checked_empty", 0 , 0, STATE_CHECKABLE | STATE_CHECKED);
testStates("checkbox_checked_undefined", 0, 0, STATE_CHECKABLE | STATE_CHECKED);
testStates("checkbox_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test native checkbox checked state and aria-checked state (if conflict, native wins)
@ -49,27 +49,124 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
testStates("native_checkbox_nativechecked_ariaempty", (STATE_CHECKABLE | STATE_CHECKED));
testStates("native_checkbox_nativechecked_ariaundefined", (STATE_CHECKABLE | STATE_CHECKED));
testStates("native_checkbox_nativechecked_ariaabsent", (STATE_CHECKABLE | STATE_CHECKED));
testStates("native_checkbox_nativeunchecked_ariatrue", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("native_checkbox_nativeunchecked_ariafalse", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("native_checkbox_nativeunchecked_ariaempty", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("native_checkbox_nativeunchecked_ariaundefined", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("native_checkbox_nativeunchecked_ariaabsent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test button aria-pressed states
testStates("button_pressed_true", STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_false", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_empty", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_undefined", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
testStates("button_pressed_absent", 0, 0, STATE_PRESSED | STATE_CHECKABLE);
// test aria-pressed state mapping to roles PUSHBUTTON vs TOGGLEBUTTON
testRole("button_pressed_true", ROLE_TOGGLE_BUTTON);
testRole("button_pressed_false", ROLE_TOGGLE_BUTTON);
testRole("button_pressed_empty", ROLE_PUSHBUTTON);
testRole("button_pressed_undefined", ROLE_PUSHBUTTON);
testRole("button_pressed_absent", ROLE_PUSHBUTTON);
// test (checkbox) readonly states
testStates("checkbox_readonly_true", STATE_READONLY);
testStates("checkbox_readonly_false", 0, 0, STATE_READONLY);
testStates("checkbox_readonly_empty", 0, 0, STATE_READONLY);
testStates("checkbox_readonly_undefined", 0, 0, STATE_READONLY);
testStates("checkbox_readonly_absent", 0, 0, STATE_READONLY);
// test (checkbox) required states
testStates("checkbox_required_true", STATE_REQUIRED);
testStates("checkbox_required_false", 0, 0, STATE_REQUIRED);
testStates("checkbox_required_empty", 0, 0, STATE_REQUIRED);
testStates("checkbox_required_undefined", 0, 0, STATE_REQUIRED);
testStates("checkbox_required_absent", 0, 0, STATE_REQUIRED);
// test (checkbox) invalid states
testStates("checkbox_invalid_true", STATE_INVALID);
testStates("checkbox_invalid_false", 0, 0, STATE_INVALID);
testStates("checkbox_invalid_empty", 0, 0, STATE_INVALID);
testStates("checkbox_invalid_undefined", 0, 0, STATE_INVALID);
testStates("checkbox_invalid_absent", 0, 0, STATE_INVALID);
// test (checkbox) disabled states
testStates("checkbox_disabled_true", STATE_UNAVAILABLE);
testStates("checkbox_disabled_false", 0, 0, STATE_UNAVAILABLE);
testStates("checkbox_disabled_empty", 0, 0, STATE_UNAVAILABLE);
testStates("checkbox_disabled_undefined", 0, 0, STATE_UNAVAILABLE);
testStates("checkbox_disabled_absent", 0, 0, STATE_UNAVAILABLE);
// test (listbox) multiselectable states
testStates("listbox_multiselectable_true", STATE_MULTISELECTABLE | STATE_EXTSELECTABLE);
testStates("listbox_multiselectable_false", 0, 0, STATE_MULTISELECTABLE | STATE_EXTSELECTABLE);
testStates("listbox_multiselectable_empty", 0, 0, STATE_MULTISELECTABLE | STATE_EXTSELECTABLE);
testStates("listbox_multiselectable_undefined", 0, 0, STATE_MULTISELECTABLE | STATE_EXTSELECTABLE);
testStates("listbox_multiselectable_absent", 0, 0, STATE_MULTISELECTABLE | STATE_EXTSELECTABLE);
// test (listitem) checkable and checked states
testStates("listitem_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("listitem_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("listitem_checked_empty", 0 , 0, STATE_CHECKABLE | STATE_CHECKED);
testStates("listitem_checked_undefined", 0, 0, STATE_CHECKABLE | STATE_CHECKED);
testStates("listitem_checked_absent", 0, 0, STATE_CHECKABLE | STATE_CHECKED);
// test (menuitem) checkable and checked states
testStates("menuitem_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitem_checked_empty", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_undefined", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitem_checked_absent", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
// test (menuitemradio) checkable and checked states
testStates("menuitemradio_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemradio_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("menuitemradio_checked_empty", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemradio_checked_undefined", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("menuitemradio_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test (radio) checkable and checked states
testStates("radio_checked_true", (STATE_CHECKABLE | STATE_CHECKED));
testStates("radio_checked_false", STATE_CHECKABLE, 0, STATE_CHECKED);
testStates("radio_checked_empty", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("radio_checked_undefined", 0, 0, (STATE_CHECKABLE | STATE_CHECKED));
testStates("radio_checked_absent", STATE_CHECKABLE, 0, STATE_CHECKED);
// test (textbox) multiline states
testStates("textbox_multiline_true", 0, EXT_STATE_MULTI_LINE);
testStates("textbox_multiline_false", 0, EXT_STATE_SINGLE_LINE);
testStates("textbox_multiline_empty", 0, 0, 0, EXT_STATE_SINGLE_LINE | EXT_STATE_MULTI_LINE);
testStates("textbox_multiline_undefined", 0, 0, 0, EXT_STATE_SINGLE_LINE | EXT_STATE_MULTI_LINE);
testStates("textbox_multiline_absent", 0, EXT_STATE_SINGLE_LINE);
// test (textbox) readonly states
testStates("textbox_readonly_true", STATE_READONLY);
testStates("textbox_readonly_false", 0, EXT_STATE_EDITABLE, STATE_READONLY);
testStates("textbox_readonly_empty", 0, 0, STATE_READONLY, EXT_STATE_EDITABLE);
testStates("textbox_readonly_undefined", 0, 0, STATE_READONLY, EXT_STATE_EDITABLE);
testStates("textbox_readonly_absent", 0, EXT_STATE_EDITABLE, STATE_READONLY);
// test native textbox readonly state and aria-readonly state (if conflict, native wins)
testStates("native_textbox_nativereadonly_ariatrue", STATE_READONLY);
testStates("native_textbox_nativereadonly_ariafalse", STATE_READONLY);
testStates("native_textbox_nativereadonly_ariaempty", STATE_READONLY);
testStates("native_textbox_nativereadonly_ariaundefined", STATE_READONLY);
testStates("native_textbox_nativereadonly_ariaabsent", STATE_READONLY);
testStates("native_textbox_nativeeditable_ariatrue", 0, 0, STATE_READONLY);
testStates("native_textbox_nativeeditable_ariafalse", 0, 0, STATE_READONLY);
testStates("native_textbox_nativeeditable_ariaempty", 0, 0, STATE_READONLY);
testStates("native_textbox_nativeeditable_ariaundefined", 0, 0, STATE_READONLY);
testStates("native_textbox_nativeeditable_ariaabsent", 0, 0, STATE_READONLY);
// test (treeitem) selectable and selected states
testStates("treeitem_selected_true", (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_false", STATE_SELECTABLE, 0, STATE_SELECTED);
testStates("treeitem_selected_empty", 0, 0, (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_undefined", 0, 0, (STATE_SELECTABLE | STATE_SELECTED));
testStates("treeitem_selected_absent", 0, 0, (STATE_SELECTABLE | STATE_SELECTED));
// test (treeitem) haspopup states
testStates("treeitem_haspopup_true", STATE_HASPOPUP);
testStates("treeitem_haspopup_false", 0, 0, STATE_HASPOPUP);
testStates("treeitem_haspopup_empty", 0, 0, STATE_HASPOPUP);
testStates("treeitem_haspopup_undefined", 0, 0, STATE_HASPOPUP);
testStates("treeitem_haspopup_absent", 0, 0, STATE_HASPOPUP);
// test (treeitem) expandable and expanded/collapsed states
testStates("treeitem_expanded_true", STATE_EXPANDED, EXT_STATE_EXPANDABLE);
testStates("treeitem_expanded_false", STATE_COLLAPSED, EXT_STATE_EXPANDABLE);
testStates("treeitem_expanded_empty", 0, 0, STATE_EXPANDED | STATE_COLLAPSED, EXT_STATE_EXPANDABLE);
testStates("treeitem_expanded_undefined", 0, 0, STATE_EXPANDED | STATE_COLLAPSED, EXT_STATE_EXPANDABLE);
testStates("treeitem_expanded_absent", 0, 0, STATE_EXPANDED | STATE_COLLAPSED, EXT_STATE_EXPANDABLE);
SimpleTest.finish();
}
@ -79,48 +176,151 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452388
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=452388">Mozilla Bug 452388</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=452388">
Mozilla Bug 452388
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=499653"
title="Unify ARIA state attributes mapping rules">
Mozilla Bug 499653
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="treeitem_selected_true" role="treeitem" aria-selected="true">This treeitem has aria-selected="true" and should get STATE_SELECTABLE. It should also get STATE_SELECTED.</div>
<div id="treeitem_selected_false" role="treeitem" aria-selected="false">This treeitem has aria-selected="false" and should get STATE_SELECTABLE.</div>
<div id="treeitem_selected_empty" role="treeitem" aria-selected="">This treeitem has aria-selected="" and should <emph>not</emph> get STATE_SELECTABLE.</div>
<div id="treeitem_selected_undefined" role="treeitem" aria-selected="undefined">This treeitem has aria-selected="undefined" and should <emph>not</emph> get STATE_SELECTABLE.</div>
<div id="treeitem_selected_absent" role="treeitem">This treeitem has <emph>no</emph> aria-selected attribute and should <emph>not</emph> get STATE_SELECTABLE.</div>
<div id="menuitem_checked_true" role="menuitem" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="menuitem_checked_false" role="menuitem" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="menuitem_checked_empty" role="menuitem" aria-checked="">This menuitem has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitem_checked_undefined" role="menuitem" aria-checked="undefined">This menuitem has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitem_checked_absent" role="menuitem">This menuitem has <emph>no</emph> aria-checked attribute and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="button_pressed_true" role="button" aria-pressed="true">This button has aria-pressed="true" and should get ROLE_TOGGLE_BUTTON. It should also get STATE_PRESSED.</div>
<div id="button_pressed_false" role="button" aria-pressed="false">This button has aria-pressed="false" and should get ROLE_TOGGLE_BUTTON.</div>
<div id="button_pressed_empty" role="button" aria-pressed="">This button has aria-pressed="" and should <emph>not</emph> get ROLE_BUTTON.</div>
<div id="button_pressed_undefined" role="button" aria-pressed="undefined">This button has aria-pressed="undefined" and should <emph>not</emph> get ROLE_TOGGLE_BUTTON.</div>
<div id="button_pressed_absent" role="button">This button has <emph>no</emph> aria-pressed attribute and should <emph>not</emph> get ROLE_TOGGLE_BUTTON.</div>
<div id="checkbox_checked_true" role="checkbox" aria-checked="true">This checkbox has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="checkbox_checked_false" role="checkbox" aria-checked="false">This checkbox has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="checkbox_checked_empty" role="checkbox" aria-checked="">This checkbox has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="checkbox_checked_undefined" role="checkbox" aria-checked="undefined">This checkbox has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="checkbox_checked_absent" role="checkbox">This checkbox has <emph>no</emph> aria-checked attribute and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="checkbox_checked_absent" role="checkbox">This checkbox has <emph>no</emph> aria-checked attribute and should get STATE_CHECKABLE.</div>
<form action="">
<input id="native_checkbox_nativechecked_ariatrue" type="checkbox" checked="checked" aria-checked="true"/>
<input id="native_checkbox_nativechecked_ariafalse" type="checkbox" checked="checked" aria-checked="false"/>
<input id="native_checkbox_nativechecked_ariaempty" type="checkbox" checked="checked" aria-checked=""/>
<input id="native_checkbox_nativechecked_ariaundefined" type="checkbox" checked="checked" aria-checked="undefined"/>
<input id="native_checkbox_nativechecked_ariaabsent" type="checkbox" checked="checked" aria-checked="false"/>
<input id="native_checkbox_nativechecked_ariaabsent" type="checkbox" checked="checked"/>
<input id="native_checkbox_nativeunchecked_ariatrue" type="checkbox" aria-checked="true"/>
<input id="native_checkbox_nativeunchecked_ariafalse" type="checkbox" aria-checked="false"/>
<input id="native_checkbox_nativeunchecked_ariaempty" type="checkbox" aria-checked=""/>
<input id="native_checkbox_nativeunchecked_ariaundefined" type="checkbox" aria-checked="undefined"/>
<input id="native_checkbox_nativeunchecked_ariaabsent" type="checkbox" aria-checked="false"/>
<input id="native_checkbox_nativeunchecked_ariaabsent" type="checkbox"/>
</form>
<div id="button_pressed_true" role="button" aria-pressed="true">This button has aria-pressed="true" and should get ROLE_TOGGLE_BUTTON. It should also get STATE_PRESSED.</div>
<div id="button_pressed_false" role="button" aria-pressed="false">This button has aria-pressed="false" and should get ROLE_TOGGLE_BUTTON.</div>
<div id="button_pressed_empty" role="button" aria-pressed="">This button has aria-pressed="" and should <emph>not</emph> get ROLE_BUTTON.</div>
<div id="button_pressed_undefined" role="button" aria-pressed="undefined">This button has aria-pressed="undefined" and should <emph>not</emph> get ROLE_TOGGLE_BUTTON.</div>
<div id="button_pressed_absent" role="button">This button has <emph>no</emph> aria-pressed attribute and should <emph>not</emph> get ROLE_TOGGLE_BUTTON.</div>
<div id="checkbox_readonly_true" role="checkbox" aria-readonly="true">This checkbox has aria-readonly="true" and should get STATE_READONLY.</div>
<div id="checkbox_readonly_false" role="checkbox" aria-readonly="false">This checkbox has aria-readonly="false" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="checkbox_readonly_empty" role="checkbox" aria-readonly="">This checkbox has aria-readonly="" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="checkbox_readonly_undefined" role="checkbox" aria-readonly="undefined">This checkbox has aria-readonly="undefined" and should <emph>not</emph> get STATE_READONLY.</div>
<div id="checkbox_readonly_absent" role="checkbox">This checkbox has <emph>no</emph> aria-readonly attribute and should <emph>not</emph> get STATE_READONLY.</div>
<div id="checkbox_required_true" role="checkbox" aria-required="true">This checkbox has aria-required="true" and should get STATE_REQUIRED.</div>
<div id="checkbox_required_false" role="checkbox" aria-required="false">This checkbox has aria-required="false" and should <emph>not</emph> get STATE_REQUIRED.</div>
<div id="checkbox_required_empty" role="checkbox" aria-required="">This checkbox has aria-required="" and should <emph>not</emph> get STATE_REQUIRED.</div>
<div id="checkbox_required_undefined" role="checkbox" aria-required="undefined">This checkbox has aria-required="undefined" and should <emph>not</emph> get STATE_REQUIRED.</div>
<div id="checkbox_required_absent" role="checkbox">This checkbox has <emph>no</emph> aria-required attribute and should <emph>not</emph> get STATE_REQUIRED.</div>
<div id="checkbox_invalid_true" role="checkbox" aria-invalid="true">This checkbox has aria-invalid="true" and should get STATE_INVALID.</div>
<div id="checkbox_invalid_false" role="checkbox" aria-invalid="false">This checkbox has aria-invalid="false" and should <emph>not</emph> get STATE_INVALID.</div>
<div id="checkbox_invalid_empty" role="checkbox" aria-invalid="">This checkbox has aria-invalid="" and should <emph>not</emph> get STATE_INVALID.</div>
<div id="checkbox_invalid_undefined" role="checkbox" aria-invalid="undefined">This checkbox has aria-invalid="undefined" and should <emph>not</emph> get STATE_INVALID.</div>
<div id="checkbox_invalid_absent" role="checkbox">This checkbox has <emph>no</emph> aria-invalid attribute and should <emph>not</emph> get STATE_INVALID.</div>
<div id="checkbox_disabled_true" role="checkbox" aria-disabled="true" tabindex="0">This checkbox has aria-disabled="true" and should get STATE_DISABLED.</div>
<div id="checkbox_disabled_false" role="checkbox" aria-disabled="false">This checkbox has aria-disabled="false" and should <emph>not</emph> get STATE_DISABLED.</div>
<div id="checkbox_disabled_empty" role="checkbox" aria-disabled="">This checkbox has aria-disabled="" and should <emph>not</emph> get STATE_DISABLED.</div>
<div id="checkbox_disabled_undefined" role="checkbox" aria-disabled="undefined">This checkbox has aria-disabled="undefined" and should <emph>not</emph> get STATE_DISABLED.</div>
<div id="checkbox_disabled_absent" role="checkbox">This checkbox has <emph>no</emph> aria-disabled attribute and should <emph>not</emph> get STATE_DISABLED.</div>
<div id="listbox_multiselectable_true" role="listbox" aria-multiselectable="true">
<div id="listitem_checked_true" role="listitem" aria-checked="true">item</div>
</div>
<div id="listbox_multiselectable_false" role="listbox" aria-multiselectable="false">
<div id="listitem_checked_false" role="listitem" aria-checked="false">item</div>
</div>
<div id="listbox_multiselectable_empty" role="listbox" aria-multiselectable="">
<div id="listitem_checked_empty" role="listitem" aria-checked="">item</div>
</div>
<div id="listbox_multiselectable_undefined" role="listbox" aria-multiselectable="undefined">
<div id="listitem_checked_undefined" role="listitem" aria-checked="undefined">item</div>
</div>
<div id="listbox_multiselectable_absent" role="listbox">
<div id="listitem_checked_absent" role="listitem">item</div>
</div>
<div role="menu">
<div id="menuitem_checked_true" role="menuitem" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="menuitem_checked_false" role="menuitem" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="menuitem_checked_empty" role="menuitem" aria-checked="">This menuitem has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitem_checked_undefined" role="menuitem" aria-checked="undefined">This menuitem has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitem_checked_absent" role="menuitem">This menuitem has <emph>no</emph> aria-checked attribute and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitemradio_checked_true" role="menuitemradio" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_checked.</div>
<div id="menuitemradio_checked_false" role="menuitemradio" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="menuitemradio_checked_empty" role="menuitemradio" aria-checked="">This menuitem has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitemradio_checked_undefined" role="menuitemradio" aria-checked="undefined">This menuitem has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="menuitemradio_checked_absent" role="menuitemradio">This menuitem has <emph>no</emph> aria-checked attribute but should get STATE_CHECKABLE.</div>
</div>
<div id="radio_checked_true" role="radio" aria-checked="true">This menuitem has aria-checked="true" and should get STATE_CHECKABLE. It should also get STATE_CHECKED.</div>
<div id="radio_checked_false" role="radio" aria-checked="false">This menuitem has aria-checked="false" and should get STATE_CHECKABLE.</div>
<div id="radio_checked_empty" role="radio" aria-checked="">This menuitem has aria-checked="" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="radio_checked_undefined" role="radio" aria-checked="undefined">This menuitem has aria-checked="undefined" and should <emph>not</emph> get STATE_CHECKABLE.</div>
<div id="radio_checked_absent" role="radio">This menuitem has <emph>no</emph> aria-checked attribute but should get STATE_CHECKABLE.</div>
<div id="textbox_readonly_true" role="textbox" aria-readonly="true"></div>
<div id="textbox_readonly_false" role="textbox" aria-readonly="false"></div>
<div id="textbox_readonly_empty" role="textbox" aria-readonly=""></div>
<div id="textbox_readonly_undefined" role="textbox" aria-readonly="undefined"></div>
<div id="textbox_readonly_absent" role="textbox"></div>
<div id="textbox_multiline_true" role="textbox" aria-multiline="true"></div>
<div id="textbox_multiline_false" role="textbox" aria-multiline="false"></div>
<div id="textbox_multiline_empty" role="textbox" aria-multiline=""></div>
<div id="textbox_multiline_undefined" role="textbox" aria-multiline="undefined"></div>
<div id="textbox_multiline_absent" role="textbox"></div>
<form action="">
<input id="native_textbox_nativereadonly_ariatrue" readonly="readonly" aria-readonly="true"/>
<input id="native_textbox_nativereadonly_ariafalse" readonly="readonly" aria-readonly="false"/>
<input id="native_textbox_nativereadonly_ariaempty" readonly="readonly" aria-readonly=""/>
<input id="native_textbox_nativereadonly_ariaundefined" readonly="readonly" aria-readonly="undefined"/>
<input id="native_textbox_nativereadonly_ariaabsent" readonly="readonly"/>
<input id="native_textbox_nativeeditable_ariatrue" aria-readonly="true"/>
<input id="native_textbox_nativeeditable_ariafalse" aria-readonly="false"/>
<input id="native_textbox_nativeeditable_ariaempty" aria-readonly=""/>
<input id="native_textbox_nativeeditable_ariaundefined" aria-readonly="undefined"/>
<input id="native_textbox_nativeeditable_ariaabsent"/>
</form>
<div role="tree">
<div id="treeitem_selected_true" role="treeitem" aria-selected="true">This treeitem has aria-selected="true" and should get STATE_SELECTABLE. It should also get STATE_SELECTED.</div>
<div id="treeitem_selected_false" role="treeitem" aria-selected="false">This treeitem has aria-selected="false" and should get STATE_SELECTABLE.</div>
<div id="treeitem_selected_empty" role="treeitem" aria-selected="">This treeitem has aria-selected="" and should <emph>not</emph> get STATE_SELECTABLE.</div>
<div id="treeitem_selected_undefined" role="treeitem" aria-selected="undefined">This treeitem has aria-selected="undefined" and should <emph>not</emph> get STATE_SELECTABLE.</div>
<div id="treeitem_selected_absent" role="treeitem">This treeitem has <emph>no</emph> aria-selected attribute and should <emph>not</emph> get STATE_SELECTABLE.</div>
<div id="treeitem_haspopup_true" role="treeitem" aria-haspopup="true">This treeitem has aria-haspopup="true" and should get STATE_HASPOPUP.</div>
<div id="treeitem_haspopup_false" role="treeitem" aria-haspopup="false">This treeitem has aria-haspopup="false" and should get STATE_HASPOPUP.</div>
<div id="treeitem_haspopup_empty" role="treeitem" aria-haspopup="">This treeitem has aria-haspopup="" and should <emph>not</emph> get STATE_HASPOPUP.</div>
<div id="treeitem_haspopup_undefined" role="treeitem" aria-haspopup="undefined">This treeitem has aria-haspopup="undefined" and should <emph>not</emph> get STATE_HASPOPUP.</div>
<div id="treeitem_haspopup_absent" role="treeitem">This treeitem has <emph>no</emph> aria-haspopup attribute and should <emph>not</emph> get STATE_HASPOPUP.</div>
<div id="treeitem_expanded_true" role="treeitem" aria-expanded="true">This treeitem has aria-expanded="true" and should get STATE_EXPANDABLE. It should also get STATE_EXPANDED.</div>
<div id="treeitem_expanded_false" role="treeitem" aria-expanded="false">This treeitem has aria-expanded="false" and should get STATE_EXPANDABLE. It should also get STATE_COLLAPSED.</div>
<div id="treeitem_expanded_empty" role="treeitem" aria-expanded="">This treeitem has aria-expanded="" and should <emph>not</emph> get STATE_EXPANDABLE.</div>
<div id="treeitem_expanded_undefined" role="treeitem" aria-expanded="undefined">This treeitem has aria-expanded="undefined" and should <emph>not</emph> get STATE_EXPANDABLE.</div>
<div id="treeitem_expanded_absent" role="treeitem">This treeitem has <emph>no</emph> aria-expanded attribute and should <emph>not</emph> get STATE_EXPANDABLE.</div>
</div>
</body>
</html>

Просмотреть файл

@ -31,9 +31,24 @@
<script type="application/javascript">
function doTest()
{
// aria_autocomplete
testStates("textbox_autocomplete_inline", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
testStates("textbox_autocomplete_list", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
testStates("textbox_autocomplete_both", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
testStates("combobox_autocomplete_inline", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
testStates("combobox_autocomplete_list", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
testStates("combobox_autocomplete_both", STATE_HASPOPUP, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
// aria-busy
testStates("textbox_busy_false", 0, 0, STATE_BUSY);
testStates("textbox_busy_true", STATE_BUSY);
testStates("textbox_busy_error", STATE_INVALID);
// aria-expanded
testStates("combobox", STATE_COLLAPSED);
testStates("combobox_expanded", STATE_EXPANDED);
// tri-state checkbox
var checkboxElem = getNode("check1");
if (checkboxElem) {
testStates(checkboxElem, STATE_CHECKED);
@ -43,6 +58,7 @@
testStates(checkboxElem, STATE_MIXED, 0);
}
// aria-checked
testStates("aria_checked_checkbox", STATE_CHECKED);
testStates("aria_mixed_checkbox", STATE_MIXED);
@ -50,6 +66,7 @@
// disabled, too. See bug 429285.
testStatesInSubtree("group", STATE_UNAVAILABLE);
// offscreen test
testStates("aria_offscreen_textbox", STATE_OFFSCREEN);
SimpleTest.finish();
@ -73,13 +90,28 @@
title="Propagate aria-disabled to descendants">
Mozilla Bug 429285
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=499653"
title="Unify ARIA state attributes mapping rules">
Mozilla Bug 499653
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="combobox" role="combobox">combobox</div>
<div id="textbox_autocomplete_inline" role="textbox" aria-autocomplete="inline"></div>
<div id="textbox_autocomplete_list" role="textbox" aria-autocomplete="list"></div>
<div id="textbox_autocomplete_both" role="textbox" aria-autocomplete="both"></div>
<div id="combobox_autocomplete_inline" role="combobox" aria-autocomplete="inline"></div>
<div id="combobox_autocomplete_list" role="combobox" aria-autocomplete="list"></div>
<div id="combobox_autocomplete_both" role="combobox" aria-autocomplete="both"></div>
<div id="textbox_busy_false" role="textbox" aria-busy="false"></div>
<div id="textbox_busy_true" role="textbox" aria-busy="true"></div>
<div id="textbox_busy_error" role="textbox" aria-busy="error"></div>
<div id="combobox" role="combobox">combobox</div>
<div id="combobox_expanded" role="combobox"
aria-expanded="true">combobox</div>

Просмотреть файл

@ -337,6 +337,7 @@
<li>Matthew Gregan</li>
<li>Will Guaraldi</li>
<li>Adam Guthrie</li>
<li>Mohammad Reza Haghighat</li>
<li>Andrei Hajdukewycz</li>
<li>Trevor Hardcastle</li>
<li>Basil Hashem</li>

Просмотреть файл

@ -129,8 +129,10 @@
<field name="_chevron">document.getAnonymousElementByAttribute(this, "class", "chevron")</field>
<field name="_openedMenuButton">null</field>
<field name="_allowPopupShowing">true</field>
<field name="_result">null</field>
<field name="_resultNode">null</field>
<!-- nsIPlacesView -->
<method name="getResult">
@ -559,7 +561,7 @@
this._self.insertBefore(button, children[aNewIndex]);
if (chevronPopup) {
// Maintain chevron in sync
menuitem = chevronPopup.childNodes[i];
var menuitem = chevronPopup.childNodes[i];
chevronPopup.removeChild(menuitem);
chevronPopup.insertBefore(menuitem,
chevronPopup.childNodes[aNewIndex]);
@ -950,7 +952,7 @@
// * Timer to turn off indicator bar.
if (aTimer == this._ibTimer) {
ib = this._dropIndicatorBar.removeAttribute('dragging');
this._dropIndicatorBar.removeAttribute('dragging');
this._ibTimer = null;
}
@ -1195,14 +1197,17 @@
}
]]></handler>
#ifdef XP_UNIX
#ifndef XP_MACOSX
<handler event="mousedown"><![CDATA[
var target = event.target;
if (event.button == 0 &&
target.localName == "toolbarbutton" &&
target.getAttribute("type") == "menu") {
this._allowPopupShowing = false;
// This is a container, we will open the menu if the user clicks
// or drag toward down or after a delay
// On Linux we can open the popup only after a delay.
// Indeed as soon as the menupopup opens we are unable to start a
// drag event. See bug 500081 for details.
this._mouseDownTimer = Cc["@mozilla.org/timer;1"]
.createInstance(Ci.nsITimer);
var callback = {
@ -1214,15 +1219,12 @@
}
};
this._mouseDownTimer.initWithCallback(callback, 500,
this._mouseDownTimer.initWithCallback(callback, 300,
Ci.nsITimer.TYPE_ONE_SHOT);
}
else {
// allow opening popups, like the chevron and context menus
this._allowPopupShowing = true;
}
]]></handler>
#endif
#endif
<handler event="mouseup"><![CDATA[
if (event.button != 0)
return;

Просмотреть файл

@ -2766,7 +2766,7 @@ SessionStoreService.prototype = {
let normalWindowIndex = 0;
// try to find a non-popup window in this._closedWindows
while (normalWindowIndex < this._closedWindows.length &&
this._closedWindows[normalWindowIndex].isPopup)
!!this._closedWindows[normalWindowIndex].isPopup)
normalWindowIndex++;
if (normalWindowIndex >= maxWindowsUndo)
spliceTo = normalWindowIndex + 1;

Просмотреть файл

@ -113,7 +113,7 @@ function test() {
function test_behavior (callback) {
// helper function that does the actual testing
function openWindowRec(windowsToOpen, expectedResults) {
function openWindowRec(windowsToOpen, expectedResults, recCallback) {
// do actual checking
if (!windowsToOpen.length) {
let closedWindowData = JSON.parse(ss.getClosedWindowData());
@ -130,7 +130,7 @@ function test() {
"There were " + oResults.normal + " normal windows to repoen");
// cleanup & return
executeSoon(callback);
executeSoon(recCallback);
return;
}
// hack to force window to be considered a popup (toolbar=no didn't work)
@ -149,7 +149,7 @@ function test() {
executeSoon(function() {
window.close();
executeSoon(function() {
openWindowRec(windowsToOpen, expectedResults);
openWindowRec(windowsToOpen, expectedResults, recCallback);
});
});
}, true);

Просмотреть файл

@ -641,9 +641,7 @@ msvcr80.dll
#else
mozcrt19.dll
#endif
xpicleanup.exe
#else
xpicleanup
#endif
xpicleanup@BIN_SUFFIX@
chrome.manifest
install.rdf

Просмотреть файл

@ -64,8 +64,6 @@ vpath book%.inc @srcdir@/en-US/profile
endif
run_for_effects_too := if ! test -d $(DIST)/branding; then $(NSINSTALL) -D $(DIST)/branding; fi)
ifdef MOZ_BRANDING_DIRECTORY
SUBMAKEFILES += \
$(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/Makefile \
@ -104,6 +102,11 @@ include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/toolkit/locales/l10n.mk
$(STAGEDIST): $(DIST)/branding
$(DIST)/branding:
$(NSINSTALL) -D $@
libs::
@if test -f "$(LOCALE_SRCDIR)/existing-profile-defaults.js"; then \
$(PERL) $(topsrcdir)/config/preprocessor.pl $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
@ -284,7 +287,12 @@ endif
ident:
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py $(STAGEDIST)/application.ini App SourceStamp
@printf "fx_revision "
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
$(STAGEDIST)/application.ini App SourceStamp
@printf "buildid "
@$(PYTHON) $(topsrcdir)/config/printconfigsetting.py \
$(STAGEDIST)/application.ini App BuildID
#These make targets call prepare-repackages by setting different UPLOAD_DIR
prepare-upload-latest-%:

Просмотреть файл

@ -1214,7 +1214,7 @@ tabpanels {
border: 1px dotted transparent;
}
.tabbrowser-tab[selected="true"]:focus > .tab-text {
.tabbrowser-tab:focus > .tab-text {
border: 1px dotted -moz-DialogText;
}

Просмотреть файл

@ -1561,7 +1561,7 @@ tabbrowser > tabbox {
background-color: -moz-mac-chrome-active;
}
.tabbrowser-tab[selected="true"]:focus > .tab-text {
.tabbrowser-tab:focus > .tab-text {
-moz-box-shadow: 0 0 4px -moz-mac-focusring,
0 0 4px -moz-mac-focusring,
0 0 3px -moz-mac-focusring,

Просмотреть файл

@ -1404,7 +1404,7 @@ tabpanels {
border: 1px dotted transparent;
}
.tabbrowser-tab[selected="true"]:focus > .tab-text {
.tabbrowser-tab:focus > .tab-text {
border: 1px dotted -moz-DialogText;
}

Просмотреть файл

@ -62,8 +62,8 @@
ac_add_options() {
for _opt
do
# Escape shell characters, space, tab, dollar, quote, backslash.
_opt=`echo $_opt | sed -e 's/\([\ \ \$\"\\]\)/\\\\\1/g;s/@\([^@]*\)@/\$\1/g;'`
# Escape shell characters, space, tab, dollar, quote, backslash, parentheses.
_opt=`echo $_opt | sed -e 's/\([\ \ \$\"\\\(\)]\)/\\\\\1/g;s/@\([^@]*\)@/\$\1/g;'`
_opt=`echo $_opt | sed -e 's/@\([^@]*\)@/\$(\1)/g'`
# Avoid adding duplicates

Просмотреть файл

@ -129,7 +129,7 @@ export::
-DMOZ_NATIVE_PNG=$(MOZ_NATIVE_PNG) \
-DMOZ_NATIVE_JPEG=$(MOZ_NATIVE_JPEG) \
$(srcdir)/system-headers | $(PERL) $(topsrcdir)/nsprpub/config/make-system-wrappers.pl system_wrappers
$(INSTALL) system_wrappers $(DIST)/include
$(INSTALL) system_wrappers $(DIST)
GARBAGE_DIRS += system_wrappers
endif

Просмотреть файл

@ -546,9 +546,6 @@ STATIC_LIBIDL = @STATIC_LIBIDL@
MOZ_NATIVE_MAKEDEPEND = @SYSTEM_MAKEDEPEND@
# Used for LD_LIBRARY_PATH
LIBS_PATH = @LIBS_PATH@
MOZ_AUTO_DEPS = @MOZ_AUTO_DEPS@
COMPILER_DEPEND = @COMPILER_DEPEND@
MDDEPDIR := @MDDEPDIR@

Просмотреть файл

@ -946,12 +946,6 @@ endif # NO_PROFILE_GUIDED_OPTIMIZE
checkout:
$(MAKE) -C $(topsrcdir) -f client.mk checkout
run_viewer: $(FINAL_TARGET)/viewer
cd $(FINAL_TARGET); \
MOZILLA_FIVE_HOME=`pwd` \
LD_LIBRARY_PATH=".:$(LIBS_PATH):$$LD_LIBRARY_PATH" \
viewer
clean clobber realclean clobber_all:: $(SUBMAKEFILES)
-rm -f $(ALL_TRASH)
-rm -rf $(ALL_TRASH_DIRS)
@ -2106,7 +2100,7 @@ endif
# Fake targets. Always run these rules, even if a file/directory with that
# name already exists.
#
.PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_viewer run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE
.PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE
# Used as a dependency to force targets to rebuild
FORCE:

Просмотреть файл

@ -3032,7 +3032,7 @@ EOF
])
if test "$ac_cv_have_visibility_builtin_bug" = "no" -a \
"$ac_cv_have_visibility_class_bug" = "no"; then
VISIBILITY_FLAGS='-I$(DIST)/include/system_wrappers -include $(topsrcdir)/config/gcc_hidden.h'
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(topsrcdir)/config/gcc_hidden.h'
WRAP_SYSTEM_INCLUDES=1
else
VISIBILITY_FLAGS='-fvisibility=hidden'
@ -8325,16 +8325,6 @@ if test "$ACCESSIBILITY" -a "$MOZ_ENABLE_GTK2" ; then
AC_DEFINE_UNQUOTED(ATK_REV_VERSION, $ATK_REV_VERSION)
fi
# Used for LD_LIBRARY_PATH of run_viewer target
LIBS_PATH=
for lib_arg in $NSPR_LIBS $TK_LIBS; do
case $lib_arg in
-L* ) LIBS_PATH="${LIBS_PATH:+$LIBS_PATH:}"`expr $lib_arg : "-L\(.*\)"` ;;
* ) ;;
esac
done
AC_SUBST(LIBS_PATH)
dnl ========================================================
dnl Use cygwin wrapper for win32 builds, except MSYS/MinGW
dnl ========================================================

Просмотреть файл

@ -64,7 +64,7 @@ interface nsIURI;
* sufficient, when combined with the imageBlockingStatus information.)
*/
[scriptable, uuid(7744c6d3-5c60-4b7b-a526-4fe9d5ac7e97)]
[scriptable, uuid(e036857e-3417-4812-a5f2-89668a616781)]
interface nsIImageLoadingContent : imgIDecoderObserver
{
/**
@ -167,4 +167,12 @@ interface nsIImageLoadingContent : imgIDecoderObserver
* @throws NS_ERROR_NOT_AVAILABLE if there is no current URI to reload
*/
void forceReload();
/**
* Enables/disables image state forcing. When |aForce| is PR_TRUE, we force
* nsImageLoadingContent::ImageState() to return |aState|. Call again with |aForce|
* as PR_FALSE to revert ImageState() to its original behaviour.
*/
void forceImageState(in boolean aForce, in long aState);
};

Просмотреть файл

@ -109,7 +109,8 @@ nsImageLoadingContent::nsImageLoadingContent()
// mBroken starts out true, since an image without a URI is broken....
mBroken(PR_TRUE),
mUserDisabled(PR_FALSE),
mSuppressed(PR_FALSE)
mSuppressed(PR_FALSE),
mIsImageStateForced(PR_FALSE)
{
if (!nsContentUtils::GetImgLoader()) {
mLoadingEnabled = PR_FALSE;
@ -617,10 +618,18 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
return NS_OK;
}
nsresult
nsImageLoadingContent::ForceImageState(PRBool aForce, PRInt32 aState)
{
mIsImageStateForced = aForce;
mForcedImageState = aState;
return NS_OK;
}
PRInt32
nsImageLoadingContent::ImageState() const
{
return
return mIsImageStateForced ? mForcedImageState :
(mBroken * NS_EVENT_STATE_BROKEN) |
(mUserDisabled * NS_EVENT_STATE_USERDISABLED) |
(mSuppressed * NS_EVENT_STATE_SUPPRESSED) |

Просмотреть файл

@ -260,10 +260,21 @@ private:
*/
ImageObserver mObserverList;
/**
* When mIsImageStateForced is true, this holds the ImageState that we'll
* return in ImageState().
*/
PRInt32 mForcedImageState;
PRInt16 mImageBlockingStatus;
PRPackedBool mLoadingEnabled : 1;
PRPackedBool mStartingLoad : 1;
/**
* When true, we return mForcedImageState from ImageState().
*/
PRPackedBool mIsImageStateForced : 1;
/**
* The state we had the last time we checked whether we needed to notify the
* document of a state change. These are maintained by UpdateImageState.

Просмотреть файл

@ -85,8 +85,6 @@
#include "nsObjectLoadingContent.h"
#include "mozAutoDocUpdate.h"
static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
#ifdef PR_LOGGING
static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
#endif
@ -301,7 +299,7 @@ IsSupportedImage(const nsCString& aMimeType)
static PRBool
IsSupportedPlugin(const nsCString& aMIMEType)
{
nsCOMPtr<nsIPluginHost> host(do_GetService("@mozilla.org/plugin/host;1"));
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
if (!host) {
return PR_FALSE;
}
@ -339,7 +337,7 @@ IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
if (ext.IsEmpty())
return PR_FALSE;
nsCOMPtr<nsIPluginHost> host(do_GetService("@mozilla.org/plugin/host;1"));
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
const char* typeFromExt;
if (host &&
NS_SUCCEEDED(host->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
@ -1584,7 +1582,7 @@ nsObjectLoadingContent::TypeForClassID(const nsAString& aClassID,
nsACString& aType)
{
// Need a plugin host for any class id support
nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(kCPluginManagerCID));
nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
if (!pluginHost) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -1834,7 +1832,7 @@ nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
/* static */ PluginSupportState
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
{
nsCOMPtr<nsIPluginHost> host(do_GetService("@mozilla.org/plugin/host;1"));
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
if (!host) {
return ePluginUnsupported;
}

Просмотреть файл

@ -80,6 +80,8 @@ categoryManager.addCategoryEntry("content-policy", policyName, policyName, false
var tests = ["SCRIPT", "IMAGE", "STYLESHEET", "OBJECT", "DOCUMENT", "SUBDOCUMENT", "XBL", "XMLHTTPREQUEST"];
var curTest = -1;
var div;
SimpleTest.waitForExplicitFinish();
setTimeout(runNextTest, 0);
@ -89,6 +91,12 @@ function runNextTest() {
if (curTest >= 0) {
var type = "TYPE_" + tests[curTest];
is(lastContentType, Ci.nsIContentPolicy[type], "Content policies triggered for " + type);
if (tests[curTest] == "XBL")
{
//XXX Removing binding to work-around a memory leak (bugs 478528, 499735).
document.removeBinding(div, testURL);
}
}
curTest++;
@ -165,7 +173,7 @@ function request_subdocument() {
function request_xbl() {
var content = $("content");
var div = document.createElement("div");
div = document.createElement("div");
content.appendChild(div);
document.addBinding(div, testURL);

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -15,11 +15,10 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2003
* Vladimir Vukicevic <vladimir@pobox.com>
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Original Author: Aaron Leventhal (aaronl@netscape.com)
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
@ -36,32 +35,60 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "prmem.h"
interface nsIAccessNode;
interface nsIContent;
#include "nsIServiceManager.h"
[uuid(fa9cafac-9562-49ad-afcf-911ab1e4e4fb)]
#include "nsIDOMDocument.h"
#include "nsIDocument.h"
#include "nsIDOMCanvasRenderingContext2D.h"
#include "nsICanvasRenderingContextInternal.h"
#include "nsICanvasElement.h"
#include "nsIPrincipal.h"
#include "nsINode.h"
interface nsPIAccessibleDocument : nsISupports
#include "nsGfxCIID.h"
#include "nsTArray.h"
#include "CanvasUtils.h"
using namespace mozilla;
void
CanvasUtils::DoDrawImageSecurityCheck(nsICanvasElement *aCanvasElement,
nsIPrincipal *aPrincipal,
PRBool forceWriteOnly)
{
/**
* Find the accessible object in the accessibility cache that
* corresponds to aStartNode or the first ancestor of aStartNode
* that has an accessible object associated with it.
* Clear that accessible object's parent's cache of accessible children and
* and remove the accessible object and any decendents from the accessible cache.
* New accessible objects will be created and cached again on demand.
* @param aChangeContent The child that is changing
* @param aEvent The event from nsIAccessibleEvent that caused the change:
* Must be one of: EVENT_REORDER (change),
* EVENT_SHOW (make visible or create) or
* EVENT_HIDE (destroy or hide)
*/
void invalidateCacheSubtree(in nsIContent aChangeContent,
in PRUint32 aChangeEvent);
void cacheAccessNode(in voidPtr aUniqueID, in nsIAccessNode aAccessNode);
void flushPendingEvents();
void fireDocLoadEvents(in PRUint32 aEventType);
void fireAnchorJumpEvent();
};
// Callers should ensure that mCanvasElement is non-null before calling this
if (!aCanvasElement) {
NS_WARNING("DoDrawImageSecurityCheck called without canvas element!");
return;
}
if (aCanvasElement->IsWriteOnly())
return;
// If we explicitly set WriteOnly just do it and get out
if (forceWriteOnly) {
aCanvasElement->SetWriteOnly();
return;
}
if (aPrincipal == nsnull)
return;
nsCOMPtr<nsINode> elem = do_QueryInterface(aCanvasElement);
if (elem) { // XXXbz How could this actually be null?
PRBool subsumes;
nsresult rv =
elem->NodePrincipal()->Subsumes(aPrincipal, &subsumes);
if (NS_SUCCEEDED(rv) && subsumes) {
// This canvas has access to that image anyway
return;
}
}
aCanvasElement->SetWriteOnly();
}

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -15,8 +15,8 @@
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* Vladimir Vukicevic <vladimir@pobox.com>
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
@ -35,28 +35,49 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nspluginroot.idl"
#ifndef _CANVASUTILS_H_
#define _CANVASUTILS_H_
%{C++
#include "nsplugindefs.h"
%}
#include "prtypes.h"
#include "nsContentUtils.h"
#include "nsICanvasElement.h"
#include "nsIPrincipal.h"
#include "nsIDOMElement.h"
#include "nsRect.h"
[uuid(57b4e2f0-019b-11d2-815b-006008119d7a)]
interface nsIWindowlessPluginInstancePeer : nsISupports
{
/**
* Corresponds to NPN_InvalidateRect
*/
void invalidateRect(in nsPluginRectPtr aRect);
#include "gfxASurface.h"
/**
* Corresponds to NPN_InvalidateRegion
*/
void invalidateRegion(in nsPluginRegion aRegion);
namespace mozilla {
/**
* Corresponds to NPN_ForceRedraw
*/
void forceRedraw();
class CanvasUtils {
public:
// Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
static PRBool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
PRInt32 realWidth, PRInt32 realHeight)
{
if (w <= 0 || h <= 0 || x < 0 || y < 0)
return PR_FALSE;
if (x >= realWidth || w > (realWidth - x) ||
y >= realHeight || h > (realHeight - y))
return PR_FALSE;
return PR_TRUE;
}
// Flag aCanvasElement as write-only if drawing an image with aPrincipal
// onto it would make it such.
static void DoDrawImageSecurityCheck(nsICanvasElement *aCanvasElement,
nsIPrincipal *aPrincipal,
PRBool forceWriteOnly);
private:
// this can't be instantiated
CanvasUtils() { }
};
}
#endif /* _CANVASUTILS_H_ */

Просмотреть файл

@ -68,17 +68,11 @@ REQUIRES = \
qcms \
$(NULL)
# XXX some platforms can't handle building
# an empty .a/lib. Remove this dummy.cpp
# whenever w have a rendering context
# that doesn't depend on any non-default
# libraries.
CPPSRCS = dummy.cpp \
$(NULL)
ifdef MOZ_ENABLE_CANVAS
CPPSRCS += nsCanvasRenderingContext2D.cpp
endif
CPPSRCS = \
CanvasUtils.cpp \
nsCanvasRenderingContext2D.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a static lib.
FORCE_STATIC_LIB = 1

Просмотреть файл

@ -1,9 +0,0 @@
/*
* This file only exists because some platforms can't handle building an empty .a
* file, or .lib, or whatever (e.g. OS X, possibly Win32).
*
* Need at least one external symbol for some linkers to create a proper
* archive file: https://bugzilla.mozilla.org/show_bug.cgi?id=311143
*/
void concvsdummy(void) {}

Просмотреть файл

@ -55,15 +55,9 @@
#include "nsIPresShell.h"
#include "nsIVariant.h"
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "nsIDOMHTMLCanvasElement.h"
#include "nsICanvasElement.h"
#include "nsIDOMHTMLImageElement.h"
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
#include "nsIFrame.h"
#include "nsDOMError.h"
#include "nsIScriptError.h"
@ -110,17 +104,15 @@
#include "nsBidiPresUtils.h"
#ifdef MOZ_MEDIA
#include "nsHTMLVideoElement.h"
#endif
#include "CanvasUtils.h"
using namespace mozilla;
#ifndef M_PI
#define M_PI 3.14159265358979323846
#define M_PI_2 1.57079632679489661923
#endif
static PRBool CheckSaneSubrectSize (PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, PRInt32 realWidth, PRInt32 realHeight);
/* Float validation stuff */
#define VALIDATE(_f) if (!JSDOUBLE_IS_FINITE(_f)) return PR_FALSE
@ -360,14 +352,6 @@ protected:
*/
void ApplyStyle(Style aWhichStyle, PRBool aUseGlobalAlpha = PR_TRUE);
// If aPrincipal is not subsumed by this canvas element, then
// we make the canvas write-only so bad guys can't extract the pixel
// data. If forceWriteOnly is set, we force write only to be set
// and ignore aPrincipal. (This is used for when the original data came
// from a <canvas> that had write-only set.)
void DoDrawImageSecurityCheck(nsIPrincipal* aPrincipal,
PRBool forceWriteOnly);
// Member vars
PRInt32 mWidth, mHeight;
PRPackedBool mValid;
@ -390,7 +374,13 @@ protected:
* Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
* Redraw is called, reset to false when Render is called.
*/
PRBool mIsFrameInvalid;
PRBool mIsEntireFrameInvalid;
/**
* Number of times we've invalidated before calling redraw
*/
PRUint32 mInvalidateCount;
static const PRUint32 kCanvasMaxInvalidateCount = 100;
/**
* Returns true iff the the given operator should affect areas of the
@ -478,8 +468,11 @@ protected:
/**
* Draws the current path in the given style. Takes care of
* any shadow drawing and will use intermediate surfaces as needed.
*
* If dirtyRect is given, it will contain the device-space dirty
* rectangle of the draw operation.
*/
nsresult DrawPath(Style style);
nsresult DrawPath(Style style, gfxRect *dirtyRect = nsnull);
/**
* Draws a rectangle in the given style; used by FillRect and StrokeRect.
@ -614,14 +607,6 @@ protected:
static PRBool ConvertJSValToDouble(double* aProp, JSContext* aContext,
jsval aValue);
// thebes helpers
nsresult ThebesSurfaceFromElement(nsIDOMElement *imgElt,
PRBool forceCopy,
gfxASurface **aSurface,
PRInt32 *widthOut, PRInt32 *heightOut,
nsIPrincipal **prinOut,
PRBool *forceWriteOnlyOut);
// other helpers
void GetAppUnitsValues(PRUint32 *perDevPixel, PRUint32 *perCSSPixel) {
// If we don't have a canvas element, we just return something generic.
@ -677,8 +662,8 @@ NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
: mValid(PR_FALSE), mOpaque(PR_FALSE), mCanvasElement(nsnull),
mSaveCount(0), mIsFrameInvalid(PR_FALSE), mLastStyle(STYLE_MAX),
mStyleStack(20)
mSaveCount(0), mIsEntireFrameInvalid(PR_FALSE), mInvalidateCount(0),
mLastStyle(STYLE_MAX), mStyleStack(20)
{
}
@ -693,7 +678,7 @@ nsCanvasRenderingContext2D::Destroy()
mSurface = nsnull;
mThebes = nsnull;
mValid = PR_FALSE;
mIsFrameInvalid = PR_FALSE;
mIsEntireFrameInvalid = PR_FALSE;
}
nsresult
@ -791,43 +776,6 @@ nsCanvasRenderingContext2D::DirtyAllStyles()
}
}
void
nsCanvasRenderingContext2D::DoDrawImageSecurityCheck(nsIPrincipal* aPrincipal,
PRBool forceWriteOnly)
{
// Callers should ensure that mCanvasElement is non-null before calling this
if (!mCanvasElement) {
NS_WARNING("DoDrawImageSecurityCheck called without canvas element!");
return;
}
if (mCanvasElement->IsWriteOnly())
return;
// If we explicitly set WriteOnly just do it and get out
if (forceWriteOnly) {
mCanvasElement->SetWriteOnly();
return;
}
if (aPrincipal == nsnull)
return;
nsCOMPtr<nsINode> elem = do_QueryInterface(mCanvasElement);
if (elem) { // XXXbz How could this actually be null?
PRBool subsumes;
nsresult rv =
elem->NodePrincipal()->Subsumes(aPrincipal, &subsumes);
if (NS_SUCCEEDED(rv) && subsumes) {
// This canvas has access to that image anyway
return;
}
}
mCanvasElement->SetWriteOnly();
}
void
nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
PRBool aUseGlobalAlpha)
@ -850,8 +798,9 @@ nsCanvasRenderingContext2D::ApplyStyle(Style aWhichStyle,
if (!mCanvasElement)
return;
DoDrawImageSecurityCheck(pattern->Principal(),
pattern->GetForceWriteOnly());
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement,
pattern->Principal(),
pattern->GetForceWriteOnly());
gfxPattern* gpat = pattern->GetPattern();
@ -883,12 +832,11 @@ nsCanvasRenderingContext2D::Redraw()
if (!mCanvasElement)
return NS_OK;
if (!mIsFrameInvalid) {
mIsFrameInvalid = PR_TRUE;
return mCanvasElement->InvalidateFrame();
}
if (mIsEntireFrameInvalid)
return NS_OK;
return NS_OK;
mIsEntireFrameInvalid = PR_TRUE;
return mCanvasElement->InvalidateFrame();
}
nsresult
@ -897,12 +845,13 @@ nsCanvasRenderingContext2D::Redraw(const gfxRect& r)
if (!mCanvasElement)
return NS_OK;
if (!mIsFrameInvalid) {
mIsFrameInvalid = PR_TRUE;
return mCanvasElement->InvalidateFrameSubrect(r);
}
if (mIsEntireFrameInvalid)
return NS_OK;
return NS_OK;
if (++mInvalidateCount > kCanvasMaxInvalidateCount)
return Redraw();
return mCanvasElement->InvalidateFrameSubrect(r);
}
NS_IMETHODIMP
@ -1013,7 +962,9 @@ nsCanvasRenderingContext2D::Render(gfxContext *ctx, gfxPattern::GraphicsFilter a
if (mOpaque)
ctx->SetOperator(op);
mIsFrameInvalid = PR_FALSE;
mIsEntireFrameInvalid = PR_FALSE;
mInvalidateCount = 0;
return rv;
}
@ -1333,7 +1284,6 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
const nsAString& repeat,
nsIDOMCanvasPattern **_retval)
{
nsresult rv;
gfxPattern::GraphicsExtend extend;
if (repeat.IsEmpty() || repeat.EqualsLiteral("repeat")) {
@ -1351,22 +1301,17 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
return NS_ERROR_DOM_SYNTAX_ERR;
}
PRInt32 imgWidth, imgHeight;
nsCOMPtr<nsIPrincipal> principal;
PRBool forceWriteOnly = PR_FALSE;
nsRefPtr<gfxASurface> imgsurf;
rv = ThebesSurfaceFromElement(image, PR_TRUE,
getter_AddRefs(imgsurf), &imgWidth, &imgHeight,
getter_AddRefs(principal), &forceWriteOnly);
if (NS_FAILED(rv))
return rv;
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(image, nsLayoutUtils::SFE_WANT_NEW_SURFACE);
if (!res.mSurface)
return NS_ERROR_NOT_AVAILABLE;
nsRefPtr<gfxPattern> thebespat = new gfxPattern(imgsurf);
nsRefPtr<gfxPattern> thebespat = new gfxPattern(res.mSurface);
thebespat->SetExtend(extend);
nsRefPtr<nsCanvasPattern> pat = new nsCanvasPattern(thebespat, principal,
forceWriteOnly);
nsRefPtr<nsCanvasPattern> pat = new nsCanvasPattern(thebespat, res.mPrincipal,
res.mIsWriteOnly);
if (!pat)
return NS_ERROR_OUT_OF_MEMORY;
@ -1524,7 +1469,7 @@ nsCanvasRenderingContext2D::ShadowFinalize(gfxAlphaBoxBlur& blur)
}
nsresult
nsCanvasRenderingContext2D::DrawPath(Style style)
nsCanvasRenderingContext2D::DrawPath(Style style, gfxRect *dirtyRect)
{
/*
* Need an intermediate surface when:
@ -1591,6 +1536,12 @@ nsCanvasRenderingContext2D::DrawPath(Style style)
else
mThebes->Stroke();
// XXX do some more work to calculate the extents of shadows
// XXX handle stroke extents
if (dirtyRect && style == STYLE_FILL && !doDrawShadow) {
*dirtyRect = mThebes->GetUserPathExtent();
}
if (doUseIntermediateSurface) {
mThebes->PopGroupToSource();
DirtyAllStyles();
@ -1598,6 +1549,15 @@ nsCanvasRenderingContext2D::DrawPath(Style style)
mThebes->Paint(CurrentState().StyleIsColor(style) ? 1.0 : CurrentState().globalAlpha);
}
if (dirtyRect) {
if (style != STYLE_FILL || doDrawShadow) {
// just use the clip extents
*dirtyRect = mThebes->GetClipExtents();
}
*dirtyRect = mThebes->UserToDevice(*dirtyRect);
}
return NS_OK;
}
@ -1619,7 +1579,8 @@ nsCanvasRenderingContext2D::ClearRect(float x, float y, float w, float h)
mThebes->Rectangle(gfxRect(x, y, w, h));
mThebes->Fill();
return Redraw();
gfxRect dirty = mThebes->UserToDevice(mThebes->GetUserPathExtent());
return Redraw(dirty);
}
nsresult
@ -1633,11 +1594,12 @@ nsCanvasRenderingContext2D::DrawRect(const gfxRect& rect, Style style)
mThebes->NewPath();
mThebes->Rectangle(rect);
nsresult rv = DrawPath(style);
gfxRect dirty;
nsresult rv = DrawPath(style, &dirty);
if (NS_FAILED(rv))
return rv;
return Redraw();
return Redraw(dirty);
}
NS_IMETHODIMP
@ -1673,19 +1635,21 @@ nsCanvasRenderingContext2D::ClosePath()
NS_IMETHODIMP
nsCanvasRenderingContext2D::Fill()
{
nsresult rv = DrawPath(STYLE_FILL);
gfxRect dirty;
nsresult rv = DrawPath(STYLE_FILL, &dirty);
if (NS_FAILED(rv))
return rv;
return Redraw();
return Redraw(dirty);
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::Stroke()
{
nsresult rv = DrawPath(STYLE_STROKE);
gfxRect dirty;
nsresult rv = DrawPath(STYLE_STROKE, &dirty);
if (NS_FAILED(rv))
return rv;
return Redraw();
return Redraw(dirty);
}
NS_IMETHODIMP
@ -2301,8 +2265,7 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
processor.mThebes = mThebes;
processor.mOp = aOp;
processor.mBoundingBox = gfxRect(0, 0, 0, 0);
// need to measure size if using an intermediate surface for drawing
processor.mDoMeasureBoundingBox = doDrawShadow;
processor.mDoMeasureBoundingBox = doDrawShadow || !mIsEntireFrameInvalid;
processor.mFontgrp = GetCurrentFontStyle();
NS_ASSERTION(processor.mFontgrp, "font group is null");
@ -2396,6 +2359,9 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
mThebes->Translate(-trans);
}
// save the previous bounding box
gfxRect boundingBox = processor.mBoundingBox;
// don't ever need to measure the bounding box twice
processor.mDoMeasureBoundingBox = PR_FALSE;
@ -2477,6 +2443,9 @@ nsCanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText,
} else if (doUseIntermediateSurface)
mThebes->Paint(CurrentState().StyleIsColor(STYLE_FILL) ? 1.0 : CurrentState().globalAlpha);
if (aOp == nsCanvasRenderingContext2D::TEXT_DRAW_OPERATION_FILL && !doDrawShadow)
return Redraw(mThebes->UserToDevice(boundingBox));
return Redraw();
}
@ -2542,7 +2511,8 @@ nsCanvasRenderingContext2D::MozDrawText(const nsAString& textToDraw)
nsnull,
nsnull,
nsnull);
return NS_OK;
return Redraw();
}
NS_IMETHODIMP
@ -2651,10 +2621,12 @@ nsCanvasRenderingContext2D::MozTextAlongPath(const nsAString& textToDraw, PRBool
x += 2 * halfAdvance;
}
if(stroke)
if (stroke) {
ApplyStyle(STYLE_STROKE);
else
mThebes->NewPath();
} else {
ApplyStyle(STYLE_FILL);
}
for(PRUint32 i = 0; i < strLength; i++)
{
@ -2679,9 +2651,12 @@ nsCanvasRenderingContext2D::MozTextAlongPath(const nsAString& textToDraw, PRBool
mThebes->SetMatrix(matrix);
}
if (stroke)
mThebes->Stroke();
delete [] cp;
return NS_OK;
return Redraw();
}
//
@ -2919,6 +2894,7 @@ NS_IMETHODIMP
nsCanvasRenderingContext2D::DrawImage()
{
nsresult rv;
gfxRect dirty;
// we can't do a security check without a canvas element, so
// just skip this entirely
@ -2959,22 +2935,33 @@ nsCanvasRenderingContext2D::DrawImage()
ctx, argv[0]))
return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
PRInt32 imgWidth, imgHeight;
nsCOMPtr<nsIPrincipal> principal;
PRBool forceWriteOnly = PR_FALSE;
gfxMatrix matrix;
nsRefPtr<gfxPattern> pattern;
nsRefPtr<gfxPath> path;
nsRefPtr<gfxASurface> imgsurf;
#ifdef WINCE
nsRefPtr<gfxASurface> currentSurface;
#endif
rv = ThebesSurfaceFromElement(imgElt, PR_FALSE,
getter_AddRefs(imgsurf), &imgWidth, &imgHeight,
getter_AddRefs(principal), &forceWriteOnly);
if (NS_FAILED(rv))
return rv;
DoDrawImageSecurityCheck(principal, forceWriteOnly);
nsLayoutUtils::SurfaceFromElementResult res =
nsLayoutUtils::SurfaceFromElement(imgElt);
if (!res.mSurface)
return NS_ERROR_NOT_AVAILABLE;
#ifndef WINCE
// On non-CE, force a copy if we're using drawImage with our destination
// as a source to work around some Cairo self-copy semantics issues.
if (res.mSurface == mSurface) {
res = nsLayoutUtils::SurfaceFromElement(imgElt, nsLayoutUtils::SFE_WANT_NEW_SURFACE);
if (!res.mSurface)
return NS_ERROR_NOT_AVAILABLE;
}
#endif
nsRefPtr<gfxASurface> imgsurf = res.mSurface;
nsCOMPtr<nsIPrincipal> principal = res.mPrincipal;
gfxIntSize imgSize = res.mSize;
PRBool forceWriteOnly = res.mIsWriteOnly;
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, principal, forceWriteOnly);
gfxContextPathAutoSaveRestore pathSR(mThebes, PR_FALSE);
@ -2987,16 +2974,16 @@ nsCanvasRenderingContext2D::DrawImage()
GET_ARG(&dx, argv[1]);
GET_ARG(&dy, argv[2]);
sx = sy = 0.0;
dw = sw = (double) imgWidth;
dh = sh = (double) imgHeight;
dw = sw = (double) imgSize.width;
dh = sh = (double) imgSize.height;
} else if (argc == 5) {
GET_ARG(&dx, argv[1]);
GET_ARG(&dy, argv[2]);
GET_ARG(&dw, argv[3]);
GET_ARG(&dh, argv[4]);
sx = sy = 0.0;
sw = (double) imgWidth;
sh = (double) imgHeight;
sw = (double) imgSize.width;
sh = (double) imgSize.height;
} else if (argc == 9) {
GET_ARG(&sx, argv[1]);
GET_ARG(&sy, argv[2]);
@ -3027,8 +3014,8 @@ nsCanvasRenderingContext2D::DrawImage()
// check args
if (sx < 0.0 || sy < 0.0 ||
sw < 0.0 || sw > (double) imgWidth ||
sh < 0.0 || sh > (double) imgHeight ||
sw < 0.0 || sw > (double) imgSize.width ||
sh < 0.0 || sh > (double) imgSize.height ||
dw < 0.0 || dh < 0.0)
{
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
@ -3118,6 +3105,8 @@ nsCanvasRenderingContext2D::DrawImage()
} else
mThebes->Clip(clip);
dirty = mThebes->UserToDevice(clip);
mThebes->Paint(CurrentState().globalAlpha);
}
@ -3134,7 +3123,7 @@ nsCanvasRenderingContext2D::DrawImage()
FINISH:
if (NS_SUCCEEDED(rv))
rv = Redraw();
rv = Redraw(dirty);
return rv;
}
@ -3258,192 +3247,6 @@ nsCanvasRenderingContext2D::ConvertJSValToXPCObject(nsISupports** aSupports, REF
return JS_FALSE;
}
/* thebes ARGB32 surfaces are ARGB stored as a packed 32-bit integer; on little-endian
* platforms, they appear as BGRA bytes in the surface data. The color values are also
* stored with premultiplied alpha.
*
* If forceCopy is FALSE, a surface may be returned that's only valid during the current
* operation. If it's TRUE, a copy will always be made that can safely be retained.
*/
nsresult
nsCanvasRenderingContext2D::ThebesSurfaceFromElement(nsIDOMElement *imgElt,
PRBool forceCopy,
gfxASurface **aSurface,
PRInt32 *widthOut,
PRInt32 *heightOut,
nsIPrincipal **prinOut,
PRBool *forceWriteOnlyOut)
{
nsresult rv;
nsCOMPtr<nsINode> node = do_QueryInterface(imgElt);
/* If it's a Canvas, grab its internal surface as necessary */
nsCOMPtr<nsICanvasElement> canvas = do_QueryInterface(imgElt);
if (node && canvas) {
PRUint32 w, h;
rv = canvas->GetSize(&w, &h);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<gfxASurface> sourceSurface;
if (!forceCopy && canvas->CountContexts() == 1) {
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
rv = srcCanvas->GetThebesSurface(getter_AddRefs(sourceSurface));
#ifndef WINCE
// force a copy if we couldn't get the surface, or if it's
// the same as what we have
if (sourceSurface == mSurface || NS_FAILED(rv))
#else
// force a copy if we couldn't get the surface
if (NS_FAILED(rv))
#endif
sourceSurface = nsnull;
}
if (sourceSurface == nsnull) {
nsRefPtr<gfxASurface> surf =
gfxPlatform::GetPlatform()->CreateOffscreenSurface
(gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
rv = canvas->RenderContexts(ctx, gfxPattern::FILTER_NEAREST);
if (NS_FAILED(rv))
return rv;
sourceSurface = surf;
}
*aSurface = sourceSurface.forget().get();
*widthOut = w;
*heightOut = h;
NS_ADDREF(*prinOut = node->NodePrincipal());
*forceWriteOnlyOut = canvas->IsWriteOnly();
return NS_OK;
}
#ifdef MOZ_MEDIA
/* Maybe it's <video>? */
nsCOMPtr<nsIDOMHTMLVideoElement> ve = do_QueryInterface(imgElt);
if (node && ve) {
nsHTMLVideoElement *video = static_cast<nsHTMLVideoElement*>(ve.get());
/* If it doesn't have a principal, just bail */
nsCOMPtr<nsIPrincipal> principal = video->GetCurrentPrincipal();
if (!principal)
return NS_ERROR_DOM_SECURITY_ERR;
PRUint32 videoWidth, videoHeight;
rv = video->GetVideoWidth(&videoWidth);
rv |= video->GetVideoHeight(&videoHeight);
if (NS_FAILED(rv))
return NS_ERROR_NOT_AVAILABLE;
nsRefPtr<gfxASurface> surf =
gfxPlatform::GetPlatform()->CreateOffscreenSurface
(gfxIntSize(videoWidth, videoHeight), gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
video->Paint(ctx, gfxPattern::FILTER_NEAREST, gfxRect(0, 0, videoWidth, videoHeight));
*aSurface = surf.forget().get();
*widthOut = videoWidth;
*heightOut = videoHeight;
*prinOut = principal.forget().get();
*forceWriteOnlyOut = PR_FALSE;
return NS_OK;
}
#endif
/* Finally, check if it's a normal image */
nsCOMPtr<imgIContainer> imgContainer;
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(imgElt);
if (!imageLoader)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<imgIRequest> imgRequest;
rv = imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
getter_AddRefs(imgRequest));
NS_ENSURE_SUCCESS(rv, rv);
if (!imgRequest)
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_NOT_AVAILABLE;
PRUint32 status;
imgRequest->GetImageStatus(&status);
if ((status & imgIRequest::STATUS_LOAD_COMPLETE) == 0)
return NS_ERROR_NOT_AVAILABLE;
// In case of data: URIs, we want to ignore principals;
// they should have the originating content's principal,
// but that's broken at the moment in imgLib.
nsCOMPtr<nsIURI> uri;
rv = imgRequest->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
PRBool isDataURI = PR_FALSE;
rv = uri->SchemeIs("data", &isDataURI);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
// Data URIs are always OK; set the principal
// to null to indicate that.
if (isDataURI) {
*prinOut = nsnull;
} else {
rv = imgRequest->GetImagePrincipal(prinOut);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(*prinOut, NS_ERROR_DOM_SECURITY_ERR);
}
*forceWriteOnlyOut = PR_FALSE;
rv = imgRequest->GetImage(getter_AddRefs(imgContainer));
NS_ENSURE_SUCCESS(rv, rv);
if (!imgContainer)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<gfxIImageFrame> frame;
rv = imgContainer->GetCurrentFrame(getter_AddRefs(frame));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIImage> img(do_GetInterface(frame));
PRInt32 imgWidth, imgHeight;
rv = frame->GetWidth(&imgWidth);
rv |= frame->GetHeight(&imgHeight);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
if (widthOut)
*widthOut = imgWidth;
if (heightOut)
*heightOut = imgHeight;
nsRefPtr<gfxPattern> gfxpattern;
img->GetPattern(getter_AddRefs(gfxpattern));
nsRefPtr<gfxASurface> gfxsurf = gfxpattern->GetSurface();
if (!gfxsurf) {
gfxsurf = new gfxImageSurface (gfxIntSize(imgWidth, imgHeight), gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(gfxsurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetPattern(gfxpattern);
ctx->Paint();
}
*aSurface = gfxsurf.forget().get();
return NS_OK;
}
/* Check that the rect [x,y,w,h] is a valid subrect of [0,0,realWidth,realHeight]
* without overflowing any integers and the like.
*/
@ -3566,7 +3369,6 @@ nsCanvasRenderingContext2D::DrawWindow(nsIDOMWindow* aWindow, float aX, float aY
// we're drawing; aX and aY are drawn to 0,0 in current user
// space.
gfxRect damageRect = mThebes->UserToDevice(gfxRect(0, 0, aW, aH));
damageRect.RoundOut();
Redraw(damageRect);
@ -3614,7 +3416,7 @@ nsCanvasRenderingContext2D::GetImageData()
if (!JS_ConvertArguments (ctx, argc, argv, "jjjj", &x, &y, &w, &h))
return NS_ERROR_DOM_SYNTAX_ERR;
if (!CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
return NS_ERROR_DOM_SYNTAX_ERR;
nsAutoArrayPtr<PRUint8> surfaceData (new (std::nothrow) PRUint8[w * h * 4]);
@ -3802,7 +3604,7 @@ nsCanvasRenderingContext2D::PutImageData()
return NS_ERROR_DOM_SYNTAX_ERR;
dataArray = JSVAL_TO_OBJECT(v);
if (!CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
if (!CanvasUtils::CheckSaneSubrectSize (x, y, w, h, mWidth, mHeight))
return NS_ERROR_DOM_SYNTAX_ERR;
jsuint arrayLen;
@ -3972,7 +3774,7 @@ nsCanvasRenderingContext2D::CreateImageData()
// check for overflow when calculating len
PRUint32 len0 = w * h;
if (len0 / w != h)
if (len0 / w != (PRUint32) h)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
PRUint32 len = len0 * 4;
if (len / 4 != len0)

Просмотреть файл

@ -256,11 +256,24 @@ public:
*/
already_AddRefed<nsILoadGroup> GetDocumentLoadGroup();
/**
* Returns PR_TRUE if the media has played or completed a seek.
* Used by video frame to determine whether to paint the poster.
*/
PRBool GetPlayedOrSeeked() { return mHasPlayedOrSeeked; }
protected:
class MediaLoadListener;
class LoadNextSourceEvent;
class SelectResourceEvent;
/**
* Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes
* we'll force a reflow so that the video frame gets reflowed to reflect
* the poster hiding or showing immediately.
*/
void SetPlayedOrSeeked(PRBool aValue);
/**
* Create a decoder for the given aMIMEType. Returns false if we
* were unable to create the decoder.
@ -469,4 +482,8 @@ protected:
// PR_TRUE if we are allowed to suspend the decoder because we were paused,
// autobuffer and autoplay were not set, and we loaded the first frame.
PRPackedBool mAllowSuspendAfterFirstFrame;
// PR_TRUE if we've played or completed a seek. We use this to determine
// when the poster frame should be shown.
PRPackedBool mHasPlayedOrSeeked;
};

Просмотреть файл

@ -413,6 +413,7 @@ NS_IMETHODIMP nsHTMLMediaElement::Load()
{
if (mIsRunningLoadMethod)
return NS_OK;
SetPlayedOrSeeked(PR_FALSE);
mIsRunningLoadMethod = PR_TRUE;
AbortExistingLoads();
QueueSelectResourceTask();
@ -784,7 +785,8 @@ nsHTMLMediaElement::nsHTMLMediaElement(nsINodeInfo *aNodeInfo, PRBool aFromParse
mDelayingLoadEvent(PR_FALSE),
mIsRunningSelectResource(PR_FALSE),
mSuspendedAfterFirstFrame(PR_FALSE),
mAllowSuspendAfterFirstFrame(PR_TRUE)
mAllowSuspendAfterFirstFrame(PR_TRUE),
mHasPlayedOrSeeked(PR_FALSE)
{
RegisterFreezableElement();
}
@ -813,9 +815,29 @@ void nsHTMLMediaElement::StopSuspendingAfterFirstFrame()
}
}
void nsHTMLMediaElement::SetPlayedOrSeeked(PRBool aValue)
{
if (aValue == mHasPlayedOrSeeked)
return;
mHasPlayedOrSeeked = aValue;
// Force a reflow so that the poster frame hides or shows immediately.
nsIDocument *doc = GetDocument();
if (!doc) return;
nsIPresShell *presShell = doc->GetPrimaryShell();
if (!presShell) return;
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (!frame) return;
presShell->FrameNeedsReflow(frame,
nsIPresShell::eTreeChange,
NS_FRAME_IS_DIRTY);
}
NS_IMETHODIMP nsHTMLMediaElement::Play()
{
StopSuspendingAfterFirstFrame();
SetPlayedOrSeeked(PR_TRUE);
if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
nsresult rv = Load();
@ -1204,6 +1226,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
mDecoder->SetVolume(mMuted ? 0.0 : mVolume);
if (!mPaused) {
SetPlayedOrSeeked(PR_TRUE);
rv = mDecoder->Play();
}
@ -1301,6 +1324,7 @@ void nsHTMLMediaElement::SeekStarted()
void nsHTMLMediaElement::SeekCompleted()
{
mPlayingBeforeSeek = PR_FALSE;
SetPlayedOrSeeked(PR_TRUE);
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("seeked"));
}
@ -1454,6 +1478,7 @@ void nsHTMLMediaElement::NotifyAutoplayDataReady()
mAutoplayEnabled) {
mPaused = PR_FALSE;
if (mDecoder) {
SetPlayedOrSeeked(PR_TRUE);
mDecoder->Play();
}
DispatchAsyncSimpleEvent(NS_LITERAL_STRING("play"));

Просмотреть файл

@ -158,3 +158,5 @@ nsHTMLVideoElement::GetAttributeMappingFunction() const
{
return &MapAttributesIntoRule;
}
NS_IMPL_URI_ATTR(nsHTMLVideoElement, Poster, poster)

Просмотреть файл

@ -41,11 +41,83 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
ifdef MOZ_MEDIA
DIRS = \
video \
MODULE = content
LIBRARY_NAME = gkconmedia_s
LIBXUL_LIBRARY = 1
REQUIRES = \
xpcom \
string \
gfx \
content \
thebes \
layout \
widget \
dom \
js \
locale \
unicharutil \
webshell \
uriloader \
htmlparser \
necko \
view \
pref \
docshell \
xpconnect \
xuldoc \
caps \
editor \
imglib2 \
mimetype \
exthandler \
uconv \
intl \
plugin \
cairo \
libpixman \
$(NULL)
EXPORTS = \
nsMediaDecoder.h \
nsMediaStream.h \
nsMediaCache.h \
$(NULL)
CPPSRCS = \
nsMediaDecoder.cpp \
nsMediaCache.cpp \
nsMediaStream.cpp \
$(NULL)
ifdef MOZ_SYDNEYAUDIO
EXPORTS += \
nsAudioStream.h \
$(NULL)
CPPSRCS += \
nsAudioStream.cpp \
$(NULL)
endif
DIRS =
ifdef MOZ_OGG
DIRS += ogg
endif
ifdef MOZ_WAVE
DIRS += wave
endif
ifdef ENABLE_TESTS
DIRS += test
endif
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../base/src \
-I$(srcdir)/../html/content/src \
$(NULL)

Просмотреть файл

Просмотреть файл

@ -34,7 +34,7 @@
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
@ -42,7 +42,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = content
LIBRARY_NAME = gkconvideo_s
LIBRARY_NAME = gkconogg_s
LIBXUL_LIBRARY = 1
REQUIRES = \
@ -78,36 +78,21 @@ REQUIRES = \
libpixman \
$(NULL)
EXPORTS += \
nsChannelReader.h \
nsOggDecoder.h \
$(NULL)
CPPSRCS = \
nsMediaDecoder.cpp \
nsMediaCache.cpp \
nsMediaStream.cpp \
$(NULL)
ifdef MOZ_SYDNEYAUDIO
CPPSRCS += \
nsAudioStream.cpp \
$(NULL)
endif
ifdef MOZ_OGG
CPPSRCS += \
nsChannelReader.cpp \
nsOggDecoder.cpp \
$(NULL)
endif
ifdef MOZ_WAVE
CPPSRCS += \
nsWaveDecoder.cpp \
$(NULL)
endif
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk
INCLUDES += \
-I$(srcdir)/../../../base/src \
-I$(srcdir)/../../../html/content/src \
-I$(srcdir)/../../base/src \
-I$(srcdir)/../../html/content/src \
$(NULL)

Просмотреть файл

Просмотреть файл

@ -34,11 +34,11 @@
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = content/media/video/test
relativesrcdir = content/media/test
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk

Просмотреть файл

Просмотреть файл

@ -7,7 +7,7 @@ function handleRequest(request, response)
createInstance(Components.interfaces.nsIFileInputStream);
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
createInstance(Components.interfaces.nsIBinaryInputStream);
var paths = "tests/content/media/video/test/320x240.ogv";
var paths = "tests/content/media/test/320x240.ogv";
var split = paths.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);

Просмотреть файл

@ -7,7 +7,7 @@ function handleRequest(request, response)
createInstance(Components.interfaces.nsIFileInputStream);
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
createInstance(Components.interfaces.nsIBinaryInputStream);
var paths = "tests/content/media/video/test/320x240.ogv";
var paths = "tests/content/media/test/320x240.ogv";
var split = paths.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);

Просмотреть файл

@ -7,7 +7,7 @@ function handleRequest(request, response)
createInstance(Components.interfaces.nsIFileInputStream);
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
createInstance(Components.interfaces.nsIBinaryInputStream);
var paths = "tests/content/media/video/test/320x240.ogv";
var paths = "tests/content/media/test/320x240.ogv";
var split = paths.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);

Просмотреть файл

@ -7,7 +7,7 @@ function handleRequest(request, response)
createInstance(Components.interfaces.nsIFileInputStream);
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
createInstance(Components.interfaces.nsIBinaryInputStream);
var paths = "tests/content/media/video/test/320x240.ogv";
var paths = "tests/content/media/test/320x240.ogv";
var split = paths.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);

Просмотреть файл

@ -7,7 +7,7 @@ function handleRequest(request, response)
createInstance(Components.interfaces.nsIFileInputStream);
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
createInstance(Components.interfaces.nsIBinaryInputStream);
var paths = "tests/content/media/video/test/320x240.ogv";
var paths = "tests/content/media/test/320x240.ogv";
var split = paths.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);

Просмотреть файл

@ -7,7 +7,7 @@ function handleRequest(request, response)
createInstance(Components.interfaces.nsIFileInputStream);
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
createInstance(Components.interfaces.nsIBinaryInputStream);
var paths = "tests/content/media/video/test/320x240.ogv";
var paths = "tests/content/media/test/320x240.ogv";
var split = paths.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);

Просмотреть файл

@ -7,7 +7,7 @@ function handleRequest(request, response)
if (getState(key[1]) == "redirect") {
var origin = request.host == "localhost" ? "example.org" : "localhost:8888";
response.setStatusLine(request.httpVersion, 303, "See Other");
response.setHeader("Location", "http://" + origin + "/tests/content/media/video/test/seek.ogv");
response.setHeader("Location", "http://" + origin + "/tests/content/media/test/seek.ogv");
response.setHeader("Content-Type", "text/html");
return;
}
@ -21,7 +21,7 @@ function handleRequest(request, response)
createInstance(Components.interfaces.nsIFileInputStream);
var bis = Components.classes["@mozilla.org/binaryinputstream;1"].
createInstance(Components.interfaces.nsIBinaryInputStream);
var paths = "tests/content/media/video/test/seek.ogv";
var paths = "tests/content/media/test/seek.ogv";
var split = paths.split("/");
for(var i = 0; i < split.length; ++i) {
file.append(split[i]);

Просмотреть файл

@ -4,67 +4,67 @@
<body onload="setTimeout(load, 0);" onunload="done()">
<script>
// Page URL: http://example.org/tests/content/media/video/test/file_access_controls.html
// Page URL: http://example.org/tests/content/media/test/file_access_controls.html
var gTests = [
{
// Test 0
url: "redirect.sjs?http://example.com/tests/content/media/video/test/320x240.ogv",
url: "redirect.sjs?http://example.com/tests/content/media/test/320x240.ogv",
result: "error",
description: "Won't load when redirected to different domain",
},{
// Test 1
url: "redirect.sjs?http://example.com/tests/content/media/video/test/320x240.allow-origin.ogv",
url: "redirect.sjs?http://example.com/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
description: "Can load when redirected to different domain with allow-origin",
},{
// Test 2
url: "redirect.sjs?http://test1.example.org/tests/content/media/video/test/320x240.ogv",
url: "redirect.sjs?http://test1.example.org/tests/content/media/test/320x240.ogv",
result: "error",
description: "Won't load when redirected to subdomain",
},{
// Test 3
url: "redirect.sjs?http://test1.example.org/tests/content/media/video/test/320x240.allow-origin.ogv",
url: "redirect.sjs?http://test1.example.org/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
description: "Can load when redirected to subdomain with allow-origin",
},{
// Test 4
url: "redirect.sjs?http://example.org/tests/content/media/video/test/320x240.ogv",
url: "redirect.sjs?http://example.org/tests/content/media/test/320x240.ogv",
result: "loaded",
description: "Can load when redirected to same domain",
},{
// Test 5
url: "http://example.org/tests/content/media/video/test/320x240.ogv",
url: "http://example.org/tests/content/media/test/320x240.ogv",
result: "loaded",
description: "Can load from same domain"
},{
// Test 6
url: "http://example.org:8000/tests/content/media/video/test/320x240.ogv",
url: "http://example.org:8000/tests/content/media/test/320x240.ogv",
result: "error",
description: "Won't load from differnet port on same domain"
},{
// Test 7
url: "http://example.org:8000/tests/content/media/video/test/320x240.allow-origin.ogv",
url: "http://example.org:8000/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
description: "Can load from different port on same domain with allow-origin",
},{
// Test 8
url: "http://example.com/tests/content/media/video/test/320x240.ogv",
url: "http://example.com/tests/content/media/test/320x240.ogv",
result: "error",
description: "Won't load cross domain",
},{
// Test 9
url: "http://example.com/tests/content/media/video/test/320x240.allow-origin.ogv",
url: "http://example.com/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
description: "Can load cross domain with allow-origin",
},{
// Test 10
url: "http://test1.example.org/tests/content/media/video/test/320x240.allow-origin.ogv",
url: "http://test1.example.org/tests/content/media/test/320x240.allow-origin.ogv",
result: "loaded",
description: "Can load from subdomain with allow-origin",
},{
// Test 11
url: "http://test1.example.org/tests/content/media/video/test/320x240.ogv",
url: "http://test1.example.org/tests/content/media/test/320x240.ogv",
result: "error",
description: "Won't load from subdomain",
}
@ -95,7 +95,7 @@ function createVideo() {
function load() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
opener.is(window.location.href,
"http://example.org/tests/content/media/video/test/file_access_controls.html",
"http://example.org/tests/content/media/test/file_access_controls.html",
"We must be on a example.org:80");
// Ensure access control check pref is on.

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=451958
/** Test for Bug 451958 **/
function run() {
window.open("http://example.org:80/tests/content/media/video/test/file_access_controls.html", "", "width=500,height=500");
window.open("http://example.org:80/tests/content/media/test/file_access_controls.html", "", "width=500,height=500");
}
function done() {

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше