layout/xul/nsLeafBoxFrame.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.

michael@0 1 /* -*- Mode: C++; tab-width: 8; 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 //
michael@0 7 // Eric Vaughan
michael@0 8 // Netscape Communications
michael@0 9 //
michael@0 10 // See documentation in associated header file
michael@0 11 //
michael@0 12
michael@0 13 #include "nsLeafBoxFrame.h"
michael@0 14 #include "nsBoxFrame.h"
michael@0 15 #include "nsCOMPtr.h"
michael@0 16 #include "nsGkAtoms.h"
michael@0 17 #include "nsPresContext.h"
michael@0 18 #include "nsStyleContext.h"
michael@0 19 #include "nsIContent.h"
michael@0 20 #include "nsNameSpaceManager.h"
michael@0 21 #include "nsBoxLayoutState.h"
michael@0 22 #include "nsWidgetsCID.h"
michael@0 23 #include "nsViewManager.h"
michael@0 24 #include "nsContainerFrame.h"
michael@0 25 #include "nsDisplayList.h"
michael@0 26 #include <algorithm>
michael@0 27
michael@0 28 //
michael@0 29 // NS_NewLeafBoxFrame
michael@0 30 //
michael@0 31 // Creates a new Toolbar frame and returns it
michael@0 32 //
michael@0 33 nsIFrame*
michael@0 34 NS_NewLeafBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
michael@0 35 {
michael@0 36 return new (aPresShell) nsLeafBoxFrame(aPresShell, aContext);
michael@0 37 }
michael@0 38
michael@0 39 NS_IMPL_FRAMEARENA_HELPERS(nsLeafBoxFrame)
michael@0 40
michael@0 41 nsLeafBoxFrame::nsLeafBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext)
michael@0 42 : nsLeafFrame(aContext)
michael@0 43 {
michael@0 44 }
michael@0 45
michael@0 46 #ifdef DEBUG_LAYOUT
michael@0 47 void
michael@0 48 nsLeafBoxFrame::GetBoxName(nsAutoString& aName)
michael@0 49 {
michael@0 50 GetFrameName(aName);
michael@0 51 }
michael@0 52 #endif
michael@0 53
michael@0 54
michael@0 55 /**
michael@0 56 * Initialize us. This is a good time to get the alignment of the box
michael@0 57 */
michael@0 58 void
michael@0 59 nsLeafBoxFrame::Init(
michael@0 60 nsIContent* aContent,
michael@0 61 nsIFrame* aParent,
michael@0 62 nsIFrame* aPrevInFlow)
michael@0 63 {
michael@0 64 nsLeafFrame::Init(aContent, aParent, aPrevInFlow);
michael@0 65
michael@0 66 if (GetStateBits() & NS_FRAME_FONT_INFLATION_CONTAINER) {
michael@0 67 AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
michael@0 68 }
michael@0 69
michael@0 70 UpdateMouseThrough();
michael@0 71 }
michael@0 72
michael@0 73 nsresult
michael@0 74 nsLeafBoxFrame::AttributeChanged(int32_t aNameSpaceID,
michael@0 75 nsIAtom* aAttribute,
michael@0 76 int32_t aModType)
michael@0 77 {
michael@0 78 nsresult rv = nsLeafFrame::AttributeChanged(aNameSpaceID, aAttribute,
michael@0 79 aModType);
michael@0 80
michael@0 81 if (aAttribute == nsGkAtoms::mousethrough)
michael@0 82 UpdateMouseThrough();
michael@0 83
michael@0 84 return rv;
michael@0 85 }
michael@0 86
michael@0 87 void nsLeafBoxFrame::UpdateMouseThrough()
michael@0 88 {
michael@0 89 if (mContent) {
michael@0 90 static nsIContent::AttrValuesArray strings[] =
michael@0 91 {&nsGkAtoms::never, &nsGkAtoms::always, nullptr};
michael@0 92 switch (mContent->FindAttrValueIn(kNameSpaceID_None,
michael@0 93 nsGkAtoms::mousethrough,
michael@0 94 strings, eCaseMatters)) {
michael@0 95 case 0: AddStateBits(NS_FRAME_MOUSE_THROUGH_NEVER); break;
michael@0 96 case 1: AddStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS); break;
michael@0 97 case 2: {
michael@0 98 RemoveStateBits(NS_FRAME_MOUSE_THROUGH_ALWAYS);
michael@0 99 RemoveStateBits(NS_FRAME_MOUSE_THROUGH_NEVER);
michael@0 100 break;
michael@0 101 }
michael@0 102 }
michael@0 103 }
michael@0 104 }
michael@0 105
michael@0 106 void
michael@0 107 nsLeafBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
michael@0 108 const nsRect& aDirtyRect,
michael@0 109 const nsDisplayListSet& aLists)
michael@0 110 {
michael@0 111 // REVIEW: GetFrameForPoint used to not report events for the background
michael@0 112 // layer, whereas this code will put an event receiver for this frame in the
michael@0 113 // BlockBorderBackground() list. But I don't see any need to preserve
michael@0 114 // that anomalous behaviour. The important thing I'm preserving is that
michael@0 115 // leaf boxes continue to receive events in the foreground layer.
michael@0 116 DisplayBorderBackgroundOutline(aBuilder, aLists);
michael@0 117
michael@0 118 if (!aBuilder->IsForEventDelivery() || !IsVisibleForPainting(aBuilder))
michael@0 119 return;
michael@0 120
michael@0 121 aLists.Content()->AppendNewToTop(new (aBuilder)
michael@0 122 nsDisplayEventReceiver(aBuilder, this));
michael@0 123 }
michael@0 124
michael@0 125 /* virtual */ nscoord
michael@0 126 nsLeafBoxFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
michael@0 127 {
michael@0 128 nscoord result;
michael@0 129 DISPLAY_MIN_WIDTH(this, result);
michael@0 130 nsBoxLayoutState state(PresContext(), aRenderingContext);
michael@0 131 nsSize minSize = GetMinSize(state);
michael@0 132
michael@0 133 // GetMinSize returns border-box width, and we want to return content
michael@0 134 // width. Since Reflow uses the reflow state's border and padding, we
michael@0 135 // actually just want to subtract what GetMinSize added, which is the
michael@0 136 // result of GetBorderAndPadding.
michael@0 137 nsMargin bp;
michael@0 138 GetBorderAndPadding(bp);
michael@0 139
michael@0 140 result = minSize.width - bp.LeftRight();
michael@0 141
michael@0 142 return result;
michael@0 143 }
michael@0 144
michael@0 145 /* virtual */ nscoord
michael@0 146 nsLeafBoxFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
michael@0 147 {
michael@0 148 nscoord result;
michael@0 149 DISPLAY_PREF_WIDTH(this, result);
michael@0 150 nsBoxLayoutState state(PresContext(), aRenderingContext);
michael@0 151 nsSize prefSize = GetPrefSize(state);
michael@0 152
michael@0 153 // GetPrefSize returns border-box width, and we want to return content
michael@0 154 // width. Since Reflow uses the reflow state's border and padding, we
michael@0 155 // actually just want to subtract what GetPrefSize added, which is the
michael@0 156 // result of GetBorderAndPadding.
michael@0 157 nsMargin bp;
michael@0 158 GetBorderAndPadding(bp);
michael@0 159
michael@0 160 result = prefSize.width - bp.LeftRight();
michael@0 161
michael@0 162 return result;
michael@0 163 }
michael@0 164
michael@0 165 nscoord
michael@0 166 nsLeafBoxFrame::GetIntrinsicWidth()
michael@0 167 {
michael@0 168 // No intrinsic width
michael@0 169 return 0;
michael@0 170 }
michael@0 171
michael@0 172 nsSize
michael@0 173 nsLeafBoxFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
michael@0 174 nsSize aCBSize, nscoord aAvailableWidth,
michael@0 175 nsSize aMargin, nsSize aBorder,
michael@0 176 nsSize aPadding, bool aShrinkWrap)
michael@0 177 {
michael@0 178 // Important: NOT calling our direct superclass here!
michael@0 179 return nsFrame::ComputeAutoSize(aRenderingContext, aCBSize, aAvailableWidth,
michael@0 180 aMargin, aBorder, aPadding, aShrinkWrap);
michael@0 181 }
michael@0 182
michael@0 183 nsresult
michael@0 184 nsLeafBoxFrame::Reflow(nsPresContext* aPresContext,
michael@0 185 nsHTMLReflowMetrics& aDesiredSize,
michael@0 186 const nsHTMLReflowState& aReflowState,
michael@0 187 nsReflowStatus& aStatus)
michael@0 188 {
michael@0 189 // This is mostly a copy of nsBoxFrame::Reflow().
michael@0 190 // We aren't able to share an implementation because of the frame
michael@0 191 // class hierarchy. If you make changes here, please keep
michael@0 192 // nsBoxFrame::Reflow in sync.
michael@0 193
michael@0 194 DO_GLOBAL_REFLOW_COUNT("nsLeafBoxFrame");
michael@0 195 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
michael@0 196
michael@0 197 NS_ASSERTION(aReflowState.ComputedWidth() >=0 &&
michael@0 198 aReflowState.ComputedHeight() >= 0, "Computed Size < 0");
michael@0 199
michael@0 200 #ifdef DO_NOISY_REFLOW
michael@0 201 printf("\n-------------Starting LeafBoxFrame Reflow ----------------------------\n");
michael@0 202 printf("%p ** nsLBF::Reflow %d R: ", this, myCounter++);
michael@0 203 switch (aReflowState.reason) {
michael@0 204 case eReflowReason_Initial:
michael@0 205 printf("Ini");break;
michael@0 206 case eReflowReason_Incremental:
michael@0 207 printf("Inc");break;
michael@0 208 case eReflowReason_Resize:
michael@0 209 printf("Rsz");break;
michael@0 210 case eReflowReason_StyleChange:
michael@0 211 printf("Sty");break;
michael@0 212 case eReflowReason_Dirty:
michael@0 213 printf("Drt ");
michael@0 214 break;
michael@0 215 default:printf("<unknown>%d", aReflowState.reason);break;
michael@0 216 }
michael@0 217
michael@0 218 printSize("AW", aReflowState.AvailableWidth());
michael@0 219 printSize("AH", aReflowState.AvailableHeight());
michael@0 220 printSize("CW", aReflowState.ComputedWidth());
michael@0 221 printSize("CH", aReflowState.ComputedHeight());
michael@0 222
michael@0 223 printf(" *\n");
michael@0 224
michael@0 225 #endif
michael@0 226
michael@0 227 aStatus = NS_FRAME_COMPLETE;
michael@0 228
michael@0 229 // create the layout state
michael@0 230 nsBoxLayoutState state(aPresContext, aReflowState.rendContext);
michael@0 231
michael@0 232 nsSize computedSize(aReflowState.ComputedWidth(),aReflowState.ComputedHeight());
michael@0 233
michael@0 234 nsMargin m;
michael@0 235 m = aReflowState.ComputedPhysicalBorderPadding();
michael@0 236
michael@0 237 //GetBorderAndPadding(m);
michael@0 238
michael@0 239 // this happens sometimes. So lets handle it gracefully.
michael@0 240 if (aReflowState.ComputedHeight() == 0) {
michael@0 241 nsSize minSize = GetMinSize(state);
michael@0 242 computedSize.height = minSize.height - m.top - m.bottom;
michael@0 243 }
michael@0 244
michael@0 245 nsSize prefSize(0,0);
michael@0 246
michael@0 247 // if we are told to layout intrinic then get our preferred size.
michael@0 248 if (computedSize.width == NS_INTRINSICSIZE || computedSize.height == NS_INTRINSICSIZE) {
michael@0 249 prefSize = GetPrefSize(state);
michael@0 250 nsSize minSize = GetMinSize(state);
michael@0 251 nsSize maxSize = GetMaxSize(state);
michael@0 252 prefSize = BoundsCheck(minSize, prefSize, maxSize);
michael@0 253 }
michael@0 254
michael@0 255 // get our desiredSize
michael@0 256 if (aReflowState.ComputedWidth() == NS_INTRINSICSIZE) {
michael@0 257 computedSize.width = prefSize.width;
michael@0 258 } else {
michael@0 259 computedSize.width += m.left + m.right;
michael@0 260 }
michael@0 261
michael@0 262 if (aReflowState.ComputedHeight() == NS_INTRINSICSIZE) {
michael@0 263 computedSize.height = prefSize.height;
michael@0 264 } else {
michael@0 265 computedSize.height += m.top + m.bottom;
michael@0 266 }
michael@0 267
michael@0 268 // handle reflow state min and max sizes
michael@0 269 // XXXbz the width handling here seems to be wrong, since
michael@0 270 // mComputedMin/MaxWidth is a content-box size, whole
michael@0 271 // computedSize.width is a border-box size...
michael@0 272 if (computedSize.width > aReflowState.ComputedMaxWidth())
michael@0 273 computedSize.width = aReflowState.ComputedMaxWidth();
michael@0 274
michael@0 275 if (computedSize.width < aReflowState.ComputedMinWidth())
michael@0 276 computedSize.width = aReflowState.ComputedMinWidth();
michael@0 277
michael@0 278 // Now adjust computedSize.height for our min and max computed
michael@0 279 // height. The only problem is that those are content-box sizes,
michael@0 280 // while computedSize.height is a border-box size. So subtract off
michael@0 281 // m.TopBottom() before adjusting, then readd it.
michael@0 282 computedSize.height = std::max(0, computedSize.height - m.TopBottom());
michael@0 283 computedSize.height = NS_CSS_MINMAX(computedSize.height,
michael@0 284 aReflowState.ComputedMinHeight(),
michael@0 285 aReflowState.ComputedMaxHeight());
michael@0 286 computedSize.height += m.TopBottom();
michael@0 287
michael@0 288 nsRect r(mRect.x, mRect.y, computedSize.width, computedSize.height);
michael@0 289
michael@0 290 SetBounds(state, r);
michael@0 291
michael@0 292 // layout our children
michael@0 293 Layout(state);
michael@0 294
michael@0 295 // ok our child could have gotten bigger. So lets get its bounds
michael@0 296 aDesiredSize.Width() = mRect.width;
michael@0 297 aDesiredSize.Height() = mRect.height;
michael@0 298 aDesiredSize.SetTopAscent(GetBoxAscent(state));
michael@0 299
michael@0 300 // the overflow rect is set in SetBounds() above
michael@0 301 aDesiredSize.mOverflowAreas = GetOverflowAreas();
michael@0 302
michael@0 303 #ifdef DO_NOISY_REFLOW
michael@0 304 {
michael@0 305 printf("%p ** nsLBF(done) W:%d H:%d ", this, aDesiredSize.Width(), aDesiredSize.Height());
michael@0 306
michael@0 307 if (maxElementWidth) {
michael@0 308 printf("MW:%d\n", *maxElementWidth);
michael@0 309 } else {
michael@0 310 printf("MW:?\n");
michael@0 311 }
michael@0 312
michael@0 313 }
michael@0 314 #endif
michael@0 315
michael@0 316 return NS_OK;
michael@0 317 }
michael@0 318
michael@0 319 #ifdef DEBUG_FRAME_DUMP
michael@0 320 nsresult
michael@0 321 nsLeafBoxFrame::GetFrameName(nsAString& aResult) const
michael@0 322 {
michael@0 323 return MakeFrameName(NS_LITERAL_STRING("LeafBox"), aResult);
michael@0 324 }
michael@0 325 #endif
michael@0 326
michael@0 327 nsIAtom*
michael@0 328 nsLeafBoxFrame::GetType() const
michael@0 329 {
michael@0 330 return nsGkAtoms::leafBoxFrame;
michael@0 331 }
michael@0 332
michael@0 333 nsresult
michael@0 334 nsLeafBoxFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo)
michael@0 335 {
michael@0 336 MarkIntrinsicWidthsDirty();
michael@0 337 return nsLeafFrame::CharacterDataChanged(aInfo);
michael@0 338 }
michael@0 339
michael@0 340 /* virtual */ nsSize
michael@0 341 nsLeafBoxFrame::GetPrefSize(nsBoxLayoutState& aState)
michael@0 342 {
michael@0 343 return nsBox::GetPrefSize(aState);
michael@0 344 }
michael@0 345
michael@0 346 /* virtual */ nsSize
michael@0 347 nsLeafBoxFrame::GetMinSize(nsBoxLayoutState& aState)
michael@0 348 {
michael@0 349 return nsBox::GetMinSize(aState);
michael@0 350 }
michael@0 351
michael@0 352 /* virtual */ nsSize
michael@0 353 nsLeafBoxFrame::GetMaxSize(nsBoxLayoutState& aState)
michael@0 354 {
michael@0 355 return nsBox::GetMaxSize(aState);
michael@0 356 }
michael@0 357
michael@0 358 /* virtual */ nscoord
michael@0 359 nsLeafBoxFrame::GetFlex(nsBoxLayoutState& aState)
michael@0 360 {
michael@0 361 return nsBox::GetFlex(aState);
michael@0 362 }
michael@0 363
michael@0 364 /* virtual */ nscoord
michael@0 365 nsLeafBoxFrame::GetBoxAscent(nsBoxLayoutState& aState)
michael@0 366 {
michael@0 367 return nsBox::GetBoxAscent(aState);
michael@0 368 }
michael@0 369
michael@0 370 /* virtual */ void
michael@0 371 nsLeafBoxFrame::MarkIntrinsicWidthsDirty()
michael@0 372 {
michael@0 373 // Don't call base class method, since everything it does is within an
michael@0 374 // IsBoxWrapped check.
michael@0 375 }
michael@0 376
michael@0 377 NS_IMETHODIMP
michael@0 378 nsLeafBoxFrame::DoLayout(nsBoxLayoutState& aState)
michael@0 379 {
michael@0 380 return nsBox::DoLayout(aState);
michael@0 381 }

mercurial