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