summaryrefslogtreecommitdiffstats
path: root/accessible/base/nsCoreUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/base/nsCoreUtils.cpp')
-rw-r--r--accessible/base/nsCoreUtils.cpp683
1 files changed, 683 insertions, 0 deletions
diff --git a/accessible/base/nsCoreUtils.cpp b/accessible/base/nsCoreUtils.cpp
new file mode 100644
index 000000000..89823b223
--- /dev/null
+++ b/accessible/base/nsCoreUtils.cpp
@@ -0,0 +1,683 @@
+/* -*- 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 "nsCoreUtils.h"
+
+#include "nsIAccessibleTypes.h"
+
+#include "nsIBaseWindow.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIDocument.h"
+#include "nsIDOMHTMLDocument.h"
+#include "nsIDOMHTMLElement.h"
+#include "nsRange.h"
+#include "nsIBoxObject.h"
+#include "nsIDOMXULElement.h"
+#include "nsIDocShell.h"
+#include "nsIObserverService.h"
+#include "nsIPresShell.h"
+#include "nsPresContext.h"
+#include "nsIScrollableFrame.h"
+#include "nsISelectionPrivate.h"
+#include "nsISelectionController.h"
+#include "nsISimpleEnumerator.h"
+#include "mozilla/dom/TouchEvent.h"
+#include "mozilla/EventListenerManager.h"
+#include "mozilla/EventStateManager.h"
+#include "mozilla/MouseEvents.h"
+#include "mozilla/TouchEvents.h"
+#include "nsView.h"
+#include "nsGkAtoms.h"
+
+#include "nsComponentManagerUtils.h"
+
+#include "nsITreeBoxObject.h"
+#include "nsITreeColumns.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/HTMLLabelElement.h"
+
+using namespace mozilla;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsCoreUtils
+////////////////////////////////////////////////////////////////////////////////
+
+bool
+nsCoreUtils::IsLabelWithControl(nsIContent* aContent)
+{
+ dom::HTMLLabelElement* label = dom::HTMLLabelElement::FromContent(aContent);
+ if (label && label->GetControl())
+ return true;
+
+ return false;
+}
+
+bool
+nsCoreUtils::HasClickListener(nsIContent *aContent)
+{
+ NS_ENSURE_TRUE(aContent, false);
+ EventListenerManager* listenerManager =
+ aContent->GetExistingListenerManager();
+
+ return listenerManager &&
+ (listenerManager->HasListenersFor(nsGkAtoms::onclick) ||
+ listenerManager->HasListenersFor(nsGkAtoms::onmousedown) ||
+ listenerManager->HasListenersFor(nsGkAtoms::onmouseup));
+}
+
+void
+nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
+ int32_t aRowIndex, nsITreeColumn *aColumn,
+ const nsAString& aPseudoElt)
+{
+ nsCOMPtr<nsIDOMElement> tcElm;
+ aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
+ if (!tcElm)
+ return;
+
+ nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
+ nsIDocument *document = tcContent->GetUncomposedDoc();
+ if (!document)
+ return;
+
+ nsCOMPtr<nsIPresShell> presShell = document->GetShell();
+ if (!presShell)
+ return;
+
+ // Ensure row is visible.
+ aTreeBoxObj->EnsureRowIsVisible(aRowIndex);
+
+ // Calculate x and y coordinates.
+ int32_t x = 0, y = 0, width = 0, height = 0;
+ nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn,
+ aPseudoElt,
+ &x, &y, &width, &height);
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
+ nsCOMPtr<nsIBoxObject> tcBoxObj;
+ tcXULElm->GetBoxObject(getter_AddRefs(tcBoxObj));
+
+ int32_t tcX = 0;
+ tcBoxObj->GetX(&tcX);
+
+ int32_t tcY = 0;
+ tcBoxObj->GetY(&tcY);
+
+ // Dispatch mouse events.
+ nsWeakFrame tcFrame = tcContent->GetPrimaryFrame();
+ nsIFrame* rootFrame = presShell->GetRootFrame();
+
+ nsPoint offset;
+ nsIWidget *rootWidget =
+ rootFrame->GetView()->GetNearestWidget(&offset);
+
+ RefPtr<nsPresContext> presContext = presShell->GetPresContext();
+
+ int32_t cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) +
+ presContext->AppUnitsToDevPixels(offset.x);
+ int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) +
+ presContext->AppUnitsToDevPixels(offset.y);
+
+ // XUL is just desktop, so there is no real reason for senfing touch events.
+ DispatchMouseEvent(eMouseDown, cnvdX, cnvdY,
+ tcContent, tcFrame, presShell, rootWidget);
+
+ DispatchMouseEvent(eMouseUp, cnvdX, cnvdY,
+ tcContent, tcFrame, presShell, rootWidget);
+}
+
+void
+nsCoreUtils::DispatchMouseEvent(EventMessage aMessage, int32_t aX, int32_t aY,
+ nsIContent *aContent, nsIFrame *aFrame,
+ nsIPresShell *aPresShell, nsIWidget *aRootWidget)
+{
+ WidgetMouseEvent event(true, aMessage, aRootWidget,
+ WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
+
+ event.mRefPoint = LayoutDeviceIntPoint(aX, aY);
+
+ event.mClickCount = 1;
+ event.button = WidgetMouseEvent::eLeftButton;
+ event.mTime = PR_IntervalNow();
+ event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
+
+ nsEventStatus status = nsEventStatus_eIgnore;
+ aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
+}
+
+void
+nsCoreUtils::DispatchTouchEvent(EventMessage aMessage, int32_t aX, int32_t aY,
+ nsIContent* aContent, nsIFrame* aFrame,
+ nsIPresShell* aPresShell, nsIWidget* aRootWidget)
+{
+ nsIDocShell* docShell = nullptr;
+ if (aPresShell->GetDocument()) {
+ docShell = aPresShell->GetDocument()->GetDocShell();
+ }
+ if (!dom::TouchEvent::PrefEnabled(docShell)) {
+ return;
+ }
+
+ WidgetTouchEvent event(true, aMessage, aRootWidget);
+
+ event.mTime = PR_IntervalNow();
+
+ // XXX: Touch has an identifier of -1 to hint that it is synthesized.
+ RefPtr<dom::Touch> t = new dom::Touch(-1, LayoutDeviceIntPoint(aX, aY),
+ LayoutDeviceIntPoint(1, 1), 0.0f, 1.0f);
+ t->SetTarget(aContent);
+ event.mTouches.AppendElement(t);
+ nsEventStatus status = nsEventStatus_eIgnore;
+ aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
+}
+
+uint32_t
+nsCoreUtils::GetAccessKeyFor(nsIContent* aContent)
+{
+ // Accesskeys are registered by @accesskey attribute only. At first check
+ // whether it is presented on the given element to avoid the slow
+ // EventStateManager::GetRegisteredAccessKey() method.
+ if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::accesskey))
+ return 0;
+
+ nsIPresShell* presShell = aContent->OwnerDoc()->GetShell();
+ if (!presShell)
+ return 0;
+
+ nsPresContext *presContext = presShell->GetPresContext();
+ if (!presContext)
+ return 0;
+
+ EventStateManager *esm = presContext->EventStateManager();
+ if (!esm)
+ return 0;
+
+ return esm->GetRegisteredAccessKey(aContent);
+}
+
+nsIContent *
+nsCoreUtils::GetDOMElementFor(nsIContent *aContent)
+{
+ if (aContent->IsElement())
+ return aContent;
+
+ if (aContent->IsNodeOfType(nsINode::eTEXT))
+ return aContent->GetFlattenedTreeParent();
+
+ return nullptr;
+}
+
+nsINode *
+nsCoreUtils::GetDOMNodeFromDOMPoint(nsINode *aNode, uint32_t aOffset)
+{
+ if (aNode && aNode->IsElement()) {
+ uint32_t childCount = aNode->GetChildCount();
+ NS_ASSERTION(aOffset <= childCount, "Wrong offset of the DOM point!");
+
+ // The offset can be after last child of container node that means DOM point
+ // is placed immediately after the last child. In this case use the DOM node
+ // from the given DOM point is used as result node.
+ if (aOffset != childCount)
+ return aNode->GetChildAt(aOffset);
+ }
+
+ return aNode;
+}
+
+bool
+nsCoreUtils::IsAncestorOf(nsINode *aPossibleAncestorNode,
+ nsINode *aPossibleDescendantNode,
+ nsINode *aRootNode)
+{
+ NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, false);
+
+ nsINode *parentNode = aPossibleDescendantNode;
+ while ((parentNode = parentNode->GetParentNode()) &&
+ parentNode != aRootNode) {
+ if (parentNode == aPossibleAncestorNode)
+ return true;
+ }
+
+ return false;
+}
+
+nsresult
+nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
+ uint32_t aScrollType)
+{
+ nsIPresShell::ScrollAxis vertical, horizontal;
+ ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
+
+ return ScrollSubstringTo(aFrame, aRange, vertical, horizontal);
+}
+
+nsresult
+nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
+ nsIPresShell::ScrollAxis aVertical,
+ nsIPresShell::ScrollAxis aHorizontal)
+{
+ if (!aFrame)
+ return NS_ERROR_FAILURE;
+
+ nsPresContext *presContext = aFrame->PresContext();
+
+ nsCOMPtr<nsISelectionController> selCon;
+ aFrame->GetSelectionController(presContext, getter_AddRefs(selCon));
+ NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
+
+ nsCOMPtr<nsISelection> selection;
+ selCon->GetSelection(nsISelectionController::SELECTION_ACCESSIBILITY,
+ getter_AddRefs(selection));
+
+ nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(selection));
+ selection->RemoveAllRanges();
+ selection->AddRange(aRange);
+
+ privSel->ScrollIntoViewInternal(
+ nsISelectionController::SELECTION_ANCHOR_REGION,
+ true, aVertical, aHorizontal);
+
+ selection->CollapseToStart();
+
+ return NS_OK;
+}
+
+void
+nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame,
+ nsIFrame *aFrame,
+ const nsIntPoint& aPoint)
+{
+ nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollableFrame);
+ if (!scrollableFrame)
+ return;
+
+ nsPoint point =
+ ToAppUnits(aPoint, aFrame->PresContext()->AppUnitsPerDevPixel());
+ nsRect frameRect = aFrame->GetScreenRectInAppUnits();
+ nsPoint deltaPoint(point.x - frameRect.x, point.y - frameRect.y);
+
+ nsPoint scrollPoint = scrollableFrame->GetScrollPosition();
+ scrollPoint -= deltaPoint;
+
+ scrollableFrame->ScrollTo(scrollPoint, nsIScrollableFrame::INSTANT);
+}
+
+void
+nsCoreUtils::ConvertScrollTypeToPercents(uint32_t aScrollType,
+ nsIPresShell::ScrollAxis *aVertical,
+ nsIPresShell::ScrollAxis *aHorizontal)
+{
+ int16_t whereY, whereX;
+ nsIPresShell::WhenToScroll whenY, whenX;
+ switch (aScrollType)
+ {
+ case nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT:
+ whereY = nsIPresShell::SCROLL_TOP;
+ whenY = nsIPresShell::SCROLL_ALWAYS;
+ whereX = nsIPresShell::SCROLL_LEFT;
+ whenX = nsIPresShell::SCROLL_ALWAYS;
+ break;
+ case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT:
+ whereY = nsIPresShell::SCROLL_BOTTOM;
+ whenY = nsIPresShell::SCROLL_ALWAYS;
+ whereX = nsIPresShell::SCROLL_RIGHT;
+ whenX = nsIPresShell::SCROLL_ALWAYS;
+ break;
+ case nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE:
+ whereY = nsIPresShell::SCROLL_TOP;
+ whenY = nsIPresShell::SCROLL_ALWAYS;
+ whereX = nsIPresShell::SCROLL_MINIMUM;
+ whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
+ break;
+ case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_EDGE:
+ whereY = nsIPresShell::SCROLL_BOTTOM;
+ whenY = nsIPresShell::SCROLL_ALWAYS;
+ whereX = nsIPresShell::SCROLL_MINIMUM;
+ whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
+ break;
+ case nsIAccessibleScrollType::SCROLL_TYPE_LEFT_EDGE:
+ whereY = nsIPresShell::SCROLL_MINIMUM;
+ whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
+ whereX = nsIPresShell::SCROLL_LEFT;
+ whenX = nsIPresShell::SCROLL_ALWAYS;
+ break;
+ case nsIAccessibleScrollType::SCROLL_TYPE_RIGHT_EDGE:
+ whereY = nsIPresShell::SCROLL_MINIMUM;
+ whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
+ whereX = nsIPresShell::SCROLL_RIGHT;
+ whenX = nsIPresShell::SCROLL_ALWAYS;
+ break;
+ default:
+ whereY = nsIPresShell::SCROLL_MINIMUM;
+ whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
+ whereX = nsIPresShell::SCROLL_MINIMUM;
+ whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
+ }
+ *aVertical = nsIPresShell::ScrollAxis(whereY, whenY);
+ *aHorizontal = nsIPresShell::ScrollAxis(whereX, whenX);
+}
+
+nsIntPoint
+nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode)
+{
+ nsIntPoint coords(0, 0);
+ nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellFor(aNode));
+ if (!treeItem)
+ return coords;
+
+ nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
+ treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
+ if (!treeOwner)
+ return coords;
+
+ nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(treeOwner);
+ if (baseWindow)
+ baseWindow->GetPosition(&coords.x, &coords.y); // in device pixels
+
+ return coords;
+}
+
+already_AddRefed<nsIDocShell>
+nsCoreUtils::GetDocShellFor(nsINode *aNode)
+{
+ if (!aNode)
+ return nullptr;
+
+ nsCOMPtr<nsIDocShell> docShell = aNode->OwnerDoc()->GetDocShell();
+ return docShell.forget();
+}
+
+bool
+nsCoreUtils::IsRootDocument(nsIDocument *aDocument)
+{
+ nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell();
+ NS_ASSERTION(docShellTreeItem, "No document shell for document!");
+
+ nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
+ docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem));
+
+ return !parentTreeItem;
+}
+
+bool
+nsCoreUtils::IsContentDocument(nsIDocument *aDocument)
+{
+ nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell();
+ NS_ASSERTION(docShellTreeItem, "No document shell tree item for document!");
+
+ return (docShellTreeItem->ItemType() == nsIDocShellTreeItem::typeContent);
+}
+
+bool
+nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode)
+{
+ nsCOMPtr<nsIDocShellTreeItem> treeItem(aDocumentNode->GetDocShell());
+
+ nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
+ treeItem->GetParent(getter_AddRefs(parentTreeItem));
+
+ // Tab document running in own process doesn't have parent.
+ if (XRE_IsContentProcess())
+ return !parentTreeItem;
+
+ // Parent of docshell for tab document running in chrome process is root.
+ nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
+ treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
+
+ return parentTreeItem == rootTreeItem;
+}
+
+bool
+nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
+{
+ nsIURI *uri = aDocument->GetDocumentURI();
+ bool isAboutScheme = false;
+ uri->SchemeIs("about", &isAboutScheme);
+ if (!isAboutScheme)
+ return false;
+
+ nsAutoCString path;
+ uri->GetPath(path);
+
+ NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
+ NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
+
+ return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
+}
+
+bool
+nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID)
+{
+ return aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aID);
+}
+
+bool
+nsCoreUtils::GetUIntAttr(nsIContent *aContent, nsIAtom *aAttr, int32_t *aUInt)
+{
+ nsAutoString value;
+ aContent->GetAttr(kNameSpaceID_None, aAttr, value);
+ if (!value.IsEmpty()) {
+ nsresult error = NS_OK;
+ int32_t integer = value.ToInteger(&error);
+ if (NS_SUCCEEDED(error) && integer > 0) {
+ *aUInt = integer;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
+ nsAString& aLanguage)
+{
+ aLanguage.Truncate();
+
+ nsIContent *walkUp = aContent;
+ while (walkUp && walkUp != aRootContent &&
+ !walkUp->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLanguage))
+ walkUp = walkUp->GetParent();
+}
+
+already_AddRefed<nsIBoxObject>
+nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
+{
+ nsCOMPtr<nsIDOMElement> tcElm;
+ aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
+ nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
+ if (!tcXULElm)
+ return nullptr;
+
+ nsCOMPtr<nsIBoxObject> boxObj;
+ tcXULElm->GetBoxObject(getter_AddRefs(boxObj));
+ return boxObj.forget();
+}
+
+already_AddRefed<nsITreeBoxObject>
+nsCoreUtils::GetTreeBoxObject(nsIContent *aContent)
+{
+ // Find DOMNode's parents recursively until reach the <tree> tag
+ nsIContent* currentContent = aContent;
+ while (currentContent) {
+ if (currentContent->NodeInfo()->Equals(nsGkAtoms::tree,
+ kNameSpaceID_XUL)) {
+ // We will get the nsITreeBoxObject from the tree node
+ nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(currentContent));
+ if (xulElement) {
+ nsCOMPtr<nsIBoxObject> box;
+ xulElement->GetBoxObject(getter_AddRefs(box));
+ nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
+ if (treeBox)
+ return treeBox.forget();
+ }
+ }
+ currentContent = currentContent->GetFlattenedTreeParent();
+ }
+
+ return nullptr;
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
+{
+ nsCOMPtr<nsITreeColumns> cols;
+ aTree->GetColumns(getter_AddRefs(cols));
+ if (!cols)
+ return nullptr;
+
+ nsCOMPtr<nsITreeColumn> column;
+ cols->GetFirstColumn(getter_AddRefs(column));
+ if (column && IsColumnHidden(column))
+ return GetNextSensibleColumn(column);
+
+ return column.forget();
+}
+
+uint32_t
+nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree)
+{
+ uint32_t count = 0;
+
+ nsCOMPtr<nsITreeColumns> cols;
+ aTree->GetColumns(getter_AddRefs(cols));
+ if (!cols)
+ return count;
+
+ nsCOMPtr<nsITreeColumn> column;
+ cols->GetFirstColumn(getter_AddRefs(column));
+
+ while (column) {
+ if (!IsColumnHidden(column))
+ count++;
+
+ nsCOMPtr<nsITreeColumn> nextColumn;
+ column->GetNext(getter_AddRefs(nextColumn));
+ column.swap(nextColumn);
+ }
+
+ return count;
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, uint32_t aIndex)
+{
+ uint32_t idx = aIndex;
+
+ nsCOMPtr<nsITreeColumn> column = GetFirstSensibleColumn(aTree);
+ while (column) {
+ if (idx == 0)
+ return column.forget();
+
+ idx--;
+ column = GetNextSensibleColumn(column);
+ }
+
+ return nullptr;
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetNextSensibleColumn(nsITreeColumn *aColumn)
+{
+ nsCOMPtr<nsITreeColumn> nextColumn;
+ aColumn->GetNext(getter_AddRefs(nextColumn));
+
+ while (nextColumn && IsColumnHidden(nextColumn)) {
+ nsCOMPtr<nsITreeColumn> tempColumn;
+ nextColumn->GetNext(getter_AddRefs(tempColumn));
+ nextColumn.swap(tempColumn);
+ }
+
+ return nextColumn.forget();
+}
+
+already_AddRefed<nsITreeColumn>
+nsCoreUtils::GetPreviousSensibleColumn(nsITreeColumn *aColumn)
+{
+ nsCOMPtr<nsITreeColumn> prevColumn;
+ aColumn->GetPrevious(getter_AddRefs(prevColumn));
+
+ while (prevColumn && IsColumnHidden(prevColumn)) {
+ nsCOMPtr<nsITreeColumn> tempColumn;
+ prevColumn->GetPrevious(getter_AddRefs(tempColumn));
+ prevColumn.swap(tempColumn);
+ }
+
+ return prevColumn.forget();
+}
+
+bool
+nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
+{
+ nsCOMPtr<nsIDOMElement> element;
+ aColumn->GetElement(getter_AddRefs(element));
+ nsCOMPtr<nsIContent> content = do_QueryInterface(element);
+ return content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
+ nsGkAtoms::_true, eCaseMatters);
+}
+
+void
+nsCoreUtils::ScrollTo(nsIPresShell* aPresShell, nsIContent* aContent,
+ uint32_t aScrollType)
+{
+ nsIPresShell::ScrollAxis vertical, horizontal;
+ ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
+ aPresShell->ScrollContentIntoView(aContent, vertical, horizontal,
+ nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
+}
+
+bool
+nsCoreUtils::IsWhitespaceString(const nsSubstring& aString)
+{
+ nsSubstring::const_char_iterator iterBegin, iterEnd;
+
+ aString.BeginReading(iterBegin);
+ aString.EndReading(iterEnd);
+
+ while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
+ ++iterBegin;
+
+ return iterBegin == iterEnd;
+}
+
+bool
+nsCoreUtils::AccEventObserversExist()
+{
+ nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
+ NS_ENSURE_TRUE(obsService, false);
+
+ nsCOMPtr<nsISimpleEnumerator> observers;
+ obsService->EnumerateObservers(NS_ACCESSIBLE_EVENT_TOPIC,
+ getter_AddRefs(observers));
+ NS_ENSURE_TRUE(observers, false);
+
+ bool hasObservers = false;
+ observers->HasMoreElements(&hasObservers);
+
+ return hasObservers;
+}
+
+void
+nsCoreUtils::DispatchAccEvent(RefPtr<nsIAccessibleEvent> event)
+{
+ nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
+ NS_ENSURE_TRUE_VOID(obsService);
+
+ obsService->NotifyObservers(event, NS_ACCESSIBLE_EVENT_TOPIC, nullptr);
+}
+
+void
+nsCoreUtils::XBLBindingRole(const nsIContent* aEl, nsAString& aRole)
+{
+ for (const nsXBLBinding* binding = aEl->GetXBLBinding(); binding;
+ binding = binding->GetBaseBinding()) {
+ nsIContent* bindingElm = binding->PrototypeBinding()->GetBindingElement();
+ bindingElm->GetAttr(kNameSpaceID_None, nsGkAtoms::role, aRole);
+ if (!aRole.IsEmpty())
+ break;
+ }
+}