/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AccEvent.h" #include "LocalAccessible-inl.h" #include "EmbeddedObjCollector.h" #include "AccGroupInfo.h" #include "AccIterator.h" #include "CachedTableAccessible.h" #include "CssAltContent.h" #include "DocAccessible-inl.h" #include "mozilla/a11y/AccAttributes.h" #include "mozilla/a11y/DocAccessibleChild.h" #include "mozilla/a11y/Platform.h" #include "mozilla/FocusModel.h" #include "nsAccUtils.h" #include "nsMenuPopupFrame.h" #include "nsAccessibilityService.h" #include "ApplicationAccessible.h" #include "nsGenericHTMLElement.h" #include "NotificationController.h" #include "nsEventShell.h" #include "nsTextEquivUtils.h" #include "EventTree.h" #include "OuterDocAccessible.h" #include "Pivot.h" #include "Relation.h" #include "mozilla/a11y/Role.h" #include "RootAccessible.h" #include "States.h" #include "TextLeafAccessible.h" #include "TextLeafRange.h" #include "TextRange.h" #include "HTMLElementAccessibles.h" #include "HTMLSelectAccessible.h" #include "HTMLTableAccessible.h" #include "ImageAccessible.h" #include "nsComputedDOMStyle.h" #include "nsGkAtoms.h" #include "nsIDOMXULButtonElement.h" #include "nsIDOMXULSelectCntrlEl.h" #include "nsIDOMXULSelectCntrlItemEl.h" #include "nsIMutationObserver.h" #include "nsINodeList.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/HTMLFormElement.h" #include "mozilla/dom/HTMLAnchorElement.h" #include "mozilla/gfx/Matrix.h" #include "nsIContent.h" #include "nsIFormControl.h" #include "nsDisplayList.h" #include "nsLayoutUtils.h" #include "nsPresContext.h" #include "nsIFrame.h" #include "nsTextFrame.h" #include "nsIDocShellTreeItem.h" #include "nsStyleStructInlines.h" #include "nsFocusManager.h" #include "nsString.h" #include "nsAtom.h" #include "nsContainerFrame.h" #include "mozilla/Assertions.h" #include "mozilla/BasicEvents.h" #include "mozilla/ErrorResult.h" #include "mozilla/FloatingPoint.h" #include "mozilla/PerfStats.h" #include "mozilla/PresShell.h" #include "mozilla/ProfilerMarkers.h" #include "mozilla/ScrollContainerFrame.h" #include "mozilla/StaticPrefs_accessibility.h" #include "mozilla/StaticPrefs_dom.h" #include "mozilla/StaticPrefs_ui.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/HTMLLabelElement.h" #include "mozilla/dom/KeyboardEventBinding.h" #include "mozilla/dom/TreeWalker.h" #include "mozilla/dom/UserActivation.h" using namespace mozilla; using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// // LocalAccessible: nsISupports and cycle collection NS_IMPL_CYCLE_COLLECTION_CLASS(LocalAccessible) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(LocalAccessible) tmp->Shutdown(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LocalAccessible) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent, mDoc) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LocalAccessible) NS_INTERFACE_MAP_ENTRY_CONCRETE(LocalAccessible) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, LocalAccessible) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(LocalAccessible) NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(LocalAccessible, LastRelease()) LocalAccessible::LocalAccessible(nsIContent* aContent, DocAccessible* aDoc) : mContent(aContent), mDoc(aDoc), mParent(nullptr), mIndexInParent(-1), mFirstLineStart(-1), mStateFlags(0), mContextFlags(0), mReorderEventTarget(false), mShowEventTarget(false), mHideEventTarget(false), mIndexOfEmbeddedChild(-1), mGroupInfo(nullptr) {} LocalAccessible::~LocalAccessible() { NS_ASSERTION(!mDoc, "LastRelease was never called!?!"); } ENameValueFlag LocalAccessible::DirectName(nsString& aName) const { if (!HasOwnContent()) return eNameOK; ENameValueFlag nameFlag = ARIAName(aName); if (!aName.IsEmpty()) return nameFlag; nameFlag = NativeName(aName); aName.CompressWhitespace(); return nameFlag; } ENameValueFlag LocalAccessible::Name(nsString& aName) const { aName.Truncate(); ENameValueFlag nameFlag = DirectName(aName); if (!aName.IsEmpty()) return nameFlag; nsTextEquivUtils::GetNameFromSubtree(this, aName); if (!aName.IsEmpty()) return eNameFromSubtree; // In the end get the name from tooltip. if (Tooltip(aName)) { return eNameFromTooltip; } if (auto cssAlt = CssAltContent(mContent)) { cssAlt.AppendToString(aName); return eNameOK; } aName.SetIsVoid(true); return eNameOK; } EDescriptionValueFlag LocalAccessible::Description( nsString& aDescription) const { // There are 4 conditions that make an accessible have no accDescription: // 1. it's a text node; or // 2. It has no ARIA describedby or description property // 3. it doesn't have an accName; or // 4. its title attribute already equals to its accName nsAutoString name; EDescriptionValueFlag descFlag = eDescriptionOK; aDescription.Truncate(); if (!HasOwnContent() || mContent->IsText()) { return descFlag; } if (ARIADescription(aDescription)) { descFlag = eDescriptionFromARIA; } if (aDescription.IsEmpty()) { NativeDescription(aDescription); aDescription.CompressWhitespace(); } if (aDescription.IsEmpty()) { Tooltip(aDescription); } if (!aDescription.IsEmpty()) { nsAutoString name; Name(name); // Don't expose a description if it is the same as the name. if (aDescription.Equals(name)) aDescription.Truncate(); } return descFlag; } KeyBinding LocalAccessible::AccessKey() const { if (!HasOwnContent()) return KeyBinding(); uint32_t key = nsCoreUtils::GetAccessKeyFor(mContent); if (!key && mContent->IsElement()) { LocalAccessible* label = nullptr; // Copy access key from label node. if (mContent->IsHTMLElement()) { // Unless it is labeled via an ancestor