/** * Gets the bounds for the areaFrame. * Walks the Frame tree and checks for proper frames. */ void HTMLComboboxListAccessible::GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame) { *aBoundingFrame = nsnull; Accessible* comboAcc = Parent(); if (!comboAcc) return; if (0 == (comboAcc->State() & states::COLLAPSED)) { HTMLSelectListAccessible::GetBoundsRect(aBounds, aBoundingFrame); return; } // Get the first option. nsIContent* content = mContent->GetFirstChild(); if (!content) { return; } nsIFrame* frame = content->GetPrimaryFrame(); if (!frame) { *aBoundingFrame = nsnull; return; } *aBoundingFrame = frame->GetParent(); aBounds = (*aBoundingFrame)->GetRect(); }
PRUint64 HTMLSelectOptionAccessible::NativeState() { // As a HTMLSelectOptionAccessible we can have the following states: // SELECTABLE, SELECTED, FOCUSED, FOCUSABLE, OFFSCREEN // Upcall to Accessible, but skip HyperTextAccessible impl // because we don't want EDITABLE or SELECTABLE_TEXT PRUint64 state = Accessible::NativeState(); Accessible* select = GetSelect(); if (!select) return state; PRUint64 selectState = select->State(); if (selectState & states::INVISIBLE) return state; // Are we selected? bool isSelected = false; nsCOMPtr<nsIDOMHTMLOptionElement> option(do_QueryInterface(mContent)); if (option) { option->GetSelected(&isSelected); if (isSelected) state |= states::SELECTED; } if (selectState & states::OFFSCREEN) { state |= states::OFFSCREEN; } else if (selectState & states::COLLAPSED) { // <select> is COLLAPSED: add OFFSCREEN, if not the currently // visible option if (!isSelected) { state |= states::OFFSCREEN; } else { // Clear offscreen and invisible for currently showing option state &= ~(states::OFFSCREEN | states::INVISIBLE); state |= selectState & states::OPAQUE1; } } else { // XXX list frames are weird, don't rely on Accessible's general // visibility implementation unless they get reimplemented in layout state &= ~states::OFFSCREEN; // <select> is not collapsed: compare bounds to calculate OFFSCREEN Accessible* listAcc = Parent(); if (listAcc) { PRInt32 optionX, optionY, optionWidth, optionHeight; PRInt32 listX, listY, listWidth, listHeight; GetBounds(&optionX, &optionY, &optionWidth, &optionHeight); listAcc->GetBounds(&listX, &listY, &listWidth, &listHeight); if (optionY < listY || optionY + optionHeight > listY + listHeight) { state |= states::OFFSCREEN; } } } return state; }
nsRect HTMLComboboxListAccessible::RelativeBounds(nsIFrame** aBoundingFrame) const { *aBoundingFrame = nullptr; Accessible* comboAcc = Parent(); if (!comboAcc) return nsRect(); if (0 == (comboAcc->State() & states::COLLAPSED)) { return HTMLSelectListAccessible::RelativeBounds(aBoundingFrame); } // Get the first option. nsIContent* content = mContent->GetFirstChild(); if (!content) return nsRect(); nsIFrame* frame = content->GetPrimaryFrame(); if (!frame) { *aBoundingFrame = nullptr; return nsRect(); } *aBoundingFrame = frame->GetParent(); return (*aBoundingFrame)->GetRect(); }
nsRect HTMLSelectOptionAccessible::RelativeBounds(nsIFrame** aBoundingFrame) const { Accessible* combobox = GetCombobox(); if (combobox && (combobox->State() & states::COLLAPSED)) return combobox->RelativeBounds(aBoundingFrame); return HyperTextAccessibleWrap::RelativeBounds(aBoundingFrame); }
uint64_t HTMLSelectOptionAccessible::NativeState() const { // As a HTMLSelectOptionAccessible we can have the following states: // SELECTABLE, SELECTED, FOCUSED, FOCUSABLE, OFFSCREEN // Upcall to Accessible, but skip HyperTextAccessible impl // because we don't want EDITABLE or SELECTABLE_TEXT uint64_t state = Accessible::NativeState(); Accessible* select = GetSelect(); if (!select) return state; uint64_t selectState = select->State(); if (selectState & states::INVISIBLE) return state; // Are we selected? HTMLOptionElement* option = HTMLOptionElement::FromNode(mContent); bool selected = option && option->Selected(); if (selected) state |= states::SELECTED; if (selectState & states::OFFSCREEN) { state |= states::OFFSCREEN; } else if (selectState & states::COLLAPSED) { // <select> is COLLAPSED: add OFFSCREEN, if not the currently // visible option if (!selected) { state |= states::OFFSCREEN; // Ensure the invisible state is removed. Otherwise, group info will skip // this option. Furthermore, this gets cached and this doesn't get // invalidated even once the select is expanded. state &= ~states::INVISIBLE; } else { // Clear offscreen and invisible for currently showing option state &= ~(states::OFFSCREEN | states::INVISIBLE); state |= selectState & states::OPAQUE1; } } else { // XXX list frames are weird, don't rely on Accessible's general // visibility implementation unless they get reimplemented in layout state &= ~states::OFFSCREEN; // <select> is not collapsed: compare bounds to calculate OFFSCREEN Accessible* listAcc = Parent(); if (listAcc) { nsIntRect optionRect = Bounds(); nsIntRect listRect = listAcc->Bounds(); if (optionRect.Y() < listRect.Y() || optionRect.YMost() > listRect.YMost()) { state |= states::OFFSCREEN; } } } return state; }
void HTMLSelectOptionAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame) { Accessible* combobox = GetCombobox(); if (combobox && (combobox->State() & states::COLLAPSED)) combobox->GetBoundsRect(aTotalBounds, aBoundingFrame); else HyperTextAccessibleWrap::GetBoundsRect(aTotalBounds, aBoundingFrame); }
uint64_t HTMLSelectOptionAccessible::NativeState() { // As a HTMLSelectOptionAccessible we can have the following states: // SELECTABLE, SELECTED, FOCUSED, FOCUSABLE, OFFSCREEN // Upcall to Accessible, but skip HyperTextAccessible impl // because we don't want EDITABLE or SELECTABLE_TEXT uint64_t state = Accessible::NativeState(); Accessible* select = GetSelect(); if (!select) return state; uint64_t selectState = select->State(); if (selectState & states::INVISIBLE) return state; // Are we selected? HTMLOptionElement* option = HTMLOptionElement::FromContent(mContent); bool selected = option && option->Selected(); if (selected) state |= states::SELECTED; if (selectState & states::OFFSCREEN) { state |= states::OFFSCREEN; } else if (selectState & states::COLLAPSED) { // <select> is COLLAPSED: add OFFSCREEN, if not the currently // visible option if (!selected) { state |= states::OFFSCREEN; state ^= states::INVISIBLE; } else { // Clear offscreen and invisible for currently showing option state &= ~(states::OFFSCREEN | states::INVISIBLE); state |= selectState & states::OPAQUE1; } } else { // XXX list frames are weird, don't rely on Accessible's general // visibility implementation unless they get reimplemented in layout state &= ~states::OFFSCREEN; // <select> is not collapsed: compare bounds to calculate OFFSCREEN Accessible* listAcc = Parent(); if (listAcc) { nsIntRect optionRect = Bounds(); nsIntRect listRect = listAcc->Bounds(); if (optionRect.y < listRect.y || optionRect.y + optionRect.height > listRect.y + listRect.height) { state |= states::OFFSCREEN; } } } return state; }
bool DocAccessibleChild::RecvState(const uint64_t& aID, uint64_t* aState) { Accessible* acc = IdToAccessible(aID); if (!acc) { *aState = states::DEFUNCT; return true; } *aState = acc->State(); return true; }
uint64_t XULMenuitemAccessible::NativeState() const { uint64_t state = Accessible::NativeState(); // Has Popup? if (mContent->NodeInfo()->Equals(nsGkAtoms::menu, kNameSpaceID_XUL)) { state |= states::HASPOPUP; if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::open)) state |= states::EXPANDED; else state |= states::COLLAPSED; } // Checkable/checked? static Element::AttrValuesArray strings[] = { nsGkAtoms::radio, nsGkAtoms::checkbox, nullptr }; if (mContent->AsElement()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, strings, eCaseMatters) >= 0) { // Checkable? state |= states::CHECKABLE; // Checked? if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked, nsGkAtoms::_true, eCaseMatters)) state |= states::CHECKED; } // Combo box listitem bool isComboboxOption = (Role() == roles::COMBOBOX_OPTION); if (isComboboxOption) { // Is selected? bool isSelected = false; nsCOMPtr<nsIDOMXULSelectControlItemElement> item(do_QueryInterface(mContent)); NS_ENSURE_TRUE(item, state); item->GetSelected(&isSelected); // Is collapsed? bool isCollapsed = false; Accessible* parent = Parent(); if (parent && parent->State() & states::INVISIBLE) isCollapsed = true; if (isSelected) { state |= states::SELECTED; // Selected and collapsed? if (isCollapsed) { // Set selected option offscreen/invisible according to combobox state Accessible* grandParent = parent->Parent(); if (!grandParent) return state; NS_ASSERTION(grandParent->IsCombobox(), "grandparent of combobox listitem is not combobox"); uint64_t grandParentState = grandParent->State(); state &= ~(states::OFFSCREEN | states::INVISIBLE); state |= (grandParentState & states::OFFSCREEN) | (grandParentState & states::INVISIBLE) | (grandParentState & states::OPAQUE1); } // isCollapsed } // isSelected } // ROLE_COMBOBOX_OPTION return state; }
void AccGroupInfo::Update() { Accessible* parent = mItem->Parent(); if (!parent) return; int32_t indexInParent = mItem->IndexInParent(); uint32_t siblingCount = parent->ChildCount(); if (indexInParent == -1 || indexInParent >= static_cast<int32_t>(siblingCount)) { NS_ERROR("Wrong index in parent! Tree invalidation problem."); return; } int32_t level = nsAccUtils::GetARIAOrDefaultLevel(mItem); // Compute position in set. mPosInSet = 1; for (int32_t idx = indexInParent - 1; idx >= 0 ; idx--) { Accessible* sibling = parent->GetChildAt(idx); roles::Role siblingRole = sibling->Role(); // If the sibling is separator then the group is ended. if (siblingRole == roles::SEPARATOR) break; // If sibling is not visible and hasn't the same base role. if (BaseRole(siblingRole) != mRole || sibling->State() & states::INVISIBLE) continue; // Check if it's hierarchical flatten structure, i.e. if the sibling // level is lesser than this one then group is ended, if the sibling level // is greater than this one then the group is split by some child elements // (group will be continued). int32_t siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling); if (siblingLevel < level) { mParent = sibling; break; } // Skip subset. if (siblingLevel > level) continue; // If the previous item in the group has calculated group information then // build group information for this item based on found one. if (sibling->mBits.groupInfo) { mPosInSet += sibling->mBits.groupInfo->mPosInSet; mParent = sibling->mBits.groupInfo->mParent; mSetSize = sibling->mBits.groupInfo->mSetSize; return; } mPosInSet++; } // Compute set size. mSetSize = mPosInSet; for (uint32_t idx = indexInParent + 1; idx < siblingCount; idx++) { Accessible* sibling = parent->GetChildAt(idx); roles::Role siblingRole = sibling->Role(); // If the sibling is separator then the group is ended. if (siblingRole == roles::SEPARATOR) break; // If sibling is visible and has the same base role if (BaseRole(siblingRole) != mRole || sibling->State() & states::INVISIBLE) continue; // and check if it's hierarchical flatten structure. int32_t siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling); if (siblingLevel < level) break; // Skip subset. if (siblingLevel > level) continue; // If the next item in the group has calculated group information then // build group information for this item based on found one. if (sibling->mBits.groupInfo) { mParent = sibling->mBits.groupInfo->mParent; mSetSize = sibling->mBits.groupInfo->mSetSize; return; } mSetSize++; } if (mParent) return; roles::Role parentRole = parent->Role(); if (ShouldReportRelations(mRole, parentRole)) mParent = parent; // ARIA tree and list can be arranged by using ARIA groups to organize levels. if (parentRole != roles::GROUPING) return; // Way #1 for ARIA tree (not ARIA treegrid): previous sibling of a group is a // parent. In other words the parent of the tree item will be a group and // the previous tree item of the group is a conceptual parent of the tree // item. if (mRole == roles::OUTLINEITEM) { Accessible* parentPrevSibling = parent->PrevSibling(); if (parentPrevSibling && parentPrevSibling->Role() == mRole) { mParent = parentPrevSibling; return; } } // Way #2 for ARIA list and tree: group is a child of an item. In other words // the parent of the item will be a group and containing item of the group is // a conceptual parent of the item. if (mRole == roles::LISTITEM || mRole == roles::OUTLINEITEM) { Accessible* grandParent = parent->Parent(); if (grandParent && grandParent->Role() == mRole) mParent = grandParent; } }
// RootAccessible protected void RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent) { MOZ_ASSERT(aDOMEvent); Event* event = aDOMEvent->InternalDOMEvent(); nsCOMPtr<nsINode> origTargetNode = do_QueryInterface(event->GetOriginalTarget()); nsAutoString eventType; aDOMEvent->GetType(eventType); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eDOMEvents)) logging::DOMEvent("processed", origTargetNode, eventType); #endif if (eventType.EqualsLiteral("popuphiding")) { HandlePopupHidingEvent(origTargetNode); return; } DocAccessible* targetDocument = GetAccService()-> GetDocAccessible(origTargetNode->OwnerDoc()); NS_ASSERTION(targetDocument, "No document while accessible is in document?!"); Accessible* accessible = targetDocument->GetAccessibleOrContainer(origTargetNode); if (!accessible) return; #ifdef MOZ_XUL XULTreeAccessible* treeAcc = accessible->AsXULTree(); if (treeAcc) { if (eventType.EqualsLiteral("TreeRowCountChanged")) { HandleTreeRowCountChangedEvent(aDOMEvent, treeAcc); return; } if (eventType.EqualsLiteral("TreeInvalidated")) { HandleTreeInvalidatedEvent(aDOMEvent, treeAcc); return; } } #endif if (eventType.EqualsLiteral("RadioStateChange")) { uint64_t state = accessible->State(); bool isEnabled = (state & (states::CHECKED | states::SELECTED)) != 0; if (accessible->NeedsDOMUIEvent()) { nsRefPtr<AccEvent> accEvent = new AccStateChangeEvent(accessible, states::CHECKED, isEnabled); nsEventShell::FireEvent(accEvent); } if (isEnabled) { FocusMgr()->ActiveItemChanged(accessible); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eFocus)) logging::ActiveItemChangeCausedBy("RadioStateChange", accessible); #endif } return; } if (eventType.EqualsLiteral("CheckboxStateChange")) { if (accessible->NeedsDOMUIEvent()) { uint64_t state = accessible->State(); bool isEnabled = !!(state & states::CHECKED); nsRefPtr<AccEvent> accEvent = new AccStateChangeEvent(accessible, states::CHECKED, isEnabled); nsEventShell::FireEvent(accEvent); } return; } Accessible* treeItemAcc = nullptr; #ifdef MOZ_XUL // If it's a tree element, need the currently selected item. if (treeAcc) { treeItemAcc = accessible->CurrentItem(); if (treeItemAcc) accessible = treeItemAcc; } if (treeItemAcc && eventType.EqualsLiteral("OpenStateChange")) { uint64_t state = accessible->State(); bool isEnabled = (state & states::EXPANDED) != 0; nsRefPtr<AccEvent> accEvent = new AccStateChangeEvent(accessible, states::EXPANDED, isEnabled); nsEventShell::FireEvent(accEvent); return; } nsINode* targetNode = accessible->GetNode(); if (treeItemAcc && eventType.EqualsLiteral("select")) { // XXX: We shouldn't be based on DOM select event which doesn't provide us // any context info. We should integrate into nsTreeSelection instead. // If multiselect tree, we should fire selectionadd or selection removed if (FocusMgr()->HasDOMFocus(targetNode)) { nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSel = do_QueryInterface(targetNode); nsAutoString selType; multiSel->GetSelType(selType); if (selType.IsEmpty() || !selType.EqualsLiteral("single")) { // XXX: We need to fire EVENT_SELECTION_ADD and EVENT_SELECTION_REMOVE // for each tree item. Perhaps each tree item will need to cache its // selection state and fire an event after a DOM "select" event when // that state changes. XULTreeAccessible::UpdateTreeSelection(); nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN, accessible); return; } nsRefPtr<AccSelChangeEvent> selChangeEvent = new AccSelChangeEvent(treeAcc, treeItemAcc, AccSelChangeEvent::eSelectionAdd); nsEventShell::FireEvent(selChangeEvent); return; } } else #endif if (eventType.EqualsLiteral("AlertActive")) { nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_ALERT, accessible); } else if (eventType.EqualsLiteral("popupshown")) { HandlePopupShownEvent(accessible); } else if (eventType.EqualsLiteral("DOMMenuInactive")) { if (accessible->Role() == roles::MENUPOPUP) { nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, accessible); } } else if (eventType.EqualsLiteral("DOMMenuItemActive")) { FocusMgr()->ActiveItemChanged(accessible); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eFocus)) logging::ActiveItemChangeCausedBy("DOMMenuItemActive", accessible); #endif } else if (eventType.EqualsLiteral("DOMMenuItemInactive")) { // Process DOMMenuItemInactive event for autocomplete only because this is // unique widget that may acquire focus from autocomplete popup while popup // stays open and has no active item. In case of XUL tree autocomplete // popup this event is fired for tree accessible. Accessible* widget = accessible->IsWidget() ? accessible : accessible->ContainerWidget(); if (widget && widget->IsAutoCompletePopup()) { FocusMgr()->ActiveItemChanged(nullptr); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eFocus)) logging::ActiveItemChangeCausedBy("DOMMenuItemInactive", accessible); #endif } } else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always from user input nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_START, accessible, eFromUserInput); // Notify of active item change when menubar gets active and if it has // current item. This is a case of mouseover (set current menuitem) and // mouse click (activate the menubar). If menubar doesn't have current item // (can be a case of menubar activation from keyboard) then ignore this // notification because later we'll receive DOMMenuItemActive event after // current menuitem is set. Accessible* activeItem = accessible->CurrentItem(); if (activeItem) { FocusMgr()->ActiveItemChanged(activeItem); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eFocus)) logging::ActiveItemChangeCausedBy("DOMMenuBarActive", accessible); #endif } } else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always from user input nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_END, accessible, eFromUserInput); FocusMgr()->ActiveItemChanged(nullptr); #ifdef A11Y_LOG if (logging::IsEnabled(logging::eFocus)) logging::ActiveItemChangeCausedBy("DOMMenuBarInactive", accessible); #endif } else if (accessible->NeedsDOMUIEvent() && eventType.EqualsLiteral("ValueChange")) { targetDocument->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, accessible); } #ifdef DEBUG_DRAGDROPSTART else if (eventType.EqualsLiteral("mouseover")) { nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_DRAGDROP_START, accessible); } #endif }
// RootAccessible protected void RootAccessible::ProcessDOMEvent(nsIDOMEvent* aDOMEvent) { nsCOMPtr<nsIDOMNSEvent> DOMNSEvent(do_QueryInterface(aDOMEvent)); nsCOMPtr<nsIDOMEventTarget> DOMEventTarget; DOMNSEvent->GetOriginalTarget(getter_AddRefs(DOMEventTarget)); nsCOMPtr<nsINode> origTargetNode(do_QueryInterface(DOMEventTarget)); nsAutoString eventType; aDOMEvent->GetType(eventType); if (eventType.EqualsLiteral("popuphiding")) { HandlePopupHidingEvent(origTargetNode); return; } DocAccessible* targetDocument = GetAccService()-> GetDocAccessible(origTargetNode->OwnerDoc()); NS_ASSERTION(targetDocument, "No document while accessible is in document?!"); Accessible* accessible = targetDocument->GetAccessibleOrContainer(origTargetNode); if (!accessible) return; nsINode* targetNode = accessible->GetNode(); #ifdef MOZ_XUL XULTreeAccessible* treeAcc = accessible->AsXULTree(); if (treeAcc) { if (eventType.EqualsLiteral("TreeRowCountChanged")) { HandleTreeRowCountChangedEvent(aDOMEvent, treeAcc); return; } if (eventType.EqualsLiteral("TreeInvalidated")) { HandleTreeInvalidatedEvent(aDOMEvent, treeAcc); return; } } #endif if (eventType.EqualsLiteral("RadioStateChange")) { PRUint64 state = accessible->State(); // radiogroup in prefWindow is exposed as a list, // and panebutton is exposed as XULListitem in A11y. // XULListitemAccessible::GetStateInternal uses STATE_SELECTED in this case, // so we need to check states::SELECTED also. bool isEnabled = (state & (states::CHECKED | states::SELECTED)) != 0; nsRefPtr<AccEvent> accEvent = new AccStateChangeEvent(accessible, states::CHECKED, isEnabled); nsEventShell::FireEvent(accEvent); if (isEnabled) { FocusMgr()->ActiveItemChanged(accessible); A11YDEBUG_FOCUS_ACTIVEITEMCHANGE_CAUSE("RadioStateChange", accessible) } return; }
void DocAccessibleWrap::CacheViewportCallback(nsITimer* aTimer, void* aDocAccParam) { RefPtr<DocAccessibleWrap> docAcc( dont_AddRef(reinterpret_cast<DocAccessibleWrap*>(aDocAccParam))); if (!docAcc) { return; } nsIPresShell* presShell = docAcc->PresShell(); if (!presShell) { return; } nsIFrame* rootFrame = presShell->GetRootFrame(); if (!rootFrame) { return; } nsTArray<nsIFrame*> frames; nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable(); nsRect scrollPort = sf ? sf->GetScrollPortRect() : rootFrame->GetRect(); nsLayoutUtils::GetFramesForArea( presShell->GetRootFrame(), scrollPort, frames, nsLayoutUtils::FrameForPointFlags::ONLY_VISIBLE); AccessibleHashtable inViewAccs; for (size_t i = 0; i < frames.Length(); i++) { nsIContent* content = frames.ElementAt(i)->GetContent(); if (!content) { continue; } Accessible* visibleAcc = docAcc->GetAccessibleOrContainer(content); if (!visibleAcc) { continue; } for (Accessible* acc = visibleAcc; acc && acc != docAcc->Parent(); acc = acc->Parent()) { if (inViewAccs.Contains(acc->UniqueID())) { break; } inViewAccs.Put(acc->UniqueID(), acc); } } if (IPCAccessibilityActive()) { DocAccessibleChild* ipcDoc = docAcc->IPCDoc(); nsTArray<BatchData> cacheData(inViewAccs.Count()); for (auto iter = inViewAccs.Iter(); !iter.Done(); iter.Next()) { Accessible* accessible = iter.Data(); auto uid = accessible->IsDoc() && accessible->AsDoc()->IPCDoc() ? 0 : reinterpret_cast<uint64_t>(accessible->UniqueID()); cacheData.AppendElement( BatchData(accessible->Document()->IPCDoc(), uid, accessible->State(), accessible->Bounds(), accessible->ActionCount(), nsString(), nsString(), nsString(), UnspecifiedNaN<double>(), UnspecifiedNaN<double>(), UnspecifiedNaN<double>(), UnspecifiedNaN<double>(), nsTArray<Attribute>())); } ipcDoc->SendBatch(eBatch_Viewport, cacheData); } else if (SessionAccessibility* sessionAcc = SessionAccessibility::GetInstanceFor(docAcc)) { nsTArray<AccessibleWrap*> accessibles(inViewAccs.Count()); for (auto iter = inViewAccs.Iter(); !iter.Done(); iter.Next()) { accessibles.AppendElement( static_cast<AccessibleWrap*>(iter.Data().get())); } sessionAcc->ReplaceViewportCache(accessibles); } if (docAcc->mCacheRefreshTimer) { docAcc->mCacheRefreshTimer = nullptr; } }