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