accessible/src/base/nsCoreUtils.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsCoreUtils.h"
     8 #include "nsIAccessibleTypes.h"
    10 #include "nsIBaseWindow.h"
    11 #include "nsIDocShellTreeOwner.h"
    12 #include "nsIDocument.h"
    13 #include "nsIDOMHTMLDocument.h"
    14 #include "nsIDOMHTMLElement.h"
    15 #include "nsRange.h"
    16 #include "nsIBoxObject.h"
    17 #include "nsIDOMXULElement.h"
    18 #include "nsIDocShell.h"
    19 #include "nsIPresShell.h"
    20 #include "nsPresContext.h"
    21 #include "nsIScrollableFrame.h"
    22 #include "nsISelectionPrivate.h"
    23 #include "nsISelectionController.h"
    24 #include "mozilla/dom/TouchEvent.h"
    25 #include "mozilla/EventListenerManager.h"
    26 #include "mozilla/EventStateManager.h"
    27 #include "mozilla/MouseEvents.h"
    28 #include "mozilla/TouchEvents.h"
    29 #include "nsView.h"
    30 #include "nsGkAtoms.h"
    32 #include "nsComponentManagerUtils.h"
    34 #include "nsITreeBoxObject.h"
    35 #include "nsITreeColumns.h"
    36 #include "mozilla/dom/Element.h"
    38 using namespace mozilla;
    40 ////////////////////////////////////////////////////////////////////////////////
    41 // nsCoreUtils
    42 ////////////////////////////////////////////////////////////////////////////////
    44 bool
    45 nsCoreUtils::HasClickListener(nsIContent *aContent)
    46 {
    47   NS_ENSURE_TRUE(aContent, false);
    48   EventListenerManager* listenerManager =
    49     aContent->GetExistingListenerManager();
    51   return listenerManager &&
    52     (listenerManager->HasListenersFor(nsGkAtoms::onclick) ||
    53      listenerManager->HasListenersFor(nsGkAtoms::onmousedown) ||
    54      listenerManager->HasListenersFor(nsGkAtoms::onmouseup));
    55 }
    57 void
    58 nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
    59                                 int32_t aRowIndex, nsITreeColumn *aColumn,
    60                                 const nsCString& aPseudoElt)
    61 {
    62   nsCOMPtr<nsIDOMElement> tcElm;
    63   aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
    64   if (!tcElm)
    65     return;
    67   nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
    68   nsIDocument *document = tcContent->GetCurrentDoc();
    69   if (!document)
    70     return;
    72   nsCOMPtr<nsIPresShell> presShell = document->GetShell();
    73   if (!presShell)
    74     return;
    76   // Ensure row is visible.
    77   aTreeBoxObj->EnsureRowIsVisible(aRowIndex);
    79   // Calculate x and y coordinates.
    80   int32_t x = 0, y = 0, width = 0, height = 0;
    81   nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn,
    82                                                   aPseudoElt,
    83                                                   &x, &y, &width, &height);
    84   if (NS_FAILED(rv))
    85     return;
    87   nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
    88   nsCOMPtr<nsIBoxObject> tcBoxObj;
    89   tcXULElm->GetBoxObject(getter_AddRefs(tcBoxObj));
    91   int32_t tcX = 0;
    92   tcBoxObj->GetX(&tcX);
    94   int32_t tcY = 0;
    95   tcBoxObj->GetY(&tcY);
    97   // Dispatch mouse events.
    98   nsWeakFrame tcFrame = tcContent->GetPrimaryFrame();
    99   nsIFrame* rootFrame = presShell->GetRootFrame();
   101   nsPoint offset;
   102   nsIWidget *rootWidget =
   103     rootFrame->GetViewExternal()->GetNearestWidget(&offset);
   105   nsRefPtr<nsPresContext> presContext = presShell->GetPresContext();
   107   int32_t cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) +
   108     presContext->AppUnitsToDevPixels(offset.x);
   109   int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) +
   110     presContext->AppUnitsToDevPixels(offset.y);
   112   // XUL is just desktop, so there is no real reason for senfing touch events.
   113   DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, cnvdX, cnvdY,
   114                      tcContent, tcFrame, presShell, rootWidget);
   116   DispatchMouseEvent(NS_MOUSE_BUTTON_UP, cnvdX, cnvdY,
   117                      tcContent, tcFrame, presShell, rootWidget);
   118 }
   120 void
   121 nsCoreUtils::DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY,
   122                                 nsIContent *aContent, nsIFrame *aFrame,
   123                                 nsIPresShell *aPresShell, nsIWidget *aRootWidget)
   124 {
   125   WidgetMouseEvent event(true, aEventType, aRootWidget,
   126                          WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
   128   event.refPoint = LayoutDeviceIntPoint(aX, aY);
   130   event.clickCount = 1;
   131   event.button = WidgetMouseEvent::eLeftButton;
   132   event.time = PR_IntervalNow();
   133   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
   135   nsEventStatus status = nsEventStatus_eIgnore;
   136   aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
   137 }
   139 void
   140 nsCoreUtils::DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY,
   141                                 nsIContent* aContent, nsIFrame* aFrame,
   142                                 nsIPresShell* aPresShell, nsIWidget* aRootWidget)
   143 {
   144   if (!dom::TouchEvent::PrefEnabled())
   145     return;
   147   WidgetTouchEvent event(true, aEventType, aRootWidget);
   149   event.time = PR_IntervalNow();
   151   // XXX: Touch has an identifier of -1 to hint that it is synthesized.
   152   nsRefPtr<dom::Touch> t = new dom::Touch(-1, nsIntPoint(aX, aY),
   153                                           nsIntPoint(1, 1), 0.0f, 1.0f);
   154   t->SetTarget(aContent);
   155   event.touches.AppendElement(t);
   156   nsEventStatus status = nsEventStatus_eIgnore;
   157   aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
   158 }
   160 uint32_t
   161 nsCoreUtils::GetAccessKeyFor(nsIContent* aContent)
   162 {
   163   // Accesskeys are registered by @accesskey attribute only. At first check
   164   // whether it is presented on the given element to avoid the slow
   165   // EventStateManager::GetRegisteredAccessKey() method.
   166   if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::accesskey))
   167     return 0;
   169   nsIPresShell* presShell = aContent->OwnerDoc()->GetShell();
   170   if (!presShell)
   171     return 0;
   173   nsPresContext *presContext = presShell->GetPresContext();
   174   if (!presContext)
   175     return 0;
   177   EventStateManager *esm = presContext->EventStateManager();
   178   if (!esm)
   179     return 0;
   181   return esm->GetRegisteredAccessKey(aContent);
   182 }
   184 nsIContent *
   185 nsCoreUtils::GetDOMElementFor(nsIContent *aContent)
   186 {
   187   if (aContent->IsElement())
   188     return aContent;
   190   if (aContent->IsNodeOfType(nsINode::eTEXT))
   191     return aContent->GetFlattenedTreeParent();
   193   return nullptr;
   194 }
   196 nsINode *
   197 nsCoreUtils::GetDOMNodeFromDOMPoint(nsINode *aNode, uint32_t aOffset)
   198 {
   199   if (aNode && aNode->IsElement()) {
   200     uint32_t childCount = aNode->GetChildCount();
   201     NS_ASSERTION(aOffset <= childCount, "Wrong offset of the DOM point!");
   203     // The offset can be after last child of container node that means DOM point
   204     // is placed immediately after the last child. In this case use the DOM node
   205     // from the given DOM point is used as result node.
   206     if (aOffset != childCount)
   207       return aNode->GetChildAt(aOffset);
   208   }
   210   return aNode;
   211 }
   213 nsIContent*
   214 nsCoreUtils::GetRoleContent(nsINode *aNode)
   215 {
   216   nsCOMPtr<nsIContent> content(do_QueryInterface(aNode));
   217   if (!content) {
   218     nsCOMPtr<nsIDocument> doc(do_QueryInterface(aNode));
   219     if (doc) {
   220       nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(aNode));
   221       if (htmlDoc) {
   222         nsCOMPtr<nsIDOMHTMLElement> bodyElement;
   223         htmlDoc->GetBody(getter_AddRefs(bodyElement));
   224         content = do_QueryInterface(bodyElement);
   225       }
   226       else {
   227         return doc->GetDocumentElement();
   228       }
   229     }
   230   }
   232   return content;
   233 }
   235 bool
   236 nsCoreUtils::IsAncestorOf(nsINode *aPossibleAncestorNode,
   237                           nsINode *aPossibleDescendantNode,
   238                           nsINode *aRootNode)
   239 {
   240   NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, false);
   242   nsINode *parentNode = aPossibleDescendantNode;
   243   while ((parentNode = parentNode->GetParentNode()) &&
   244          parentNode != aRootNode) {
   245     if (parentNode == aPossibleAncestorNode)
   246       return true;
   247   }
   249   return false;
   250 }
   252 nsresult
   253 nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
   254                                uint32_t aScrollType)
   255 {
   256   nsIPresShell::ScrollAxis vertical, horizontal;
   257   ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
   259   return ScrollSubstringTo(aFrame, aRange, vertical, horizontal);
   260 }
   262 nsresult
   263 nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
   264                                nsIPresShell::ScrollAxis aVertical,
   265                                nsIPresShell::ScrollAxis aHorizontal)
   266 {
   267   if (!aFrame)
   268     return NS_ERROR_FAILURE;
   270   nsPresContext *presContext = aFrame->PresContext();
   272   nsCOMPtr<nsISelectionController> selCon;
   273   aFrame->GetSelectionController(presContext, getter_AddRefs(selCon));
   274   NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
   276   nsCOMPtr<nsISelection> selection;
   277   selCon->GetSelection(nsISelectionController::SELECTION_ACCESSIBILITY,
   278                        getter_AddRefs(selection));
   280   nsCOMPtr<nsISelectionPrivate> privSel(do_QueryInterface(selection));
   281   selection->RemoveAllRanges();
   282   selection->AddRange(aRange);
   284   privSel->ScrollIntoViewInternal(
   285     nsISelectionController::SELECTION_ANCHOR_REGION,
   286     true, aVertical, aHorizontal);
   288   selection->CollapseToStart();
   290   return NS_OK;
   291 }
   293 void
   294 nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame,
   295                                 nsIFrame *aFrame,
   296                                 const nsIntPoint& aPoint)
   297 {
   298   nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollableFrame);
   299   if (!scrollableFrame)
   300     return;
   302   nsPoint point =
   303     aPoint.ToAppUnits(aFrame->PresContext()->AppUnitsPerDevPixel());
   304   nsRect frameRect = aFrame->GetScreenRectInAppUnits();
   305   nsPoint deltaPoint(point.x - frameRect.x, point.y - frameRect.y);
   307   nsPoint scrollPoint = scrollableFrame->GetScrollPosition();
   308   scrollPoint -= deltaPoint;
   310   scrollableFrame->ScrollTo(scrollPoint, nsIScrollableFrame::INSTANT);
   311 }
   313 void
   314 nsCoreUtils::ConvertScrollTypeToPercents(uint32_t aScrollType,
   315                                          nsIPresShell::ScrollAxis *aVertical,
   316                                          nsIPresShell::ScrollAxis *aHorizontal)
   317 {
   318   int16_t whereY, whereX;
   319   nsIPresShell::WhenToScroll whenY, whenX;
   320   switch (aScrollType)
   321   {
   322     case nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT:
   323       whereY = nsIPresShell::SCROLL_TOP;
   324       whenY  = nsIPresShell::SCROLL_ALWAYS;
   325       whereX = nsIPresShell::SCROLL_LEFT;
   326       whenX  = nsIPresShell::SCROLL_ALWAYS;
   327       break;
   328     case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT:
   329       whereY = nsIPresShell::SCROLL_BOTTOM;
   330       whenY  = nsIPresShell::SCROLL_ALWAYS;
   331       whereX = nsIPresShell::SCROLL_RIGHT;
   332       whenX  = nsIPresShell::SCROLL_ALWAYS;
   333       break;
   334     case nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE:
   335       whereY = nsIPresShell::SCROLL_TOP;
   336       whenY  = nsIPresShell::SCROLL_ALWAYS;
   337       whereX = nsIPresShell::SCROLL_MINIMUM;
   338       whenX  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
   339       break;
   340     case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_EDGE:
   341       whereY = nsIPresShell::SCROLL_BOTTOM;
   342       whenY  = nsIPresShell::SCROLL_ALWAYS;
   343       whereX = nsIPresShell::SCROLL_MINIMUM;
   344       whenX  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
   345       break;
   346     case nsIAccessibleScrollType::SCROLL_TYPE_LEFT_EDGE:
   347       whereY = nsIPresShell::SCROLL_MINIMUM;
   348       whenY  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
   349       whereX = nsIPresShell::SCROLL_LEFT;
   350       whenX  = nsIPresShell::SCROLL_ALWAYS;
   351       break;
   352     case nsIAccessibleScrollType::SCROLL_TYPE_RIGHT_EDGE:
   353       whereY = nsIPresShell::SCROLL_MINIMUM;
   354       whenY  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
   355       whereX = nsIPresShell::SCROLL_RIGHT;
   356       whenX  = nsIPresShell::SCROLL_ALWAYS;
   357       break;
   358     default:
   359       whereY = nsIPresShell::SCROLL_MINIMUM;
   360       whenY  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
   361       whereX = nsIPresShell::SCROLL_MINIMUM;
   362       whenX  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
   363   }
   364   *aVertical = nsIPresShell::ScrollAxis(whereY, whenY);
   365   *aHorizontal = nsIPresShell::ScrollAxis(whereX, whenX);
   366 }
   368 nsIntPoint
   369 nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode)
   370 {
   371   nsIntPoint coords(0, 0);
   372   nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellFor(aNode));
   373   if (!treeItem)
   374     return coords;
   376   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   377   treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
   378   if (!treeOwner)
   379     return coords;
   381   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(treeOwner);
   382   if (baseWindow)
   383     baseWindow->GetPosition(&coords.x, &coords.y); // in device pixels
   385   return coords;
   386 }
   388 already_AddRefed<nsIDocShell>
   389 nsCoreUtils::GetDocShellFor(nsINode *aNode)
   390 {
   391   if (!aNode)
   392     return nullptr;
   394   nsCOMPtr<nsIDocShell> docShell = aNode->OwnerDoc()->GetDocShell();
   395   return docShell.forget();
   396 }
   398 bool
   399 nsCoreUtils::IsRootDocument(nsIDocument *aDocument)
   400 {
   401   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell();
   402   NS_ASSERTION(docShellTreeItem, "No document shell for document!");
   404   nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
   405   docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem));
   407   return !parentTreeItem;
   408 }
   410 bool
   411 nsCoreUtils::IsContentDocument(nsIDocument *aDocument)
   412 {
   413   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell();
   414   NS_ASSERTION(docShellTreeItem, "No document shell tree item for document!");
   416   return (docShellTreeItem->ItemType() == nsIDocShellTreeItem::typeContent);
   417 }
   419 bool
   420 nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode)
   421 {
   422   nsCOMPtr<nsIDocShellTreeItem> treeItem(aDocumentNode->GetDocShell());
   424   nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
   425   treeItem->GetParent(getter_AddRefs(parentTreeItem));
   427   // Tab document running in own process doesn't have parent.
   428   if (XRE_GetProcessType() == GeckoProcessType_Content)
   429     return !parentTreeItem;
   431   // Parent of docshell for tab document running in chrome process is root.
   432   nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
   433   treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
   435   return parentTreeItem == rootTreeItem;
   436 }
   438 bool
   439 nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
   440 {
   441   nsIURI *uri = aDocument->GetDocumentURI();
   442   bool isAboutScheme = false;
   443   uri->SchemeIs("about", &isAboutScheme);
   444   if (!isAboutScheme)
   445     return false;
   447   nsAutoCString path;
   448   uri->GetPath(path);
   450   NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
   451   NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
   453   return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
   454 }
   456 bool
   457 nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID)
   458 {
   459   nsIAtom *idAttribute = aContent->GetIDAttributeName();
   460   return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : false;
   461 }
   463 bool
   464 nsCoreUtils::GetUIntAttr(nsIContent *aContent, nsIAtom *aAttr, int32_t *aUInt)
   465 {
   466   nsAutoString value;
   467   aContent->GetAttr(kNameSpaceID_None, aAttr, value);
   468   if (!value.IsEmpty()) {
   469     nsresult error = NS_OK;
   470     int32_t integer = value.ToInteger(&error);
   471     if (NS_SUCCEEDED(error) && integer > 0) {
   472       *aUInt = integer;
   473       return true;
   474     }
   475   }
   477   return false;
   478 }
   480 void
   481 nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
   482                             nsAString& aLanguage)
   483 {
   484   aLanguage.Truncate();
   486   nsIContent *walkUp = aContent;
   487   while (walkUp && walkUp != aRootContent &&
   488          !walkUp->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLanguage))
   489     walkUp = walkUp->GetParent();
   490 }
   492 already_AddRefed<nsIBoxObject>
   493 nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
   494 {
   495   nsCOMPtr<nsIDOMElement> tcElm;
   496   aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
   497   nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
   498   if (!tcXULElm)
   499     return nullptr;
   501   nsCOMPtr<nsIBoxObject> boxObj;
   502   tcXULElm->GetBoxObject(getter_AddRefs(boxObj));
   503   return boxObj.forget();
   504 }
   506 already_AddRefed<nsITreeBoxObject>
   507 nsCoreUtils::GetTreeBoxObject(nsIContent *aContent)
   508 {
   509   // Find DOMNode's parents recursively until reach the <tree> tag
   510   nsIContent* currentContent = aContent;
   511   while (currentContent) {
   512     if (currentContent->NodeInfo()->Equals(nsGkAtoms::tree,
   513                                            kNameSpaceID_XUL)) {
   514       // We will get the nsITreeBoxObject from the tree node
   515       nsCOMPtr<nsIDOMXULElement> xulElement(do_QueryInterface(currentContent));
   516       if (xulElement) {
   517         nsCOMPtr<nsIBoxObject> box;
   518         xulElement->GetBoxObject(getter_AddRefs(box));
   519         nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
   520         if (treeBox)
   521           return treeBox.forget();
   522       }
   523     }
   524     currentContent = currentContent->GetFlattenedTreeParent();
   525   }
   527   return nullptr;
   528 }
   530 already_AddRefed<nsITreeColumn>
   531 nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
   532 {
   533   nsCOMPtr<nsITreeColumns> cols;
   534   aTree->GetColumns(getter_AddRefs(cols));
   535   if (!cols)
   536     return nullptr;
   538   nsCOMPtr<nsITreeColumn> column;
   539   cols->GetFirstColumn(getter_AddRefs(column));
   540   if (column && IsColumnHidden(column))
   541     return GetNextSensibleColumn(column);
   543   return column.forget();
   544 }
   546 uint32_t
   547 nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree)
   548 {
   549   uint32_t count = 0;
   551   nsCOMPtr<nsITreeColumns> cols;
   552   aTree->GetColumns(getter_AddRefs(cols));
   553   if (!cols)
   554     return count;
   556   nsCOMPtr<nsITreeColumn> column;
   557   cols->GetFirstColumn(getter_AddRefs(column));
   559   while (column) {
   560     if (!IsColumnHidden(column))
   561       count++;
   563     nsCOMPtr<nsITreeColumn> nextColumn;
   564     column->GetNext(getter_AddRefs(nextColumn));
   565     column.swap(nextColumn);
   566   }
   568   return count;
   569 }
   571 already_AddRefed<nsITreeColumn>
   572 nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, uint32_t aIndex)
   573 {
   574   uint32_t idx = aIndex;
   576   nsCOMPtr<nsITreeColumn> column = GetFirstSensibleColumn(aTree);
   577   while (column) {
   578     if (idx == 0)
   579       return column.forget();
   581     idx--;
   582     column = GetNextSensibleColumn(column);
   583   }
   585   return nullptr;
   586 }
   588 already_AddRefed<nsITreeColumn>
   589 nsCoreUtils::GetNextSensibleColumn(nsITreeColumn *aColumn)
   590 {
   591   nsCOMPtr<nsITreeColumn> nextColumn;
   592   aColumn->GetNext(getter_AddRefs(nextColumn));
   594   while (nextColumn && IsColumnHidden(nextColumn)) {
   595     nsCOMPtr<nsITreeColumn> tempColumn;
   596     nextColumn->GetNext(getter_AddRefs(tempColumn));
   597     nextColumn.swap(tempColumn);
   598   }
   600   return nextColumn.forget();
   601 }
   603 already_AddRefed<nsITreeColumn>
   604 nsCoreUtils::GetPreviousSensibleColumn(nsITreeColumn *aColumn)
   605 {
   606   nsCOMPtr<nsITreeColumn> prevColumn;
   607   aColumn->GetPrevious(getter_AddRefs(prevColumn));
   609   while (prevColumn && IsColumnHidden(prevColumn)) {
   610     nsCOMPtr<nsITreeColumn> tempColumn;
   611     prevColumn->GetPrevious(getter_AddRefs(tempColumn));
   612     prevColumn.swap(tempColumn);
   613   }
   615   return prevColumn.forget();
   616 }
   618 bool
   619 nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn)
   620 {
   621   nsCOMPtr<nsIDOMElement> element;
   622   aColumn->GetElement(getter_AddRefs(element));
   623   nsCOMPtr<nsIContent> content = do_QueryInterface(element);
   624   return content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
   625                               nsGkAtoms::_true, eCaseMatters);
   626 }
   628 void
   629 nsCoreUtils::ScrollTo(nsIPresShell* aPresShell, nsIContent* aContent,
   630                       uint32_t aScrollType)
   631 {
   632   nsIPresShell::ScrollAxis vertical, horizontal;
   633   ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
   634   aPresShell->ScrollContentIntoView(aContent, vertical, horizontal,
   635                                     nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
   636 }
   638 bool
   639 nsCoreUtils::IsWhitespaceString(const nsSubstring& aString)
   640 {
   641   nsSubstring::const_char_iterator iterBegin, iterEnd;
   643   aString.BeginReading(iterBegin);
   644   aString.EndReading(iterEnd);
   646   while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
   647     ++iterBegin;
   649   return iterBegin == iterEnd;
   650 }

mercurial