Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/base/nsCoreUtils.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
5
6
#include "nsCoreUtils.h"
7
8
#include "nsIAccessibleTypes.h"
9
10
#include "nsIBaseWindow.h"
11
#include "nsIDocShellTreeOwner.h"
12
#include "nsIDocument.h"
13
#include "nsRange.h"
14
#include "nsIBoxObject.h"
15
#include "nsXULElement.h"
16
#include "mozilla/dom/BoxObject.h"
17
#include "nsIDocShell.h"
18
#include "nsIObserverService.h"
19
#include "nsIPresShell.h"
20
#include "nsPresContext.h"
21
#include "nsIScrollableFrame.h"
22
#include "nsISelectionController.h"
23
#include "nsISimpleEnumerator.h"
24
#include "mozilla/dom/TouchEvent.h"
25
#include "mozilla/ErrorResult.h"
26
#include "mozilla/EventListenerManager.h"
27
#include "mozilla/EventStateManager.h"
28
#include "mozilla/MouseEvents.h"
29
#include "mozilla/TouchEvents.h"
30
#include "nsView.h"
31
#include "nsGkAtoms.h"
32
33
#include "nsComponentManagerUtils.h"
34
35
#include "nsITreeBoxObject.h"
36
#include "nsTreeColumns.h"
37
#include "mozilla/dom/Element.h"
38
#include "mozilla/dom/HTMLLabelElement.h"
39
#include "mozilla/dom/MouseEventBinding.h"
40
#include "mozilla/dom/Selection.h"
41
42
using namespace mozilla;
43
44
////////////////////////////////////////////////////////////////////////////////
45
// nsCoreUtils
46
////////////////////////////////////////////////////////////////////////////////
47
48
bool
49
nsCoreUtils::IsLabelWithControl(nsIContent* aContent)
50
0
{
51
0
  dom::HTMLLabelElement* label = dom::HTMLLabelElement::FromNode(aContent);
52
0
  if (label && label->GetControl())
53
0
    return true;
54
0
55
0
  return false;
56
0
}
57
58
bool
59
nsCoreUtils::HasClickListener(nsIContent *aContent)
60
0
{
61
0
  NS_ENSURE_TRUE(aContent, false);
62
0
  EventListenerManager* listenerManager =
63
0
    aContent->GetExistingListenerManager();
64
0
65
0
  return listenerManager &&
66
0
    (listenerManager->HasListenersFor(nsGkAtoms::onclick) ||
67
0
     listenerManager->HasListenersFor(nsGkAtoms::onmousedown) ||
68
0
     listenerManager->HasListenersFor(nsGkAtoms::onmouseup));
69
0
}
70
71
void
72
nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
73
                                int32_t aRowIndex, nsTreeColumn *aColumn,
74
                                const nsAString& aPseudoElt)
75
0
{
76
0
  RefPtr<dom::Element> tcElm;
77
0
  aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
78
0
  if (!tcElm)
79
0
    return;
80
0
81
0
  nsIDocument *document = tcElm->GetUncomposedDoc();
82
0
  if (!document)
83
0
    return;
84
0
85
0
  nsCOMPtr<nsIPresShell> presShell = document->GetShell();
86
0
  if (!presShell)
87
0
    return;
88
0
89
0
  // Ensure row is visible.
90
0
  aTreeBoxObj->EnsureRowIsVisible(aRowIndex);
91
0
92
0
  // Calculate x and y coordinates.
93
0
  int32_t x = 0, y = 0, width = 0, height = 0;
94
0
  nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn,
95
0
                                                  aPseudoElt,
96
0
                                                  &x, &y, &width, &height);
97
0
  if (NS_FAILED(rv))
98
0
    return;
99
0
100
0
  nsCOMPtr<nsIBoxObject> tcBoxObj =
101
0
    nsXULElement::FromNode(tcElm)->GetBoxObject(IgnoreErrors());
102
0
103
0
  int32_t tcX = 0;
104
0
  tcBoxObj->GetX(&tcX);
105
0
106
0
  int32_t tcY = 0;
107
0
  tcBoxObj->GetY(&tcY);
108
0
109
0
  // Dispatch mouse events.
110
0
  AutoWeakFrame tcFrame = tcElm->GetPrimaryFrame();
111
0
  nsIFrame* rootFrame = presShell->GetRootFrame();
112
0
113
0
  nsPoint offset;
114
0
  nsIWidget *rootWidget =
115
0
    rootFrame->GetView()->GetNearestWidget(&offset);
116
0
117
0
  RefPtr<nsPresContext> presContext = presShell->GetPresContext();
118
0
119
0
  int32_t cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) +
120
0
    presContext->AppUnitsToDevPixels(offset.x);
121
0
  int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) +
122
0
    presContext->AppUnitsToDevPixels(offset.y);
123
0
124
0
  // XUL is just desktop, so there is no real reason for senfing touch events.
125
0
  DispatchMouseEvent(eMouseDown, cnvdX, cnvdY,
126
0
                     tcElm, tcFrame, presShell, rootWidget);
127
0
128
0
  DispatchMouseEvent(eMouseUp, cnvdX, cnvdY,
129
0
                     tcElm, tcFrame, presShell, rootWidget);
130
0
}
131
132
void
133
nsCoreUtils::DispatchMouseEvent(EventMessage aMessage, int32_t aX, int32_t aY,
134
                                nsIContent *aContent, nsIFrame *aFrame,
135
                                nsIPresShell *aPresShell, nsIWidget *aRootWidget)
136
0
{
137
0
  WidgetMouseEvent event(true, aMessage, aRootWidget,
138
0
                         WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
139
0
140
0
  event.mRefPoint = LayoutDeviceIntPoint(aX, aY);
141
0
142
0
  event.mClickCount = 1;
143
0
  event.button = WidgetMouseEvent::eLeftButton;
144
0
  event.mTime = PR_IntervalNow();
145
0
  event.inputSource = dom::MouseEvent_Binding::MOZ_SOURCE_UNKNOWN;
146
0
147
0
  nsEventStatus status = nsEventStatus_eIgnore;
148
0
  aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
149
0
}
150
151
void
152
nsCoreUtils::DispatchTouchEvent(EventMessage aMessage, int32_t aX, int32_t aY,
153
                                nsIContent* aContent, nsIFrame* aFrame,
154
                                nsIPresShell* aPresShell, nsIWidget* aRootWidget)
155
0
{
156
0
  nsIDocShell* docShell = nullptr;
157
0
  if (aPresShell->GetDocument()) {
158
0
    docShell = aPresShell->GetDocument()->GetDocShell();
159
0
  }
160
0
  if (!dom::TouchEvent::PrefEnabled(docShell)) {
161
0
    return;
162
0
  }
163
0
164
0
  WidgetTouchEvent event(true, aMessage, aRootWidget);
165
0
166
0
  event.mTime = PR_IntervalNow();
167
0
168
0
  // XXX: Touch has an identifier of -1 to hint that it is synthesized.
169
0
  RefPtr<dom::Touch> t = new dom::Touch(-1, LayoutDeviceIntPoint(aX, aY),
170
0
                                        LayoutDeviceIntPoint(1, 1), 0.0f, 1.0f);
171
0
  t->SetTouchTarget(aContent);
172
0
  event.mTouches.AppendElement(t);
173
0
  nsEventStatus status = nsEventStatus_eIgnore;
174
0
  aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status);
175
0
}
176
177
uint32_t
178
nsCoreUtils::GetAccessKeyFor(nsIContent* aContent)
179
0
{
180
0
  // Accesskeys are registered by @accesskey attribute only. At first check
181
0
  // whether it is presented on the given element to avoid the slow
182
0
  // EventStateManager::GetRegisteredAccessKey() method.
183
0
  if (!aContent->IsElement() ||
184
0
      !aContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::accesskey))
185
0
    return 0;
186
0
187
0
  nsPresContext* presContext = aContent->OwnerDoc()->GetPresContext();
188
0
  if (!presContext)
189
0
    return 0;
190
0
191
0
  EventStateManager *esm = presContext->EventStateManager();
192
0
  if (!esm)
193
0
    return 0;
194
0
195
0
  return esm->GetRegisteredAccessKey(aContent->AsElement());
196
0
}
197
198
nsIContent *
199
nsCoreUtils::GetDOMElementFor(nsIContent *aContent)
200
0
{
201
0
  if (aContent->IsElement())
202
0
    return aContent;
203
0
204
0
  if (aContent->IsText())
205
0
    return aContent->GetFlattenedTreeParent();
206
0
207
0
  return nullptr;
208
0
}
209
210
nsINode *
211
nsCoreUtils::GetDOMNodeFromDOMPoint(nsINode *aNode, uint32_t aOffset)
212
0
{
213
0
  if (aNode && aNode->IsElement()) {
214
0
    uint32_t childCount = aNode->GetChildCount();
215
0
    NS_ASSERTION(aOffset <= childCount, "Wrong offset of the DOM point!");
216
0
217
0
    // The offset can be after last child of container node that means DOM point
218
0
    // is placed immediately after the last child. In this case use the DOM node
219
0
    // from the given DOM point is used as result node.
220
0
    if (aOffset != childCount)
221
0
      return aNode->GetChildAt_Deprecated(aOffset);
222
0
  }
223
0
224
0
  return aNode;
225
0
}
226
227
bool
228
nsCoreUtils::IsAncestorOf(nsINode *aPossibleAncestorNode,
229
                          nsINode *aPossibleDescendantNode,
230
                          nsINode *aRootNode)
231
0
{
232
0
  NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, false);
233
0
234
0
  nsINode *parentNode = aPossibleDescendantNode;
235
0
  while ((parentNode = parentNode->GetParentNode()) &&
236
0
         parentNode != aRootNode) {
237
0
    if (parentNode == aPossibleAncestorNode)
238
0
      return true;
239
0
  }
240
0
241
0
  return false;
242
0
}
243
244
nsresult
245
nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
246
                               uint32_t aScrollType)
247
0
{
248
0
  nsIPresShell::ScrollAxis vertical, horizontal;
249
0
  ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
250
0
251
0
  return ScrollSubstringTo(aFrame, aRange, vertical, horizontal);
252
0
}
253
254
nsresult
255
nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange,
256
                               nsIPresShell::ScrollAxis aVertical,
257
                               nsIPresShell::ScrollAxis aHorizontal)
258
0
{
259
0
  if (!aFrame || !aRange) {
260
0
    return NS_ERROR_FAILURE;
261
0
  }
262
0
263
0
  nsPresContext *presContext = aFrame->PresContext();
264
0
265
0
  nsCOMPtr<nsISelectionController> selCon;
266
0
  aFrame->GetSelectionController(presContext, getter_AddRefs(selCon));
267
0
  NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
268
0
269
0
  RefPtr<dom::Selection> selection =
270
0
    selCon->GetSelection(nsISelectionController::SELECTION_ACCESSIBILITY);
271
0
272
0
  selection->RemoveAllRanges(IgnoreErrors());
273
0
  selection->AddRange(*aRange, IgnoreErrors());
274
0
275
0
  selection->ScrollIntoView(nsISelectionController::SELECTION_ANCHOR_REGION,
276
0
                            aVertical, aHorizontal,
277
0
                            Selection::SCROLL_SYNCHRONOUS);
278
0
279
0
  selection->CollapseToStart(IgnoreErrors());
280
0
281
0
  return NS_OK;
282
0
}
283
284
void
285
nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame,
286
                                nsIFrame *aFrame,
287
                                const nsIntPoint& aPoint)
288
0
{
289
0
  nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollableFrame);
290
0
  if (!scrollableFrame)
291
0
    return;
292
0
293
0
  nsPoint point =
294
0
    ToAppUnits(aPoint, aFrame->PresContext()->AppUnitsPerDevPixel());
295
0
  nsRect frameRect = aFrame->GetScreenRectInAppUnits();
296
0
  nsPoint deltaPoint = point - frameRect.TopLeft();
297
0
298
0
  nsPoint scrollPoint = scrollableFrame->GetScrollPosition();
299
0
  scrollPoint -= deltaPoint;
300
0
301
0
  scrollableFrame->ScrollTo(scrollPoint, nsIScrollableFrame::INSTANT);
302
0
}
303
304
void
305
nsCoreUtils::ConvertScrollTypeToPercents(uint32_t aScrollType,
306
                                         nsIPresShell::ScrollAxis *aVertical,
307
                                         nsIPresShell::ScrollAxis *aHorizontal)
308
0
{
309
0
  int16_t whereY, whereX;
310
0
  nsIPresShell::WhenToScroll whenY, whenX;
311
0
  switch (aScrollType)
312
0
  {
313
0
    case nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT:
314
0
      whereY = nsIPresShell::SCROLL_TOP;
315
0
      whenY  = nsIPresShell::SCROLL_ALWAYS;
316
0
      whereX = nsIPresShell::SCROLL_LEFT;
317
0
      whenX  = nsIPresShell::SCROLL_ALWAYS;
318
0
      break;
319
0
    case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT:
320
0
      whereY = nsIPresShell::SCROLL_BOTTOM;
321
0
      whenY  = nsIPresShell::SCROLL_ALWAYS;
322
0
      whereX = nsIPresShell::SCROLL_RIGHT;
323
0
      whenX  = nsIPresShell::SCROLL_ALWAYS;
324
0
      break;
325
0
    case nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE:
326
0
      whereY = nsIPresShell::SCROLL_TOP;
327
0
      whenY  = nsIPresShell::SCROLL_ALWAYS;
328
0
      whereX = nsIPresShell::SCROLL_MINIMUM;
329
0
      whenX  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
330
0
      break;
331
0
    case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_EDGE:
332
0
      whereY = nsIPresShell::SCROLL_BOTTOM;
333
0
      whenY  = nsIPresShell::SCROLL_ALWAYS;
334
0
      whereX = nsIPresShell::SCROLL_MINIMUM;
335
0
      whenX  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
336
0
      break;
337
0
    case nsIAccessibleScrollType::SCROLL_TYPE_LEFT_EDGE:
338
0
      whereY = nsIPresShell::SCROLL_MINIMUM;
339
0
      whenY  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
340
0
      whereX = nsIPresShell::SCROLL_LEFT;
341
0
      whenX  = nsIPresShell::SCROLL_ALWAYS;
342
0
      break;
343
0
    case nsIAccessibleScrollType::SCROLL_TYPE_RIGHT_EDGE:
344
0
      whereY = nsIPresShell::SCROLL_MINIMUM;
345
0
      whenY  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
346
0
      whereX = nsIPresShell::SCROLL_RIGHT;
347
0
      whenX  = nsIPresShell::SCROLL_ALWAYS;
348
0
      break;
349
0
    default:
350
0
      whereY = nsIPresShell::SCROLL_MINIMUM;
351
0
      whenY  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
352
0
      whereX = nsIPresShell::SCROLL_MINIMUM;
353
0
      whenX  = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE;
354
0
  }
355
0
  *aVertical = nsIPresShell::ScrollAxis(whereY, whenY);
356
0
  *aHorizontal = nsIPresShell::ScrollAxis(whereX, whenX);
357
0
}
358
359
nsIntPoint
360
nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode)
361
0
{
362
0
  nsIntPoint coords(0, 0);
363
0
  nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellFor(aNode));
364
0
  if (!treeItem)
365
0
    return coords;
366
0
367
0
  nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
368
0
  treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
369
0
  if (!treeOwner)
370
0
    return coords;
371
0
372
0
  nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(treeOwner);
373
0
  if (baseWindow)
374
0
    baseWindow->GetPosition(&coords.x, &coords.y); // in device pixels
375
0
376
0
  return coords;
377
0
}
378
379
already_AddRefed<nsIDocShell>
380
nsCoreUtils::GetDocShellFor(nsINode *aNode)
381
0
{
382
0
  if (!aNode)
383
0
    return nullptr;
384
0
385
0
  nsCOMPtr<nsIDocShell> docShell = aNode->OwnerDoc()->GetDocShell();
386
0
  return docShell.forget();
387
0
}
388
389
bool
390
nsCoreUtils::IsRootDocument(nsIDocument *aDocument)
391
0
{
392
0
  nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell();
393
0
  NS_ASSERTION(docShellTreeItem, "No document shell for document!");
394
0
395
0
  nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
396
0
  docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem));
397
0
398
0
  return !parentTreeItem;
399
0
}
400
401
bool
402
nsCoreUtils::IsContentDocument(nsIDocument *aDocument)
403
0
{
404
0
  nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = aDocument->GetDocShell();
405
0
  NS_ASSERTION(docShellTreeItem, "No document shell tree item for document!");
406
0
407
0
  return (docShellTreeItem->ItemType() == nsIDocShellTreeItem::typeContent);
408
0
}
409
410
bool
411
nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode)
412
0
{
413
0
  nsCOMPtr<nsIDocShellTreeItem> treeItem(aDocumentNode->GetDocShell());
414
0
415
0
  nsCOMPtr<nsIDocShellTreeItem> parentTreeItem;
416
0
  treeItem->GetParent(getter_AddRefs(parentTreeItem));
417
0
418
0
  // Tab document running in own process doesn't have parent.
419
0
  if (XRE_IsContentProcess())
420
0
    return !parentTreeItem;
421
0
422
0
  // Parent of docshell for tab document running in chrome process is root.
423
0
  nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
424
0
  treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
425
0
426
0
  return parentTreeItem == rootTreeItem;
427
0
}
428
429
bool
430
nsCoreUtils::IsErrorPage(nsIDocument *aDocument)
431
0
{
432
0
  nsIURI *uri = aDocument->GetDocumentURI();
433
0
  bool isAboutScheme = false;
434
0
  uri->SchemeIs("about", &isAboutScheme);
435
0
  if (!isAboutScheme)
436
0
    return false;
437
0
438
0
  nsAutoCString path;
439
0
  uri->GetPathQueryRef(path);
440
0
441
0
  NS_NAMED_LITERAL_CSTRING(neterror, "neterror");
442
0
  NS_NAMED_LITERAL_CSTRING(certerror, "certerror");
443
0
444
0
  return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror);
445
0
}
446
447
bool
448
nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID)
449
0
{
450
0
  return aContent->IsElement() &&
451
0
    aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::id, aID);
452
0
}
453
454
bool
455
nsCoreUtils::GetUIntAttr(nsIContent *aContent, nsAtom *aAttr, int32_t *aUInt)
456
0
{
457
0
  nsAutoString value;
458
0
  if (!aContent->IsElement()) {
459
0
    return false;
460
0
  }
461
0
  aContent->AsElement()->GetAttr(kNameSpaceID_None, aAttr, value);
462
0
  if (!value.IsEmpty()) {
463
0
    nsresult error = NS_OK;
464
0
    int32_t integer = value.ToInteger(&error);
465
0
    if (NS_SUCCEEDED(error) && integer > 0) {
466
0
      *aUInt = integer;
467
0
      return true;
468
0
    }
469
0
  }
470
0
471
0
  return false;
472
0
}
473
474
void
475
nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent,
476
                            nsAString& aLanguage)
477
0
{
478
0
  aLanguage.Truncate();
479
0
480
0
  nsIContent *walkUp = aContent;
481
0
  while (walkUp && walkUp != aRootContent &&
482
0
         (!walkUp->IsElement() ||
483
0
          !walkUp->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLanguage)))
484
0
    walkUp = walkUp->GetParent();
485
0
}
486
487
already_AddRefed<nsIBoxObject>
488
nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
489
0
{
490
0
  RefPtr<dom::Element> tcElm;
491
0
  aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
492
0
  RefPtr<nsXULElement> tcXULElm = nsXULElement::FromNodeOrNull(tcElm);
493
0
  if (!tcXULElm)
494
0
    return nullptr;
495
0
496
0
  return tcXULElm->GetBoxObject(IgnoreErrors());
497
0
}
498
499
already_AddRefed<nsITreeBoxObject>
500
nsCoreUtils::GetTreeBoxObject(nsIContent *aContent)
501
0
{
502
0
  // Find DOMNode's parents recursively until reach the <tree> tag
503
0
  nsIContent* currentContent = aContent;
504
0
  while (currentContent) {
505
0
    if (currentContent->NodeInfo()->Equals(nsGkAtoms::tree,
506
0
                                           kNameSpaceID_XUL)) {
507
0
      // We will get the nsITreeBoxObject from the tree node
508
0
      RefPtr<nsXULElement> xulElement =
509
0
        nsXULElement::FromNode(currentContent);
510
0
      nsCOMPtr<nsIBoxObject> box = xulElement->GetBoxObject(IgnoreErrors());
511
0
      nsCOMPtr<nsITreeBoxObject> treeBox(do_QueryInterface(box));
512
0
      if (treeBox)
513
0
        return treeBox.forget();
514
0
    }
515
0
    currentContent = currentContent->GetFlattenedTreeParent();
516
0
  }
517
0
518
0
  return nullptr;
519
0
}
520
521
already_AddRefed<nsTreeColumn>
522
nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree)
523
0
{
524
0
  RefPtr<nsTreeColumns> cols;
525
0
  aTree->GetColumns(getter_AddRefs(cols));
526
0
  if (!cols)
527
0
    return nullptr;
528
0
529
0
  RefPtr<nsTreeColumn> column = cols->GetFirstColumn();
530
0
  if (column && IsColumnHidden(column))
531
0
    return GetNextSensibleColumn(column);
532
0
533
0
  return column.forget();
534
0
}
535
536
uint32_t
537
nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree)
538
0
{
539
0
  uint32_t count = 0;
540
0
541
0
  RefPtr<nsTreeColumns> cols;
542
0
  aTree->GetColumns(getter_AddRefs(cols));
543
0
  if (!cols)
544
0
    return count;
545
0
546
0
  nsTreeColumn* column = cols->GetFirstColumn();
547
0
548
0
  while (column) {
549
0
    if (!IsColumnHidden(column))
550
0
      count++;
551
0
552
0
    column = column->GetNext();
553
0
  }
554
0
555
0
  return count;
556
0
}
557
558
already_AddRefed<nsTreeColumn>
559
nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, uint32_t aIndex)
560
0
{
561
0
  uint32_t idx = aIndex;
562
0
563
0
  nsCOMPtr<nsTreeColumn> column = GetFirstSensibleColumn(aTree);
564
0
  while (column) {
565
0
    if (idx == 0)
566
0
      return column.forget();
567
0
568
0
    idx--;
569
0
    column = GetNextSensibleColumn(column);
570
0
  }
571
0
572
0
  return nullptr;
573
0
}
574
575
already_AddRefed<nsTreeColumn>
576
nsCoreUtils::GetNextSensibleColumn(nsTreeColumn* aColumn)
577
0
{
578
0
  RefPtr<nsTreeColumn> nextColumn = aColumn->GetNext();
579
0
580
0
  while (nextColumn && IsColumnHidden(nextColumn)) {
581
0
    nextColumn = nextColumn->GetNext();
582
0
  }
583
0
584
0
  return nextColumn.forget();
585
0
}
586
587
already_AddRefed<nsTreeColumn>
588
nsCoreUtils::GetPreviousSensibleColumn(nsTreeColumn* aColumn)
589
0
{
590
0
  RefPtr<nsTreeColumn> prevColumn = aColumn->GetPrevious();
591
0
592
0
  while (prevColumn && IsColumnHidden(prevColumn)) {
593
0
    prevColumn = prevColumn->GetPrevious();
594
0
  }
595
0
596
0
  return prevColumn.forget();
597
0
}
598
599
bool
600
nsCoreUtils::IsColumnHidden(nsTreeColumn* aColumn)
601
0
{
602
0
  Element* element = aColumn->Element();
603
0
  return element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden,
604
0
                              nsGkAtoms::_true, eCaseMatters);
605
0
}
606
607
void
608
nsCoreUtils::ScrollTo(nsIPresShell* aPresShell, nsIContent* aContent,
609
                      uint32_t aScrollType)
610
0
{
611
0
  nsIPresShell::ScrollAxis vertical, horizontal;
612
0
  ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal);
613
0
  aPresShell->ScrollContentIntoView(aContent, vertical, horizontal,
614
0
                                    nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
615
0
}
616
617
bool
618
nsCoreUtils::IsWhitespaceString(const nsAString& aString)
619
0
{
620
0
  nsAString::const_char_iterator iterBegin, iterEnd;
621
0
622
0
  aString.BeginReading(iterBegin);
623
0
  aString.EndReading(iterEnd);
624
0
625
0
  while (iterBegin != iterEnd && IsWhitespace(*iterBegin))
626
0
    ++iterBegin;
627
0
628
0
  return iterBegin == iterEnd;
629
0
}
630
631
bool
632
nsCoreUtils::AccEventObserversExist()
633
0
{
634
0
  nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
635
0
  NS_ENSURE_TRUE(obsService, false);
636
0
637
0
  nsCOMPtr<nsISimpleEnumerator> observers;
638
0
  obsService->EnumerateObservers(NS_ACCESSIBLE_EVENT_TOPIC,
639
0
                                 getter_AddRefs(observers));
640
0
  NS_ENSURE_TRUE(observers, false);
641
0
642
0
  bool hasObservers = false;
643
0
  observers->HasMoreElements(&hasObservers);
644
0
645
0
  return hasObservers;
646
0
}
647
648
void
649
nsCoreUtils::DispatchAccEvent(RefPtr<nsIAccessibleEvent> event)
650
0
{
651
0
  nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
652
0
  NS_ENSURE_TRUE_VOID(obsService);
653
0
654
0
  obsService->NotifyObservers(event, NS_ACCESSIBLE_EVENT_TOPIC, nullptr);
655
0
}