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.
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 "nsMathMLTokenFrame.h"
7 #include "nsPresContext.h"
8 #include "nsContentUtils.h"
9 #include "nsTextFrame.h"
10 #include "RestyleManager.h"
11 #include <algorithm>
13 nsIFrame*
14 NS_NewMathMLTokenFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
15 {
16 return new (aPresShell) nsMathMLTokenFrame(aContext);
17 }
19 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLTokenFrame)
21 nsMathMLTokenFrame::~nsMathMLTokenFrame()
22 {
23 }
25 NS_IMETHODIMP
26 nsMathMLTokenFrame::InheritAutomaticData(nsIFrame* aParent)
27 {
28 // let the base class get the default from our parent
29 nsMathMLContainerFrame::InheritAutomaticData(aParent);
31 return NS_OK;
32 }
34 eMathMLFrameType
35 nsMathMLTokenFrame::GetMathMLFrameType()
36 {
37 // treat everything other than <mi> as ordinary...
38 if (mContent->Tag() != nsGkAtoms::mi_) {
39 return eMathMLFrameType_Ordinary;
40 }
42 uint8_t mathVariant = StyleFont()->mMathVariant;
43 if ((mathVariant == NS_MATHML_MATHVARIANT_NONE &&
44 (StyleFont()->mFont.style == NS_STYLE_FONT_STYLE_ITALIC ||
45 HasAnyStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI))) ||
46 mathVariant == NS_MATHML_MATHVARIANT_ITALIC ||
47 mathVariant == NS_MATHML_MATHVARIANT_BOLD_ITALIC ||
48 mathVariant == NS_MATHML_MATHVARIANT_SANS_SERIF_ITALIC ||
49 mathVariant == NS_MATHML_MATHVARIANT_SANS_SERIF_BOLD_ITALIC) {
50 return eMathMLFrameType_ItalicIdentifier;
51 }
52 return eMathMLFrameType_UprightIdentifier;
53 }
55 void
56 nsMathMLTokenFrame::MarkTextFramesAsTokenMathML()
57 {
58 nsIFrame* child = nullptr;
59 uint32_t childCount = 0;
61 // Set flags on child text frames
62 // - to force them to trim their leading and trailing whitespaces.
63 // - Indicate which frames are suitable for mathvariant
64 // - flag single character <mi> frames for special italic treatment
65 for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame;
66 childFrame = childFrame->GetNextSibling()) {
67 for (nsIFrame* childFrame2 = childFrame->GetFirstPrincipalChild();
68 childFrame2; childFrame2 = childFrame2->GetNextSibling()) {
69 if (childFrame2->GetType() == nsGkAtoms::textFrame) {
70 childFrame2->AddStateBits(TEXT_IS_IN_TOKEN_MATHML);
71 child = childFrame2;
72 childCount++;
73 }
74 }
75 }
76 if (mContent->Tag() == nsGkAtoms::mi_ && childCount == 1) {
77 nsAutoString data;
78 if (!nsContentUtils::GetNodeTextContent(mContent, false, data)) {
79 NS_RUNTIMEABORT("OOM");
80 }
82 data.CompressWhitespace();
83 int32_t length = data.Length();
85 bool isSingleCharacter = length == 1 ||
86 (length == 2 && NS_IS_HIGH_SURROGATE(data[0]));
88 if (isSingleCharacter) {
89 child->AddStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI);
90 AddStateBits(NS_FRAME_IS_IN_SINGLE_CHAR_MI);
91 }
92 }
93 }
95 nsresult
96 nsMathMLTokenFrame::SetInitialChildList(ChildListID aListID,
97 nsFrameList& aChildList)
98 {
99 // First, let the base class do its work
100 nsresult rv = nsMathMLContainerFrame::SetInitialChildList(aListID, aChildList);
101 if (NS_FAILED(rv))
102 return rv;
104 MarkTextFramesAsTokenMathML();
106 return rv;
107 }
109 nsresult
110 nsMathMLTokenFrame::AppendFrames(ChildListID aListID,
111 nsFrameList& aChildList)
112 {
113 nsresult rv = nsMathMLContainerFrame::AppendFrames(aListID, aChildList);
114 if (NS_FAILED(rv))
115 return rv;
117 MarkTextFramesAsTokenMathML();
119 return rv;
120 }
122 nsresult
123 nsMathMLTokenFrame::InsertFrames(ChildListID aListID,
124 nsIFrame* aPrevFrame,
125 nsFrameList& aChildList)
126 {
127 nsresult rv = nsMathMLContainerFrame::InsertFrames(aListID, aPrevFrame,
128 aChildList);
129 if (NS_FAILED(rv))
130 return rv;
132 MarkTextFramesAsTokenMathML();
134 return rv;
135 }
137 nsresult
138 nsMathMLTokenFrame::Reflow(nsPresContext* aPresContext,
139 nsHTMLReflowMetrics& aDesiredSize,
140 const nsHTMLReflowState& aReflowState,
141 nsReflowStatus& aStatus)
142 {
143 nsresult rv = NS_OK;
145 // initializations needed for empty markup like <mtag></mtag>
146 aDesiredSize.Width() = aDesiredSize.Height() = 0;
147 aDesiredSize.SetTopAscent(0);
148 aDesiredSize.mBoundingMetrics = nsBoundingMetrics();
150 nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE);
151 nsIFrame* childFrame = GetFirstPrincipalChild();
152 while (childFrame) {
153 // ask our children to compute their bounding metrics
154 nsHTMLReflowMetrics childDesiredSize(aReflowState.GetWritingMode(),
155 aDesiredSize.mFlags
156 | NS_REFLOW_CALC_BOUNDING_METRICS);
157 nsHTMLReflowState childReflowState(aPresContext, aReflowState,
158 childFrame, availSize);
159 rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
160 childReflowState, aStatus);
161 //NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status");
162 if (NS_FAILED(rv)) {
163 // Call DidReflow() for the child frames we successfully did reflow.
164 DidReflowChildren(GetFirstPrincipalChild(), childFrame);
165 return rv;
166 }
168 SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize,
169 childDesiredSize.mBoundingMetrics);
171 childFrame = childFrame->GetNextSibling();
172 }
175 // place and size children
176 FinalizeReflow(*aReflowState.rendContext, aDesiredSize);
178 aStatus = NS_FRAME_COMPLETE;
179 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
180 return NS_OK;
181 }
183 // For token elements, mBoundingMetrics is computed at the ReflowToken
184 // pass, it is not computed here because our children may be text frames
185 // that do not implement the GetBoundingMetrics() interface.
186 /* virtual */ nsresult
187 nsMathMLTokenFrame::Place(nsRenderingContext& aRenderingContext,
188 bool aPlaceOrigin,
189 nsHTMLReflowMetrics& aDesiredSize)
190 {
191 mBoundingMetrics = nsBoundingMetrics();
192 for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame;
193 childFrame = childFrame->GetNextSibling()) {
194 nsHTMLReflowMetrics childSize(aDesiredSize.GetWritingMode());
195 GetReflowAndBoundingMetricsFor(childFrame, childSize,
196 childSize.mBoundingMetrics, nullptr);
197 // compute and cache the bounding metrics
198 mBoundingMetrics += childSize.mBoundingMetrics;
199 }
201 nsRefPtr<nsFontMetrics> fm;
202 nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
203 nscoord ascent = fm->MaxAscent();
204 nscoord descent = fm->MaxDescent();
206 aDesiredSize.mBoundingMetrics = mBoundingMetrics;
207 aDesiredSize.Width() = mBoundingMetrics.width;
208 aDesiredSize.SetTopAscent(std::max(mBoundingMetrics.ascent, ascent));
209 aDesiredSize.Height() = aDesiredSize.TopAscent() +
210 std::max(mBoundingMetrics.descent, descent);
212 if (aPlaceOrigin) {
213 nscoord dy, dx = 0;
214 for (nsIFrame* childFrame = GetFirstPrincipalChild(); childFrame;
215 childFrame = childFrame->GetNextSibling()) {
216 nsHTMLReflowMetrics childSize(aDesiredSize.GetWritingMode());
217 GetReflowAndBoundingMetricsFor(childFrame, childSize,
218 childSize.mBoundingMetrics);
220 // place and size the child; (dx,0) makes the caret happy - bug 188146
221 dy = childSize.Height() == 0 ? 0 : aDesiredSize.TopAscent() - childSize.TopAscent();
222 FinishReflowChild(childFrame, PresContext(), childSize, nullptr, dx, dy, 0);
223 dx += childSize.Width();
224 }
225 }
227 SetReference(nsPoint(0, aDesiredSize.TopAscent()));
229 return NS_OK;
230 }