Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d5b1cc5d8 | ||
|
|
0e521f6302 | ||
|
|
9cacfcff57 | ||
|
|
21ad7adc90 | ||
|
|
9a29430751 | ||
|
|
481d4868b0 | ||
|
|
d148c11717 | ||
|
|
bc322e58f8 | ||
|
|
e48a6f26a5 | ||
|
|
d85edd01df | ||
|
|
296379d751 | ||
|
|
7ba9fc2801 | ||
|
|
a9ac8b390f | ||
|
|
71c0f8246c | ||
|
|
6cda35442f | ||
|
|
1dba423327 | ||
|
|
e2af0b28bf | ||
|
|
5ea9b7b80a | ||
|
|
b799e100ad | ||
|
|
1c500a6abb | ||
|
|
b909fccc92 | ||
|
|
abddee43b4 | ||
|
|
49d184e550 | ||
|
|
3e223cbfb4 | ||
|
|
dd9099a7d3 | ||
|
|
31558a1521 | ||
|
|
0e683bf699 | ||
|
|
6459dec5bb | ||
|
|
0e930fba3f | ||
|
|
3b683bbe59 | ||
|
|
0042e54c38 | ||
|
|
e75201f7d1 | ||
|
|
28c47723b2 | ||
|
|
3d872ff7b0 | ||
|
|
beb684c29e | ||
|
|
775588b75d | ||
|
|
8a2a5d837c | ||
|
|
8add755c81 | ||
|
|
257c64567e | ||
|
|
d0b61d4a68 | ||
|
|
3b5f50cc35 | ||
|
|
27c6a7f477 | ||
|
|
c65f84214e | ||
|
|
a317c65fd7 | ||
|
|
0ec35ce534 | ||
|
|
bf0c040722 | ||
|
|
ebadd51401 | ||
|
|
5ed0bf8b44 | ||
|
|
f877c1dba5 | ||
|
|
4c14f8f89b | ||
|
|
c119728965 | ||
|
|
fa55b9c2e8 | ||
|
|
16aba76fc5 | ||
|
|
995def99cd | ||
|
|
923e52789c | ||
|
|
22d945430b |
No files matched your search
@@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for Idle GC backout
|
||||
Clobber for removal of network tickler
|
||||
@@ -3,6 +3,6 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
JS_PREFERENCE_PP_FILES += [
|
||||
JS_PREFERENCE_FILES += [
|
||||
'devtools.js',
|
||||
]
|
||||
@@ -97,7 +97,7 @@ ToJSValue(JSContext* aCx,
|
||||
return true;
|
||||
}
|
||||
|
||||
// accept floating point types
|
||||
// Accept floating point types
|
||||
inline bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
float aArgument,
|
||||
@@ -106,7 +106,7 @@ ToJSValue(JSContext* aCx,
|
||||
// Make sure we're called in a compartment
|
||||
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx));
|
||||
|
||||
aValue.setNumber(aArgument);
|
||||
aValue.set(JS_NumberValue(double(aArgument)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -876,20 +876,12 @@ HTMLImageElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
return HTMLImageElementBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsIDOMHTMLFormElement*
|
||||
HTMLImageElement::GetForm() const
|
||||
{
|
||||
return mForm;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
HTMLImageElement::SetForm(nsIDOMHTMLFormElement* aForm)
|
||||
{
|
||||
NS_PRECONDITION(aForm, "Don't pass null here");
|
||||
NS_ASSERTION(!mForm,
|
||||
"We don't support switching from one non-null form to another.");
|
||||
MOZ_ASSERT(!mForm && !HasFlag(ADDED_TO_FORM),
|
||||
"We don't support switching from one non-null form to another.");
|
||||
|
||||
mForm = static_cast<HTMLFormElement*>(aForm);
|
||||
}
|
||||
|
||||
@@ -216,9 +216,8 @@ public:
|
||||
SetHTMLAttr(nsGkAtoms::lowsrc, aLowsrc, aError);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsIDOMHTMLFormElement* GetForm() const;
|
||||
#endif
|
||||
HTMLFormElement* GetForm() const { return mForm; };
|
||||
|
||||
void SetForm(nsIDOMHTMLFormElement* aForm);
|
||||
void ClearForm(bool aRemoveFromForm);
|
||||
|
||||
|
||||
@@ -1487,8 +1487,15 @@ nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttr
|
||||
}
|
||||
|
||||
if (w && h && *w != 0 && *h != 0) {
|
||||
nsCSSValue* aspect_ratio = aData->ValueForAspectRatio();
|
||||
aspect_ratio->SetFloatValue((float(*w) / float(*h)), eCSSUnit_Number);
|
||||
nsCSSValue width;
|
||||
width.SetFloatValue(float(*w), eCSSUnit_Number);
|
||||
nsCSSValue height;
|
||||
height.SetFloatValue(float(*h), eCSSUnit_Number);
|
||||
nsCSSValue ratio;
|
||||
ratio.SetPairValue(width, height);
|
||||
nsCSSValue autoValue;
|
||||
autoValue.SetAutoValue();
|
||||
aData->ValueForAspectRatio()->SetPairValue(autoValue, ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1824,8 +1831,8 @@ void
|
||||
nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm)
|
||||
{
|
||||
NS_PRECONDITION(aForm, "Don't pass null here");
|
||||
NS_ASSERTION(!mForm,
|
||||
"We don't support switching from one non-null form to another.");
|
||||
MOZ_ASSERT(!mForm && !HasFlag(ADDED_TO_FORM),
|
||||
"We don't support switching from one non-null form to another.");
|
||||
|
||||
// keep a *weak* ref to the form here
|
||||
mForm = static_cast<HTMLFormElement*>(aForm);
|
||||
|
||||
@@ -2455,7 +2455,7 @@ ContentChild::RecvUpdateWindow(const uintptr_t& aChildId)
|
||||
if (parentInstance) {
|
||||
// sync! update call to the plugin instance that forces the
|
||||
// plugin to paint its child window.
|
||||
parentInstance->CallUpdateWindow();
|
||||
Unused << parentInstance->CallUpdateWindow();
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
|
||||
@@ -367,12 +367,13 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static const uint32_t MIN_RATE = 8000;
|
||||
static const uint32_t MAX_RATE = 640000;
|
||||
|
||||
bool IsValid() const override
|
||||
{
|
||||
return mChannels > 0 && mChannels <= MAX_AUDIO_CHANNELS
|
||||
&& mRate > 0 && mRate <= MAX_RATE;
|
||||
&& mRate >= MIN_RATE && mRate <= MAX_RATE;
|
||||
}
|
||||
|
||||
AudioInfo* GetAsAudioInfo() override
|
||||
|
||||
@@ -179,12 +179,18 @@ IsValidVideoRegion(const nsIntSize& aFrame, const nsIntRect& aPicture,
|
||||
aFrame.height <= PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aFrame.width * aFrame.height <= MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
|
||||
aFrame.width * aFrame.height != 0 &&
|
||||
aPicture.width > 0 &&
|
||||
aPicture.width <= PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aPicture.x >= 0 &&
|
||||
aPicture.x < PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aPicture.x + aPicture.width < PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aPicture.XMost() <= aFrame.width &&
|
||||
aPicture.height > 0 &&
|
||||
aPicture.height <= PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aPicture.y >= 0 &&
|
||||
aPicture.y < PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aPicture.y + aPicture.height < PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
aPicture.YMost() <= aFrame.height &&
|
||||
aPicture.width * aPicture.height <= MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
|
||||
aPicture.width * aPicture.height != 0 &&
|
||||
aDisplay.width <= PlanarYCbCrImage::MAX_DIMENSION &&
|
||||
|
||||
@@ -439,7 +439,7 @@ private:
|
||||
Maybe<size_t> mInitOffset;
|
||||
Maybe<size_t> mMediaOffset;
|
||||
bool mValid = true;
|
||||
char mLastInvalidBox[5];
|
||||
char mLastInvalidBox[5]{};
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "WebMBufferedParser.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
@@ -352,19 +353,27 @@ WebMDemuxer::ReadMetadata()
|
||||
mInfo.mVideo.mExtraData = new MediaByteBuffer(length);
|
||||
mInfo.mVideo.mExtraData->AppendElements(data, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
NS_WARNING("Unknown WebM video codec");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Picture region, taking into account cropping, before scaling
|
||||
// to the display size.
|
||||
unsigned int cropH = params.crop_right + params.crop_left;
|
||||
unsigned int cropV = params.crop_bottom + params.crop_top;
|
||||
CheckedInt<uint32_t> cropH = CheckedInt<uint32_t>(params.crop_left) + params.crop_right;
|
||||
CheckedInt<uint32_t> cropV = CheckedInt<uint32_t>(params.crop_top) + params.crop_bottom;
|
||||
if (!cropH.isValid() || !cropV.isValid() ||
|
||||
cropH.value() >= params.width || cropV.value() >= params.height) {
|
||||
WEBM_DEBUG("Invalid crop values left: {} right: {} top: {} bottom: {}",
|
||||
params.crop_left, params.crop_right, params.crop_top,
|
||||
params.crop_bottom);
|
||||
// Ignore invalid crop parameters.
|
||||
continue;
|
||||
}
|
||||
nsIntRect pictureRect(params.crop_left,
|
||||
params.crop_top,
|
||||
params.width - cropH,
|
||||
params.height - cropV);
|
||||
params.width - cropH.value(),
|
||||
params.height - cropV.value());
|
||||
|
||||
// If the cropping data appears invalid then use the frame data
|
||||
if (pictureRect.width <= 0 ||
|
||||
|
||||
@@ -25,6 +25,8 @@ interface CSSStyleSheet : StyleSheet {
|
||||
unsigned long insertRule(DOMString rule, optional unsigned long index = 0);
|
||||
[Throws, NeedsSubjectPrincipal]
|
||||
void deleteRule(unsigned long index);
|
||||
[Throws]
|
||||
void replaceSync(DOMString text);
|
||||
|
||||
// Non-standard WebKit things, see https://github.com/w3c/csswg-drafts/pull/3900.
|
||||
[Throws, NeedsSubjectPrincipal, BinaryName="cssRules"]
|
||||
|
||||
@@ -336,7 +336,20 @@ gfxGraphiteShaper::SetGlyphsFromSegment(DrawTarget *aDrawTarget,
|
||||
// not a one-to-one mapping with simple metrics: use DetailedGlyph
|
||||
AutoTArray<gfxShapedText::DetailedGlyph,8> details;
|
||||
float clusterLoc;
|
||||
for (uint32_t j = c.baseGlyph; j < c.baseGlyph + c.nGlyphs; ++j) {
|
||||
|
||||
uint32_t glyph_start = c.baseGlyph;
|
||||
uint32_t glyph_end = glyph_start + c.nGlyphs;
|
||||
if (glyph_end < glyph_start) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
if (glyph_end - glyph_start > 0xFFFF) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
if (!details.SetCapacity(glyph_end - glyph_start, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for (uint32_t j = glyph_start; j < glyph_end; ++j) {
|
||||
gfxShapedText::DetailedGlyph* d = details.AppendElement();
|
||||
d->mGlyphID = gids[j];
|
||||
d->mYOffset = roundY ? NSToIntRound(-yLocs[j]) * dev2appUnits :
|
||||
|
||||
@@ -231,11 +231,13 @@ gfxTextRun::ComputeLigatureData(Range aPartRange,
|
||||
LigatureData result;
|
||||
const CompressedGlyph *charGlyphs = mCharacterGlyphs;
|
||||
|
||||
uint32_t i;
|
||||
for (i = aPartRange.start; !charGlyphs[i].IsLigatureGroupStart(); --i) {
|
||||
NS_ASSERTION(i > 0, "Ligature at the start of the run??");
|
||||
uint32_t i = aPartRange.start;
|
||||
while (i && !charGlyphs[i].IsLigatureGroupStart()) {
|
||||
--i;
|
||||
}
|
||||
NS_ASSERTION(charGlyphs[i].IsLigatureGroupStart(), "Ligature at run start?");
|
||||
result.mRange.start = i;
|
||||
|
||||
for (i = aPartRange.start + 1;
|
||||
i < GetLength() && !charGlyphs[i].IsLigatureGroupStart(); ++i) {
|
||||
}
|
||||
@@ -1704,21 +1706,27 @@ gfxFontGroup::GetFontAt(int32_t i, uint32_t aCh)
|
||||
|
||||
RefPtr<gfxFont> font = ff.Font();
|
||||
if (!font) {
|
||||
gfxFontEntry* fe = mFonts[i].FontEntry();
|
||||
gfxCharacterMap* unicodeRangeMap = nullptr;
|
||||
RefPtr<gfxFontEntry> fe = ff.FontEntry();
|
||||
if (!fe) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<gfxCharacterMap> unicodeRangeMap;
|
||||
if (fe->mIsUserFontContainer) {
|
||||
gfxUserFontEntry* ufe = static_cast<gfxUserFontEntry*>(fe);
|
||||
// This raw pointer is OK because fe holds a strong ref to the object.
|
||||
gfxUserFontEntry* ufe = static_cast<gfxUserFontEntry*>(fe.get());
|
||||
if (ufe->LoadState() == gfxUserFontEntry::STATUS_NOT_LOADED &&
|
||||
ufe->CharacterInUnicodeRange(aCh) &&
|
||||
!FontLoadingForFamily(ff.Family(), aCh)) {
|
||||
ufe->Load();
|
||||
ff.CheckState(mSkipDrawing);
|
||||
}
|
||||
unicodeRangeMap = ufe->GetUnicodeRangeMap();
|
||||
// Update fe to refer to the actual platform font entry, rather than the
|
||||
// webfont wrapper. After this, we no longer have a strong ref to ufe.
|
||||
fe = ufe->GetPlatformFontEntry();
|
||||
if (!fe) {
|
||||
return nullptr;
|
||||
}
|
||||
unicodeRangeMap = ufe->GetUnicodeRangeMap();
|
||||
}
|
||||
font = fe->FindOrMakeFont(&mStyle, mFonts[i].NeedsBold(),
|
||||
unicodeRangeMap);
|
||||
|
||||
@@ -1637,10 +1637,13 @@ RasterImage::NotifyDecodeComplete(const DecoderFinalStatus& aStatus,
|
||||
|
||||
if (!(aDecoderFlags & DecoderFlags::FIRST_FRAME_ONLY) &&
|
||||
mHasBeenDecoded && mAnimationState) {
|
||||
// We've finished a full decode of all animation frames and our AnimationState
|
||||
// has been notified about them all, so let it know not to expect anymore.
|
||||
mAnimationState->NotifyDecodeComplete();
|
||||
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
|
||||
// If we've successfully finished a full decode of all animation frames
|
||||
// then let our animation state know it's complete and to not to expect
|
||||
// any more frames.
|
||||
if (aStatus.mFinished && !aStatus.mHadError) {
|
||||
mAnimationState->NotifyDecodeComplete();
|
||||
mAnimationState->UpdateState(mAnimationFinished, this, mSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Only act on errors if we have no usable frames from the decoder.
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "irregexp/RegExpParser.h"
|
||||
#include "jit/InlinableNatives.h"
|
||||
#include "vm/RegExpStatics.h"
|
||||
@@ -1754,7 +1757,9 @@ js::RegExpGetSubstitution(JSContext* cx, HandleArrayObject matchResult, HandleLi
|
||||
// Step 6.
|
||||
MOZ_ASSERT(position <= string->length());
|
||||
|
||||
uint32_t nCaptures = matchResultLength - 1;
|
||||
// String substitutions can only reference $1 through $99.
|
||||
uint32_t nCaptures = std::min<uint32_t>(matchResultLength - 1,
|
||||
REGEXP_MAX_SUBSTITUTION_CAPTURES);
|
||||
Rooted<CapturesVector> captures(cx, CapturesVector(cx));
|
||||
if (!captures.reserve(nCaptures))
|
||||
return false;
|
||||
|
||||
@@ -463,6 +463,12 @@ function RegExpGetComplexReplacement(result, matched, S, position,
|
||||
// Step 14.k.i (reordered).
|
||||
_DefineDataProperty(captures, capturesLength++, matched);
|
||||
|
||||
// String substitutions can only reference $1 through $99. Keep getting and
|
||||
// stringifying all captures because those operations are observable.
|
||||
var storedCaptures = functionalReplace ?
|
||||
nCaptures :
|
||||
std_Math_min(nCaptures, REGEXP_MAX_SUBSTITUTION_CAPTURES);
|
||||
|
||||
// Step 14.g, 14.i, 14.i.iv.
|
||||
for (var n = 1; n <= nCaptures; n++) {
|
||||
// Step 14.i.i.
|
||||
@@ -473,7 +479,9 @@ function RegExpGetComplexReplacement(result, matched, S, position,
|
||||
capN = ToString(capN);
|
||||
|
||||
// Step 14.i.iii.
|
||||
_DefineDataProperty(captures, capturesLength++, capN);
|
||||
if (n <= storedCaptures) {
|
||||
_DefineDataProperty(captures, capturesLength++, capN);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 14.j.
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
|
||||
#define REGEXP_FLAGS_SLOT 2
|
||||
|
||||
#define REGEXP_MAX_SUBSTITUTION_CAPTURES 99
|
||||
|
||||
#define REGEXP_IGNORECASE_FLAG 0x01
|
||||
#define REGEXP_GLOBAL_FLAG 0x02
|
||||
#define REGEXP_MULTILINE_FLAG 0x04
|
||||
|
||||
@@ -494,6 +494,9 @@ OnLeaveBaselineFrame(JSContext* cx, const JitFrameIterator& frame, jsbytecode* p
|
||||
{
|
||||
BaselineFrame* baselineFrame = frame.baselineFrame();
|
||||
if (jit::DebugEpilogue(cx, baselineFrame, pc, frameOk)) {
|
||||
if (!baselineFrame->hasReturnValue()) {
|
||||
baselineFrame->setReturnValue(UndefinedValue());
|
||||
}
|
||||
rfe->kind = ResumeFromException::RESUME_FORCED_RETURN;
|
||||
rfe->framePointer = frame.fp() - BaselineFrame::FramePointerOffset;
|
||||
rfe->stackPointer = reinterpret_cast<uint8_t*>(baselineFrame);
|
||||
|
||||
+5
-4
@@ -312,12 +312,13 @@ cvt_s(SprintfState* ss, const char* s, int width, int prec, int flags)
|
||||
s = generic_null_str(s);
|
||||
|
||||
// Limit string length by precision value
|
||||
int slen = int(generic_strlen(s));
|
||||
if (0 < prec && prec < slen)
|
||||
slen = prec;
|
||||
size_t slen = strnlen(s, size_t(prec));
|
||||
if (slen > INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// and away we go
|
||||
return fill2(ss, s, slen, width, flags);
|
||||
return fill2(ss, s, int(slen), width, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -411,6 +411,13 @@ DottedCornerFinder::FindBestOverlap(Float aMinR, Float aMinBorderRadius,
|
||||
mCount = mMaxCount;
|
||||
break;
|
||||
}
|
||||
// GetCountAndLastOverlap() failed without writing |count| and
|
||||
// |actualOverlap|: the walk needed more than mMaxCount circles, i.e.
|
||||
// this overlap produces too many circles. Narrow the search toward
|
||||
// smaller overlaps.
|
||||
upper = overlap;
|
||||
overlap = (upper + lower) / 2.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (j == 0) {
|
||||
|
||||
@@ -5107,19 +5107,28 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
|
||||
styleMinBSize.GetCoordValue() == 0)) ||
|
||||
styleMaxBSize.GetUnit() != eStyleUnit_None) {
|
||||
|
||||
AspectRatio ratio = aFrame->GetIntrinsicRatio();
|
||||
AspectRatio ratio = aFrame->GetAspectRatio();
|
||||
if (ratio) {
|
||||
// Convert 'ratio' if necessary, so that it's storing ISize/BSize:
|
||||
if (!horizontalAxis) {
|
||||
ratio = ratio.Inverted();
|
||||
}
|
||||
AddStateBitToAncestors(aFrame,
|
||||
NS_FRAME_DESCENDANT_INTRINSIC_ISIZE_DEPENDS_ON_BSIZE);
|
||||
|
||||
const WritingMode wm = aFrame->GetWritingMode();
|
||||
LogicalSize boxSizingAdjust(wm);
|
||||
boxSizingAdjust.ISize(wm) =
|
||||
GetDefiniteSizeTakenByBoxSizing(boxSizing, aFrame, isInlineAxis,
|
||||
aFlags & IGNORE_PADDING,
|
||||
aPercentageBasis);
|
||||
nscoord bSizeTakenByBoxSizing =
|
||||
GetDefiniteSizeTakenByBoxSizing(boxSizing, aFrame, !isInlineAxis,
|
||||
aFlags & IGNORE_PADDING,
|
||||
aPercentageBasis);
|
||||
boxSizingAdjust.BSize(wm) = bSizeTakenByBoxSizing;
|
||||
auto iSizeFromBSize = [&](nscoord aBSize) {
|
||||
LogicalAxis dependentAxis =
|
||||
isInlineAxis ? eLogicalAxisInline : eLogicalAxisBlock;
|
||||
return ratio.ComputeRatioDependentSize(
|
||||
dependentAxis, wm, aBSize, boxSizingAdjust);
|
||||
};
|
||||
// NOTE: This is only the minContentSize if we've been passed MIN_INTRINSIC_ISIZE
|
||||
// (which is fine, because this should only be used inside a check for that flag).
|
||||
nscoord minContentSize = result;
|
||||
@@ -5128,14 +5137,14 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
|
||||
(aPercentageBasis.isNothing() &&
|
||||
GetPercentBSize(styleBSize, aFrame, horizontalAxis, h))) {
|
||||
h = std::max(0, h - bSizeTakenByBoxSizing);
|
||||
result = ratio.ApplyTo(h);
|
||||
result = iSizeFromBSize(h);
|
||||
}
|
||||
|
||||
if (GetDefiniteSize(styleMaxBSize, aFrame, !isInlineAxis, aPercentageBasis, &h) ||
|
||||
(aPercentageBasis.isNothing() &&
|
||||
GetPercentBSize(styleMaxBSize, aFrame, horizontalAxis, h))) {
|
||||
h = std::max(0, h - bSizeTakenByBoxSizing);
|
||||
nscoord maxISize = ratio.ApplyTo(h);
|
||||
nscoord maxISize = iSizeFromBSize(h);
|
||||
if (maxISize < result) {
|
||||
result = maxISize;
|
||||
}
|
||||
@@ -5148,7 +5157,7 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
|
||||
(aPercentageBasis.isNothing() &&
|
||||
GetPercentBSize(styleMinBSize, aFrame, horizontalAxis, h))) {
|
||||
h = std::max(0, h - bSizeTakenByBoxSizing);
|
||||
nscoord minISize = ratio.ApplyTo(h);
|
||||
nscoord minISize = iSizeFromBSize(h);
|
||||
if (minISize > result) {
|
||||
result = minISize;
|
||||
}
|
||||
|
||||
@@ -234,7 +234,18 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
|
||||
{
|
||||
WritingMode wm = GetWritingMode();
|
||||
LogicalSize availSize = aButtonReflowInput.ComputedSize(wm);
|
||||
availSize.BSize(wm) = NS_INTRINSICSIZE;
|
||||
|
||||
// Identify if the inner anonymous block is actually functioning as a flex or grid container.
|
||||
nsIAtom* kidType = aFirstKid->GetType();
|
||||
bool isFlexOrGrid = (kidType == nsGkAtoms::flexContainerFrame ||
|
||||
kidType == nsGkAtoms::gridContainerFrame);
|
||||
|
||||
// Preserve the button's definite BSize ONLY for flex/grid children so they
|
||||
// see a definite containing block main size. For standard buttons, clobber
|
||||
// to intrinsic so standard vertical centering (extraSpace) calculations work.
|
||||
if (!isFlexOrGrid || aButtonReflowInput.ComputedBSize() == NS_INTRINSICSIZE) {
|
||||
availSize.BSize(wm) = NS_INTRINSICSIZE;
|
||||
}
|
||||
|
||||
// shorthand for a value we need to use in a bunch of places
|
||||
const LogicalMargin& clbp = aButtonReflowInput.ComputedLogicalBorderPadding();
|
||||
@@ -248,6 +259,12 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
|
||||
aFirstKid,
|
||||
availSize);
|
||||
|
||||
// Apply the definite BSize directly on the inner reflow input ONLY if it's
|
||||
// a flex or grid container, allowing it to be used as-is.
|
||||
if (isFlexOrGrid && aButtonReflowInput.ComputedBSize() != NS_INTRINSICSIZE) {
|
||||
contentsReflowInput.SetComputedBSize(aButtonReflowInput.ComputedBSize());
|
||||
}
|
||||
|
||||
nsReflowStatus contentsReflowStatus;
|
||||
ReflowOutput contentsDesiredSize(aButtonReflowInput);
|
||||
childPos.B(wm) = 0; // This will be set properly later, after reflowing the
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/AspectRatio.h"
|
||||
|
||||
#include "mozilla/WritingModes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
nscoord
|
||||
AspectRatio::ComputeRatioDependentSize(
|
||||
LogicalAxis aRatioDependentAxis,
|
||||
const WritingMode& aWM,
|
||||
nscoord aRatioDeterminingSize,
|
||||
const LogicalSize& aContentBoxToBoxSizingAdjust) const
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(*this);
|
||||
|
||||
LogicalSize adjust(aWM);
|
||||
if (mUseBoxSizing == UseBoxSizing::Yes) {
|
||||
adjust = aContentBoxToBoxSizingAdjust;
|
||||
}
|
||||
|
||||
AspectRatio logicalRatio = aWM.IsVertical() ? Inverted() : *this;
|
||||
nscoord result;
|
||||
if (aRatioDependentAxis == eLogicalAxisInline) {
|
||||
result = logicalRatio.ApplyTo(aRatioDeterminingSize +
|
||||
adjust.BSize(aWM)) -
|
||||
adjust.ISize(aWM);
|
||||
} else {
|
||||
result = logicalRatio.Inverted().ApplyTo(aRatioDeterminingSize +
|
||||
adjust.ISize(aWM)) -
|
||||
adjust.BSize(aWM);
|
||||
}
|
||||
return std::max(nscoord(0), result);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
@@ -9,21 +9,46 @@
|
||||
/* The aspect ratio of a box, in a "width / height" format. */
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/LogicalTypes.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsSize.h"
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct AspectRatio {
|
||||
AspectRatio() : mRatio(0.0f) {}
|
||||
explicit AspectRatio(float aRatio) : mRatio(std::max(aRatio, 0.0f)) {}
|
||||
class LogicalSize;
|
||||
class WritingMode;
|
||||
|
||||
static AspectRatio FromSize(float aWidth, float aHeight) {
|
||||
enum class UseBoxSizing : uint8_t {
|
||||
// Natural ratios and "auto <ratio>" always use content-box dimensions.
|
||||
No,
|
||||
// A specified <ratio> uses the dimensions selected by box-sizing.
|
||||
Yes,
|
||||
};
|
||||
|
||||
struct AspectRatio {
|
||||
AspectRatio()
|
||||
: mRatio(0.0f)
|
||||
, mUseBoxSizing(UseBoxSizing::No)
|
||||
{}
|
||||
|
||||
explicit AspectRatio(float aRatio,
|
||||
UseBoxSizing aUseBoxSizing = UseBoxSizing::No)
|
||||
: mRatio(std::max(aRatio, 0.0f))
|
||||
, mUseBoxSizing(aUseBoxSizing)
|
||||
{}
|
||||
|
||||
static AspectRatio FromSize(float aWidth, float aHeight,
|
||||
UseBoxSizing aUseBoxSizing = UseBoxSizing::No) {
|
||||
if (aWidth == 0.0f || aHeight == 0.0f) {
|
||||
return AspectRatio();
|
||||
}
|
||||
return AspectRatio(aWidth / aHeight);
|
||||
float ratio = aWidth / aHeight;
|
||||
if (!std::isfinite(ratio)) {
|
||||
return AspectRatio();
|
||||
}
|
||||
return AspectRatio(ratio, aUseBoxSizing);
|
||||
}
|
||||
|
||||
static AspectRatio FromSize(nsSize aSize) {
|
||||
@@ -55,11 +80,23 @@ struct AspectRatio {
|
||||
// 0.0f in the division here (so that valid ratios always generate other
|
||||
// valid ratios when inverted).
|
||||
return AspectRatio(
|
||||
std::max(std::numeric_limits<float>::epsilon(), 1.0f / mRatio));
|
||||
std::max(std::numeric_limits<float>::epsilon(), 1.0f / mRatio),
|
||||
mUseBoxSizing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a content-box size in the ratio-dependent axis from a
|
||||
* content-box size in the ratio-determining axis.
|
||||
*/
|
||||
nscoord ComputeRatioDependentSize(
|
||||
LogicalAxis aRatioDependentAxis,
|
||||
const WritingMode& aWM,
|
||||
nscoord aRatioDeterminingSize,
|
||||
const LogicalSize& aContentBoxToBoxSizingAdjust) const;
|
||||
|
||||
bool operator==(const AspectRatio& aOther) const {
|
||||
return mRatio == aOther.mRatio;
|
||||
return mRatio == aOther.mRatio &&
|
||||
mUseBoxSizing == aOther.mUseBoxSizing;
|
||||
}
|
||||
|
||||
bool operator!=(const AspectRatio& aOther) const {
|
||||
@@ -73,6 +110,7 @@ struct AspectRatio {
|
||||
private:
|
||||
// 0.0f represents no aspect ratio.
|
||||
float mRatio;
|
||||
UseBoxSizing mUseBoxSizing;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_LogicalTypes_h
|
||||
#define mozilla_LogicalTypes_h
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Logical axis, edge, side and corner constants for use in various places.
|
||||
enum LogicalAxis {
|
||||
eLogicalAxisBlock = 0x0,
|
||||
eLogicalAxisInline = 0x1
|
||||
};
|
||||
enum LogicalEdge {
|
||||
eLogicalEdgeStart = 0x0,
|
||||
eLogicalEdgeEnd = 0x1
|
||||
};
|
||||
enum LogicalSide {
|
||||
eLogicalSideBStart = (eLogicalAxisBlock << 1) | eLogicalEdgeStart, // 0x0
|
||||
eLogicalSideBEnd = (eLogicalAxisBlock << 1) | eLogicalEdgeEnd, // 0x1
|
||||
eLogicalSideIStart = (eLogicalAxisInline << 1) | eLogicalEdgeStart, // 0x2
|
||||
eLogicalSideIEnd = (eLogicalAxisInline << 1) | eLogicalEdgeEnd // 0x3
|
||||
};
|
||||
|
||||
enum LogicalCorner
|
||||
{
|
||||
eLogicalCornerBStartIStart = 0,
|
||||
eLogicalCornerBStartIEnd = 1,
|
||||
eLogicalCornerBEndIEnd = 2,
|
||||
eLogicalCornerBEndIStart = 3
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_LogicalTypes_h
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef WritingModes_h_
|
||||
#define WritingModes_h_
|
||||
|
||||
#include "mozilla/LogicalTypes.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsBidiUtils.h"
|
||||
|
||||
@@ -110,6 +110,7 @@ EXPORTS += [
|
||||
EXPORTS.mozilla += [
|
||||
'AspectRatio.h',
|
||||
'CSSAlignUtils.h',
|
||||
'LogicalTypes.h',
|
||||
'ReflowInput.h',
|
||||
'ReflowOutput.h',
|
||||
'WritingModes.h',
|
||||
@@ -124,6 +125,7 @@ EXPORTS.mozilla.layout += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AspectRatio.cpp',
|
||||
'AsyncScrollBase.cpp',
|
||||
'BlockReflowInput.cpp',
|
||||
'CSSAlignUtils.cpp',
|
||||
|
||||
@@ -1945,7 +1945,7 @@ FlexItem::FlexItem(ReflowInput& aFlexItemReflowInput,
|
||||
: mFrame(aFlexItemReflowInput.mFrame),
|
||||
mFlexGrow(aFlexGrow),
|
||||
mFlexShrink(aFlexShrink),
|
||||
mIntrinsicRatio(mFrame->GetIntrinsicRatio()),
|
||||
mIntrinsicRatio(mFrame->GetAspectRatio()),
|
||||
mBorderPadding(aFlexItemReflowInput.ComputedPhysicalBorderPadding()),
|
||||
mMargin(aFlexItemReflowInput.ComputedPhysicalMargin()),
|
||||
mMainMinSize(aMainMinSize),
|
||||
|
||||
+67
-26
@@ -4655,10 +4655,44 @@ nsFrame::GetIntrinsicSize()
|
||||
/* virtual */ AspectRatio
|
||||
nsFrame::GetIntrinsicRatio()
|
||||
{
|
||||
const nsStylePosition* stylePos = StylePosition();
|
||||
return stylePos->mAspectRatio == 0.0f
|
||||
? AspectRatio()
|
||||
: AspectRatio(stylePos->mAspectRatio);
|
||||
return AspectRatio();
|
||||
}
|
||||
|
||||
AspectRatio
|
||||
nsIFrame::GetAspectRatio()
|
||||
{
|
||||
// The property does not apply to inline boxes or internal ruby/table boxes.
|
||||
nsIAtom* type = GetType();
|
||||
if (type == nsGkAtoms::inlineFrame ||
|
||||
RubyUtils::IsRubyBox(type) ||
|
||||
type == nsGkAtoms::tableCellFrame ||
|
||||
type == nsGkAtoms::tableColFrame ||
|
||||
type == nsGkAtoms::tableColGroupFrame ||
|
||||
type == nsGkAtoms::tableRowFrame ||
|
||||
type == nsGkAtoms::tableRowGroupFrame) {
|
||||
return AspectRatio();
|
||||
}
|
||||
|
||||
const StyleAspectRatio& styleRatio = StylePosition()->mAspectRatio;
|
||||
|
||||
// A non-auto, non-degenerate ratio overrides the natural ratio and uses the
|
||||
// box selected by box-sizing.
|
||||
if (!styleRatio.mAuto && styleRatio.HasUsableRatio()) {
|
||||
return AspectRatio::FromSize(styleRatio.mWidth, styleRatio.mHeight,
|
||||
UseBoxSizing::Yes);
|
||||
}
|
||||
|
||||
if (AspectRatio intrinsicRatio = GetIntrinsicRatio()) {
|
||||
return intrinsicRatio;
|
||||
}
|
||||
|
||||
// The fallback in "auto <ratio>" always operates on the content box.
|
||||
if (styleRatio.HasUsableRatio()) {
|
||||
return AspectRatio::FromSize(styleRatio.mWidth, styleRatio.mHeight,
|
||||
UseBoxSizing::No);
|
||||
}
|
||||
|
||||
return AspectRatio();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -4727,11 +4761,11 @@ nsFrame::ComputeSize(nsRenderingContext* aRenderingContext,
|
||||
const LogicalSize& aPadding,
|
||||
ComputeSizeFlags aFlags)
|
||||
{
|
||||
AspectRatio intrinsicRatio = GetIntrinsicRatio();
|
||||
if (intrinsicRatio) {
|
||||
AspectRatio aspectRatio = GetAspectRatio();
|
||||
if (aspectRatio) {
|
||||
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
|
||||
GetIntrinsicSize(),
|
||||
intrinsicRatio,
|
||||
aspectRatio,
|
||||
aCBSize, aMargin,
|
||||
aBorder, aPadding,
|
||||
aFlags);
|
||||
@@ -4976,8 +5010,6 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
|
||||
const LogicalSize& aPadding,
|
||||
ComputeSizeFlags aFlags)
|
||||
{
|
||||
auto logicalRatio =
|
||||
aWM.IsVertical() ? aIntrinsicRatio.Inverted() : aIntrinsicRatio;
|
||||
const nsStylePosition* stylePos = StylePosition();
|
||||
const nsStyleCoord* inlineStyleCoord = &stylePos->ISize(aWM);
|
||||
const nsStyleCoord* blockStyleCoord = &stylePos->BSize(aWM);
|
||||
@@ -5039,6 +5071,14 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
|
||||
if (stylePos->mBoxSizing == StyleBoxSizing::Border) {
|
||||
boxSizingAdjust = aBorder + aPadding;
|
||||
}
|
||||
auto iSizeFromBSize = [&](nscoord aBSize) {
|
||||
return aIntrinsicRatio.ComputeRatioDependentSize(
|
||||
eLogicalAxisInline, aWM, aBSize, boxSizingAdjust);
|
||||
};
|
||||
auto bSizeFromISize = [&](nscoord aISize) {
|
||||
return aIntrinsicRatio.ComputeRatioDependentSize(
|
||||
eLogicalAxisBlock, aWM, aISize, boxSizingAdjust);
|
||||
};
|
||||
nscoord boxSizingToMarginEdgeISize =
|
||||
aMargin.ISize(aWM) + aBorder.ISize(aWM) + aPadding.ISize(aWM) -
|
||||
boxSizingAdjust.ISize(aWM);
|
||||
@@ -5129,7 +5169,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
|
||||
bSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM),
|
||||
boxSizingAdjust.BSize(aWM),
|
||||
*blockStyleCoord);
|
||||
} else if (MOZ_UNLIKELY(isGridItem)) {
|
||||
} else if (MOZ_UNLIKELY(isGridItem) &&
|
||||
!(aFlags & nsIFrame::eUseAutoBSize)) {
|
||||
MOZ_ASSERT(!IS_TRUE_OVERFLOW_CONTAINER(this));
|
||||
// 'auto' block-size for grid-level box - apply 'stretch' as needed:
|
||||
auto cbSize = aCBSize.BSize(aWM);
|
||||
@@ -5230,9 +5271,9 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
|
||||
|
||||
if (hasIntrinsicISize) {
|
||||
tentISize = intrinsicISize;
|
||||
} else if (hasIntrinsicBSize && logicalRatio) {
|
||||
tentISize = logicalRatio.ApplyTo(intrinsicBSize);
|
||||
} else if (logicalRatio) {
|
||||
} else if (hasIntrinsicBSize && aIntrinsicRatio) {
|
||||
tentISize = iSizeFromBSize(intrinsicBSize);
|
||||
} else if (aIntrinsicRatio) {
|
||||
tentISize = aCBSize.ISize(aWM) - boxSizingToMarginEdgeISize; // XXX scrollbar?
|
||||
if (tentISize < 0) tentISize = 0;
|
||||
} else {
|
||||
@@ -5249,8 +5290,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
|
||||
|
||||
if (hasIntrinsicBSize) {
|
||||
tentBSize = intrinsicBSize;
|
||||
} else if (logicalRatio) {
|
||||
tentBSize = logicalRatio.Inverted().ApplyTo(tentISize);
|
||||
} else if (aIntrinsicRatio) {
|
||||
tentBSize = bSizeFromISize(tentISize);
|
||||
} else {
|
||||
tentBSize = nsPresContext::CSSPixelsToAppUnits(150);
|
||||
}
|
||||
@@ -5261,39 +5302,39 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
|
||||
stretchB = (stretchI == eStretch ? eStretch : eStretchPreservingRatio);
|
||||
}
|
||||
|
||||
if (logicalRatio) {
|
||||
if (aIntrinsicRatio) {
|
||||
if (stretchI == eStretch) {
|
||||
tentISize = iSize; // * / 'stretch'
|
||||
if (stretchB == eStretch) {
|
||||
tentBSize = bSize; // 'stretch' / 'stretch'
|
||||
} else if (stretchB == eStretchPreservingRatio) {
|
||||
// 'normal' / 'stretch'
|
||||
tentBSize = logicalRatio.Inverted().ApplyTo(iSize);
|
||||
tentBSize = bSizeFromISize(iSize);
|
||||
}
|
||||
} else if (stretchB == eStretch) {
|
||||
tentBSize = bSize; // 'stretch' / * (except 'stretch')
|
||||
if (stretchI == eStretchPreservingRatio) {
|
||||
// 'stretch' / 'normal'
|
||||
tentISize = logicalRatio.ApplyTo(bSize);
|
||||
tentISize = iSizeFromBSize(bSize);
|
||||
}
|
||||
} else if (stretchI == eStretchPreservingRatio) {
|
||||
tentISize = iSize; // * (except 'stretch') / 'normal'
|
||||
tentBSize = logicalRatio.Inverted().ApplyTo(iSize);
|
||||
tentBSize = bSizeFromISize(iSize);
|
||||
if (stretchB == eStretchPreservingRatio && tentBSize > bSize) {
|
||||
// Stretch within the CB size with preserved intrinsic ratio.
|
||||
tentBSize = bSize; // 'normal' / 'normal'
|
||||
tentISize = logicalRatio.ApplyTo(bSize);
|
||||
tentISize = iSizeFromBSize(bSize);
|
||||
}
|
||||
} else if (stretchB == eStretchPreservingRatio) {
|
||||
tentBSize = bSize; // 'normal' / * (except 'normal' and 'stretch')
|
||||
tentISize = logicalRatio.ApplyTo(bSize);
|
||||
tentISize = iSizeFromBSize(bSize);
|
||||
}
|
||||
}
|
||||
|
||||
// ComputeAutoSizeWithIntrinsicDimensions preserves the ratio when applying
|
||||
// the min/max-size. We don't want that when we have 'stretch' in either
|
||||
// axis because tentISize/tentBSize is likely not according to ratio now.
|
||||
if (logicalRatio && stretchI != eStretch && stretchB != eStretch) {
|
||||
if (aIntrinsicRatio && stretchI != eStretch && stretchB != eStretch) {
|
||||
nsSize autoSize = nsLayoutUtils::
|
||||
ComputeAutoSizeWithIntrinsicDimensions(minISize, minBSize,
|
||||
maxISize, maxBSize,
|
||||
@@ -5314,8 +5355,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
|
||||
// 'auto' iSize, non-'auto' bSize
|
||||
bSize = NS_CSS_MINMAX(bSize, minBSize, maxBSize);
|
||||
if (stretchI != eStretch) {
|
||||
if (logicalRatio) {
|
||||
iSize = logicalRatio.ApplyTo(bSize);
|
||||
if (aIntrinsicRatio) {
|
||||
iSize = iSizeFromBSize(bSize);
|
||||
} else if (hasIntrinsicISize) {
|
||||
if (!((aFlags & ComputeSizeFlags::eIClampMarginBoxMinSize) &&
|
||||
intrinsicISize > iSize)) {
|
||||
@@ -5334,8 +5375,8 @@ nsFrame::ComputeSizeWithIntrinsicDimensions(nsRenderingContext* aRenderingConte
|
||||
// non-'auto' iSize, 'auto' bSize
|
||||
iSize = NS_CSS_MINMAX(iSize, minISize, maxISize);
|
||||
if (stretchB != eStretch) {
|
||||
if (logicalRatio) {
|
||||
bSize = logicalRatio.Inverted().ApplyTo(iSize);
|
||||
if (aIntrinsicRatio) {
|
||||
bSize = bSizeFromISize(iSize);
|
||||
} else if (hasIntrinsicBSize) {
|
||||
if (!((aFlags & ComputeSizeFlags::eBClampMarginBoxMinSize) &&
|
||||
intrinsicBSize > bSize)) {
|
||||
|
||||
@@ -318,7 +318,11 @@ nsHTMLFramesetFrame::Init(nsIContent* aContent,
|
||||
mChildFrameborder[mChildCount] = GetFrameBorder(child);
|
||||
mChildBorderColors[mChildCount].Set(GetBorderColor(child));
|
||||
}
|
||||
child->SetPrimaryFrame(frame);
|
||||
if (MOZ_LIKELY(!child->GetPrimaryFrame())) {
|
||||
// Child might have a pre-existing primary frame if we're doing fixed-pos
|
||||
// replication... So, only set it if there is no primary frame yet.
|
||||
child->SetPrimaryFrame(frame);
|
||||
}
|
||||
|
||||
mFrames.AppendFrame(nullptr, frame);
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ nsHTMLCanvasFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
||||
intrinsicSize.width.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.width));
|
||||
intrinsicSize.height.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(size.height));
|
||||
|
||||
AspectRatio intrinsicRatio = GetIntrinsicRatio();
|
||||
AspectRatio intrinsicRatio = GetAspectRatio();
|
||||
|
||||
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
|
||||
intrinsicSize, intrinsicRatio,
|
||||
@@ -424,4 +424,3 @@ nsHTMLCanvasFrame::GetFrameName(nsAString& aResult) const
|
||||
return MakeFrameName(NS_LITERAL_STRING("HTMLCanvas"), aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2078,6 +2078,12 @@ public:
|
||||
|
||||
virtual mozilla::IntrinsicSize GetIntrinsicSize() = 0;
|
||||
|
||||
/**
|
||||
* Get the preferred aspect ratio after applying the aspect-ratio property
|
||||
* to this frame's natural ratio.
|
||||
*/
|
||||
mozilla::AspectRatio GetAspectRatio();
|
||||
|
||||
/**
|
||||
* Get the intrinsic ratio of this element, or a default-constructed
|
||||
* AspectRatio if it has no intrinsic ratio.
|
||||
|
||||
@@ -320,7 +320,7 @@ ComputeIntrinsicSize(imgIContainer* aImage,
|
||||
}
|
||||
*/
|
||||
|
||||
if (aUseMappedRatio && aFrame.StylePosition()->mAspectRatio != 0.0f) {
|
||||
if (aUseMappedRatio && aFrame.StylePosition()->mAspectRatio.HasRatio()) {
|
||||
return IntrinsicSize();
|
||||
}
|
||||
|
||||
@@ -375,8 +375,10 @@ ComputeAspectRatio(imgIContainer* aImage,
|
||||
return fromImage;
|
||||
}
|
||||
}
|
||||
if (aUseMappedRatio && aFrame.StylePosition()->mAspectRatio != 0.0f) {
|
||||
return AspectRatio(aFrame.StylePosition()->mAspectRatio);
|
||||
if (aUseMappedRatio &&
|
||||
aFrame.StylePosition()->mAspectRatio.HasUsableRatio()) {
|
||||
const StyleAspectRatio& ratio = aFrame.StylePosition()->mAspectRatio;
|
||||
return AspectRatio::FromSize(ratio.mWidth, ratio.mHeight);
|
||||
}
|
||||
if (aFrame.ShouldShowBrokenImageIcon()) {
|
||||
return AspectRatio(1.0f);
|
||||
@@ -891,7 +893,7 @@ nsImageFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
||||
}
|
||||
|
||||
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
|
||||
intrinsicSize, mIntrinsicRatio,
|
||||
intrinsicSize, GetAspectRatio(),
|
||||
aCBSize, aMargin, aBorder, aPadding,
|
||||
aFlags);
|
||||
}
|
||||
|
||||
@@ -786,7 +786,7 @@ IsPercentageAware(const nsIFrame* aFrame)
|
||||
// is calculated from the constraint equation used for
|
||||
// block-level, non-replaced elements in normal flow.
|
||||
nsIFrame *f = const_cast<nsIFrame*>(aFrame);
|
||||
if (f->GetIntrinsicRatio() &&
|
||||
if (f->GetAspectRatio() &&
|
||||
// Some percents are treated like 'auto', so check != coord
|
||||
pos->mHeight.GetUnit() != eStyleUnit_Coord) {
|
||||
const IntrinsicSize &intrinsicSize = f->GetIntrinsicSize();
|
||||
|
||||
@@ -721,7 +721,7 @@ nsSubDocumentFrame::ComputeSize(nsRenderingContext* aRenderingContext,
|
||||
if (subDocRoot) {
|
||||
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
|
||||
subDocRoot->GetIntrinsicSize(),
|
||||
subDocRoot->GetIntrinsicRatio(),
|
||||
GetAspectRatio(),
|
||||
aCBSize, aMargin, aBorder,
|
||||
aPadding, aFlags);
|
||||
}
|
||||
|
||||
@@ -543,13 +543,8 @@ nsVideoFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
||||
intrinsicSize.width.SetCoordValue(size.width);
|
||||
intrinsicSize.height.SetCoordValue(size.height);
|
||||
|
||||
// Only video elements have an intrinsic ratio.
|
||||
auto intrinsicRatio = HasVideoElement() ?
|
||||
AspectRatio::FromSize(size) :
|
||||
AspectRatio();
|
||||
|
||||
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
|
||||
intrinsicSize, intrinsicRatio,
|
||||
intrinsicSize, GetAspectRatio(),
|
||||
aCBSize, aMargin, aBorder, aPadding,
|
||||
aFlags);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Grid: aspect-ratio contributes to an auto row reference</title>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.gallery {
|
||||
display: grid;
|
||||
width: 640px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
padding: 30px;
|
||||
}
|
||||
.item {
|
||||
position: relative;
|
||||
height: 280px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.item > div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="gallery">
|
||||
<div class="item"><div></div></div>
|
||||
<div class="item"><div></div></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Grid: aspect-ratio contributes to an auto row</title>
|
||||
<link rel="match" href="grid-item-aspect-ratio-001-ref.html">
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.gallery {
|
||||
display: grid;
|
||||
width: 640px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
padding: 30px;
|
||||
}
|
||||
.item {
|
||||
position: relative;
|
||||
aspect-ratio: 1;
|
||||
overflow: hidden;
|
||||
background: red;
|
||||
}
|
||||
.item > div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="gallery">
|
||||
<div class="item"><div></div></div>
|
||||
<div class="item"><div></div></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -280,5 +280,6 @@ asserts(0-10) == grid-fragmentation-015.html grid-fragmentation-015-ref.html # b
|
||||
== grid-fragmentation-dyn2-031.html grid-fragmentation-031-ref.html
|
||||
== bug1306106.html bug1306106-ref.html
|
||||
== grid-percent-intrinsic-sizing-001.html grid-percent-intrinsic-sizing-001-ref.html
|
||||
== grid-item-aspect-ratio-001.html grid-item-aspect-ratio-001-ref.html
|
||||
== bug1349571.html bug1349571-ref.html
|
||||
== bug1356820.html bug1356820-ref.html
|
||||
@@ -1987,6 +1987,86 @@ CSSStyleSheet::DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CSSStyleSheet::ReplaceSyncInternal(const nsAString& aText, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(mInner->mComplete);
|
||||
|
||||
RefPtr<CSSStyleSheet> parsedSheet =
|
||||
new CSSStyleSheet(mParsingMode, GetCORSMode(), GetReferrerPolicy());
|
||||
parsedSheet->SetURIs(mInner->mSheetURI, mInner->mOriginalSheetURI,
|
||||
mInner->mBaseURI);
|
||||
parsedSheet->SetPrincipal(mInner->mPrincipal);
|
||||
parsedSheet->SetComplete();
|
||||
|
||||
nsCSSParser parser(nullptr, parsedSheet);
|
||||
nsresult rv = parser.ParseSheet(aText, parsedSheet->GetSheetURI(),
|
||||
parsedSheet->GetBaseURI(),
|
||||
parsedSheet->Principal(), 1);
|
||||
if (NS_FAILED(rv)) {
|
||||
parsedSheet->mInner->mOrderedRules.EnumerateForwards(SetStyleSheetReference,
|
||||
nullptr);
|
||||
parsedSheet->mInner->mOrderedRules.Clear();
|
||||
}
|
||||
|
||||
for (int32_t index = parsedSheet->mInner->mOrderedRules.Count() - 1;
|
||||
index >= 0; --index) {
|
||||
RefPtr<css::Rule> rule = parsedSheet->mInner->mOrderedRules.ObjectAt(index);
|
||||
if (rule->GetType() == css::Rule::IMPORT_RULE) {
|
||||
parsedSheet->mInner->mOrderedRules.RemoveObjectAt(index);
|
||||
rule->SetStyleSheet(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, true);
|
||||
|
||||
WillDirty();
|
||||
|
||||
while (mInner->mOrderedRules.Count() != 0) {
|
||||
RefPtr<css::Rule> rule =
|
||||
mInner->mOrderedRules.ObjectAt(mInner->mOrderedRules.Count() - 1);
|
||||
mInner->mOrderedRules.RemoveObjectAt(mInner->mOrderedRules.Count() - 1);
|
||||
rule->SetStyleSheet(nullptr);
|
||||
if (mDocument) {
|
||||
mDocument->StyleRuleRemoved(this, rule);
|
||||
}
|
||||
}
|
||||
|
||||
for (CSSStyleSheet* child = mInner->mFirstChild; child; ) {
|
||||
NS_ASSERTION(child->mParent == this, "Child sheet is not parented to this!");
|
||||
CSSStyleSheet* next = child->mNext;
|
||||
child->mParent = nullptr;
|
||||
child->mDocument = nullptr;
|
||||
child->mNext = nullptr;
|
||||
child = next;
|
||||
}
|
||||
mInner->mFirstChild = nullptr;
|
||||
mInner->mNameSpaceMap = nullptr;
|
||||
|
||||
for (int32_t index = 0; index < parsedSheet->mInner->mOrderedRules.Count();
|
||||
++index) {
|
||||
RefPtr<css::Rule> rule = parsedSheet->mInner->mOrderedRules.ObjectAt(index);
|
||||
if (!mInner->mOrderedRules.AppendObject(rule)) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
rule->SetStyleSheet(this);
|
||||
}
|
||||
parsedSheet->mInner->mOrderedRules.Clear();
|
||||
parsedSheet->mInner->mNameSpaceMap = nullptr;
|
||||
|
||||
mInner->RebuildNameSpaces();
|
||||
|
||||
DidDirty();
|
||||
|
||||
if (mDocument) {
|
||||
for (int32_t index = 0; index < mInner->mOrderedRules.Count(); ++index) {
|
||||
RefPtr<css::Rule> rule = mInner->mOrderedRules.ObjectAt(index);
|
||||
mDocument->StyleRuleAdded(this, rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
CSSStyleSheet::DeleteRuleFromGroup(css::GroupRule* aGroup, uint32_t aIndex)
|
||||
{
|
||||
|
||||
@@ -253,6 +253,7 @@ protected:
|
||||
uint32_t InsertRuleInternal(const nsAString& aRule,
|
||||
uint32_t aIndex, ErrorResult& aRv);
|
||||
void DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv);
|
||||
void ReplaceSyncInternal(const nsAString& aText, ErrorResult& aRv);
|
||||
|
||||
RefPtr<nsMediaList> mMedia;
|
||||
RefPtr<CSSStyleSheet> mNext;
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "nsIFrame.h"
|
||||
#include "gfx2DGlue.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::css;
|
||||
using namespace mozilla::gfx;
|
||||
@@ -39,6 +41,35 @@ using nsStyleTransformMatrix::Decompose2DMatrix;
|
||||
using nsStyleTransformMatrix::Decompose3DMatrix;
|
||||
using nsStyleTransformMatrix::ShearType;
|
||||
|
||||
static bool
|
||||
GetAspectRatioAnimationValue(const nsCSSValuePair* aPair,
|
||||
bool& aAuto,
|
||||
float& aRatio)
|
||||
{
|
||||
aAuto = aPair->mXValue.GetUnit() == eCSSUnit_Auto;
|
||||
if (aAuto) {
|
||||
if (aPair->mYValue.GetUnit() != eCSSUnit_Pair) {
|
||||
return false;
|
||||
}
|
||||
aPair = &aPair->mYValue.GetPairValue();
|
||||
}
|
||||
|
||||
if (aPair->mXValue.GetUnit() != eCSSUnit_Number ||
|
||||
aPair->mYValue.GetUnit() != eCSSUnit_Number) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float width = aPair->mXValue.GetFloatValue();
|
||||
float height = aPair->mYValue.GetFloatValue();
|
||||
if (width <= 0.0f || height <= 0.0f ||
|
||||
!std::isfinite(width) || !std::isfinite(height)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aRatio = width / height;
|
||||
return std::isfinite(aRatio) && aRatio > 0.0f;
|
||||
}
|
||||
|
||||
// HELPER METHODS
|
||||
// --------------
|
||||
/*
|
||||
@@ -1243,6 +1274,21 @@ StyleAnimationValue::ComputeDistance(nsCSSPropertyID aProperty,
|
||||
case eUnit_CSSValuePair: {
|
||||
const nsCSSValuePair *pair1 = aStartValue.GetCSSValuePairValue();
|
||||
const nsCSSValuePair *pair2 = aEndValue.GetCSSValuePairValue();
|
||||
if (aProperty == eCSSProperty_aspect_ratio) {
|
||||
bool auto1;
|
||||
bool auto2;
|
||||
float ratio1;
|
||||
float ratio2;
|
||||
if (!GetAspectRatioAnimationValue(pair1, auto1, ratio1) ||
|
||||
!GetAspectRatioAnimationValue(pair2, auto2, ratio2) ||
|
||||
auto1 != auto2) {
|
||||
return false;
|
||||
}
|
||||
aDistance = Abs(std::log(double(ratio2)) -
|
||||
std::log(double(ratio1)));
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCSSUnit unit[2];
|
||||
unit[0] = GetCommonUnit(aProperty, pair1->mXValue.GetUnit(),
|
||||
pair2->mXValue.GetUnit());
|
||||
@@ -2821,6 +2867,42 @@ StyleAnimationValue::AddWeighted(nsCSSPropertyID aProperty,
|
||||
return true;
|
||||
}
|
||||
case eUnit_CSSValuePair: {
|
||||
if (aProperty == eCSSProperty_aspect_ratio) {
|
||||
bool auto1;
|
||||
bool auto2;
|
||||
float ratio1;
|
||||
float ratio2;
|
||||
if (!GetAspectRatioAnimationValue(aValue1.GetCSSValuePairValue(),
|
||||
auto1, ratio1) ||
|
||||
!GetAspectRatioAnimationValue(aValue2.GetCSSValuePairValue(),
|
||||
auto2, ratio2) ||
|
||||
auto1 != auto2 ||
|
||||
std::abs((aCoeff1 + aCoeff2) - 1.0) > 0.000001) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float resultRatio =
|
||||
std::exp(aCoeff1 * std::log(double(ratio1)) +
|
||||
aCoeff2 * std::log(double(ratio2)));
|
||||
nsCSSValue width;
|
||||
width.SetFloatValue(resultRatio, eCSSUnit_Number);
|
||||
nsCSSValue height;
|
||||
height.SetFloatValue(1.0f, eCSSUnit_Number);
|
||||
nsCSSValue ratio;
|
||||
ratio.SetPairValue(width, height);
|
||||
|
||||
auto result = MakeUnique<nsCSSValuePair>();
|
||||
if (auto1) {
|
||||
result->mXValue.SetAutoValue();
|
||||
result->mYValue = ratio;
|
||||
} else {
|
||||
*result = ratio.GetPairValue();
|
||||
}
|
||||
aResultValue.SetAndAdoptCSSValuePairValue(result.release(),
|
||||
eUnit_CSSValuePair);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t restrictions = nsCSSProps::ValueRestrictions(aProperty);
|
||||
Maybe<nsCSSValuePair> result =
|
||||
AddCSSValuePair(aProperty, restrictions,
|
||||
@@ -4031,6 +4113,33 @@ StyleAnimationValue::ExtractComputedValue(nsCSSPropertyID aProperty,
|
||||
break;
|
||||
}
|
||||
|
||||
case eCSSProperty_aspect_ratio: {
|
||||
const StyleAspectRatio& ratio =
|
||||
static_cast<const nsStylePosition*>(styleStruct)->mAspectRatio;
|
||||
if (!ratio.HasRatio()) {
|
||||
aComputedValue.SetAutoValue();
|
||||
break;
|
||||
}
|
||||
|
||||
nsCSSValue width;
|
||||
width.SetFloatValue(ratio.mWidth, eCSSUnit_Number);
|
||||
nsCSSValue height;
|
||||
height.SetFloatValue(ratio.mHeight, eCSSUnit_Number);
|
||||
nsCSSValue ratioValue;
|
||||
ratioValue.SetPairValue(width, height);
|
||||
|
||||
auto pair = MakeUnique<nsCSSValuePair>();
|
||||
if (ratio.mAuto) {
|
||||
pair->mXValue.SetAutoValue();
|
||||
pair->mYValue = ratioValue;
|
||||
} else {
|
||||
*pair = ratioValue.GetPairValue();
|
||||
}
|
||||
aComputedValue.SetAndAdoptCSSValuePairValue(pair.release(),
|
||||
eUnit_CSSValuePair);
|
||||
break;
|
||||
}
|
||||
|
||||
case eCSSProperty_border_spacing: {
|
||||
const nsStyleTableBorder *styleTableBorder =
|
||||
static_cast<const nsStyleTableBorder*>(styleStruct);
|
||||
|
||||
@@ -26,6 +26,8 @@ StyleSheet::StyleSheet(css::SheetParsingMode aParsingMode)
|
||||
, mOwningNode(nullptr)
|
||||
, mParsingMode(aParsingMode)
|
||||
, mDisabled(false)
|
||||
, mConstructed(false)
|
||||
, mDisallowModification(false)
|
||||
, mDocumentAssociationMode(NotOwnedByDocument)
|
||||
{
|
||||
}
|
||||
@@ -38,6 +40,8 @@ StyleSheet::StyleSheet(const StyleSheet& aCopy,
|
||||
, mOwningNode(aOwningNodeToUse)
|
||||
, mParsingMode(aCopy.mParsingMode)
|
||||
, mDisabled(aCopy.mDisabled)
|
||||
, mConstructed(aCopy.mConstructed)
|
||||
, mDisallowModification(false)
|
||||
// We only use this constructor during cloning. It's the cloner's
|
||||
// responsibility to notify us if we end up being owned by a document.
|
||||
, mDocumentAssociationMode(NotOwnedByDocument)
|
||||
@@ -254,6 +258,7 @@ StyleSheet::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
sheet->SetURIs(documentURI, nullptr, baseURI);
|
||||
sheet->SetPrincipal(principal);
|
||||
sheet->SetComplete();
|
||||
sheet->SetConstructed();
|
||||
|
||||
return sheet.forget();
|
||||
}
|
||||
@@ -290,6 +295,17 @@ StyleSheet::DeleteRule(uint32_t aIndex,
|
||||
AsConcrete()->DeleteRuleInternal(aIndex, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
StyleSheet::ReplaceSync(const nsAString& aText, ErrorResult& aRv)
|
||||
{
|
||||
if (!IsConstructed() || IsModificationDisallowed()) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_ALLOWED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
AsConcrete()->ReplaceSyncInternal(aText, aRv);
|
||||
}
|
||||
|
||||
int32_t
|
||||
StyleSheet::AddRule(const nsAString& aSelector, const nsAString& aBlock,
|
||||
const Optional<uint32_t>& aIndex,
|
||||
|
||||
@@ -160,6 +160,7 @@ public:
|
||||
void DeleteRule(uint32_t aIndex,
|
||||
nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv);
|
||||
void ReplaceSync(const nsAString& aText, ErrorResult& aRv);
|
||||
int32_t AddRule(const nsAString& aSelector, const nsAString& aBlock,
|
||||
const dom::Optional<uint32_t>& aIndex,
|
||||
nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
|
||||
@@ -205,6 +206,10 @@ private:
|
||||
bool AreRulesAvailable(nsIPrincipal& aSubjectPrincipal,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool IsConstructed() const { return mConstructed; }
|
||||
void SetConstructed() { mConstructed = true; }
|
||||
bool IsModificationDisallowed() const { return mDisallowModification; }
|
||||
|
||||
protected:
|
||||
// Return success if the subject principal subsumes the principal of our
|
||||
// inner, error otherwise. This will also succeed if the subject has
|
||||
@@ -223,6 +228,8 @@ protected:
|
||||
css::SheetParsingMode mParsingMode;
|
||||
|
||||
bool mDisabled;
|
||||
bool mConstructed;
|
||||
bool mDisallowModification;
|
||||
|
||||
// mDocumentAssociationMode determines whether mDocument directly owns us (in
|
||||
// the sense that if it's known-live then we're known-live). Always
|
||||
|
||||
@@ -13419,23 +13419,26 @@ bool
|
||||
CSSParserImpl::ParseAspectRatioRatio(nsCSSValue& aValue)
|
||||
{
|
||||
nsCSSValue width;
|
||||
if (!ParseNonNegativeNumber(width)) {
|
||||
if (!ParseSingleTokenNonNegativeVariant(width,
|
||||
VARIANT_NUMBER | VARIANT_CALC,
|
||||
nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float w = width.GetFloatValue();
|
||||
float h = 1.0f;
|
||||
nsCSSValue height;
|
||||
height.SetFloatValue(1.0f, eCSSUnit_Number);
|
||||
if (ExpectSymbol('/', true)) {
|
||||
nsCSSValue height;
|
||||
if (!ParseNonNegativeNumber(height)) {
|
||||
if (!ParseSingleTokenNonNegativeVariant(height,
|
||||
VARIANT_NUMBER | VARIANT_CALC,
|
||||
nullptr)) {
|
||||
return false;
|
||||
}
|
||||
h = height.GetFloatValue();
|
||||
}
|
||||
|
||||
// Degenerate ratios behave as auto in layout.
|
||||
aValue.SetFloatValue(w == 0.0f || h == 0.0f ? 0.0f : w / h,
|
||||
eCSSUnit_Number);
|
||||
// Keep both components: the computed value is a pair of numbers, and
|
||||
// degenerate ratios still serialize as ratios even though they behave as
|
||||
// auto during layout.
|
||||
aValue.SetPairValue(width, height);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13458,9 +13461,15 @@ CSSParserImpl::ParseAspectRatio(nsCSSValue& aValue)
|
||||
if (hasRatio) {
|
||||
if (!hasAuto) {
|
||||
// The grammar is "auto || <ratio>", so auto may appear after the ratio.
|
||||
ParseSingleTokenVariant(autoValue, VARIANT_AUTO, nullptr);
|
||||
hasAuto = ParseSingleTokenVariant(autoValue, VARIANT_AUTO, nullptr);
|
||||
}
|
||||
if (hasAuto) {
|
||||
nsCSSValue combined;
|
||||
combined.SetPairValue(autoValue, ratioValue);
|
||||
aValue = combined;
|
||||
} else {
|
||||
aValue = ratioValue;
|
||||
}
|
||||
aValue = ratioValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -479,8 +479,8 @@ CSS_PROP_POSITION(
|
||||
"",
|
||||
0,
|
||||
nullptr,
|
||||
offsetof(nsStylePosition, mAspectRatio),
|
||||
eStyleAnimType_None)
|
||||
CSS_PROP_NO_OFFSET,
|
||||
eStyleAnimType_Custom)
|
||||
CSS_PROP_DISPLAY(
|
||||
backface-visibility,
|
||||
backface_visibility,
|
||||
|
||||
@@ -2972,6 +2972,20 @@ nsCSSValuePair::AppendToString(nsCSSPropertyID aProperty,
|
||||
nsAString& aResult,
|
||||
nsCSSValue::Serialization aSerialization) const
|
||||
{
|
||||
if (aProperty == eCSSProperty_aspect_ratio) {
|
||||
if (mXValue.GetUnit() == eCSSUnit_Auto) {
|
||||
mXValue.AppendToString(aProperty, aResult, aSerialization);
|
||||
aResult.Append(char16_t(' '));
|
||||
mYValue.AppendToString(aProperty, aResult, aSerialization);
|
||||
return;
|
||||
}
|
||||
|
||||
mXValue.AppendToString(aProperty, aResult, aSerialization);
|
||||
aResult.AppendLiteral(" / ");
|
||||
mYValue.AppendToString(aProperty, aResult, aSerialization);
|
||||
return;
|
||||
}
|
||||
|
||||
mXValue.AppendToString(aProperty, aResult, aSerialization);
|
||||
if (mYValue.GetUnit() != eCSSUnit_Null) {
|
||||
aResult.Append(char16_t(' '));
|
||||
|
||||
@@ -968,13 +968,17 @@ already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetAspectRatio()
|
||||
{
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
float ratio = StylePosition()->mAspectRatio;
|
||||
if (ratio == 0.0f) {
|
||||
const StyleAspectRatio& ratio = StylePosition()->mAspectRatio;
|
||||
if (!ratio.HasRatio()) {
|
||||
val->SetIdent(eCSSKeyword_auto);
|
||||
} else {
|
||||
nsAutoString ratioString;
|
||||
nsStyleUtil::AppendCSSNumber(ratio, ratioString);
|
||||
ratioString.AppendLiteral(" / 1");
|
||||
if (ratio.mAuto) {
|
||||
ratioString.AppendLiteral("auto ");
|
||||
}
|
||||
nsStyleUtil::AppendCSSNumber(ratio.mWidth, ratioString);
|
||||
ratioString.AppendLiteral(" / ");
|
||||
nsStyleUtil::AppendCSSNumber(ratio.mHeight, ratioString);
|
||||
val->SetString(ratioString);
|
||||
}
|
||||
return val.forget();
|
||||
|
||||
@@ -9607,15 +9607,54 @@ nsRuleNode::ComputePositionData(void* aStartStruct,
|
||||
SETCOORD_UNSET_INITIAL,
|
||||
aContext, mPresContext, conditions);
|
||||
|
||||
// aspect-ratio: auto | <ratio>
|
||||
// aspect-ratio: auto || <ratio>
|
||||
const nsCSSValue* aspectRatio = aRuleData->ValueForAspectRatio();
|
||||
if (aspectRatio->GetUnit() == eCSSUnit_Auto) {
|
||||
pos->mAspectRatio = 0.0f;
|
||||
} else {
|
||||
SetFactor(*aspectRatio,
|
||||
pos->mAspectRatio, conditions,
|
||||
parentPos->mAspectRatio, 0.0f,
|
||||
SETFCT_UNSET_INITIAL | SETFCT_POSITIVE | SETFCT_NONE);
|
||||
switch (aspectRatio->GetUnit()) {
|
||||
case eCSSUnit_Null:
|
||||
break;
|
||||
|
||||
case eCSSUnit_Inherit:
|
||||
conditions.SetUncacheable();
|
||||
pos->mAspectRatio = parentPos->mAspectRatio;
|
||||
break;
|
||||
|
||||
case eCSSUnit_Auto:
|
||||
case eCSSUnit_Initial:
|
||||
case eCSSUnit_Unset:
|
||||
case eCSSUnit_Revert:
|
||||
case eCSSUnit_RevertLayer:
|
||||
pos->mAspectRatio = StyleAspectRatio();
|
||||
break;
|
||||
|
||||
case eCSSUnit_Number:
|
||||
// Animation normalizes a ratio to <number> / 1 when both components
|
||||
// would otherwise compare equal and the pair is collapsed.
|
||||
pos->mAspectRatio =
|
||||
StyleAspectRatio(aspectRatio->GetFloatValue(), 1.0f, false);
|
||||
break;
|
||||
|
||||
case eCSSUnit_Pair: {
|
||||
const nsCSSValuePair* ratio = &aspectRatio->GetPairValue();
|
||||
bool hasAuto = ratio->mXValue.GetUnit() == eCSSUnit_Auto;
|
||||
if (hasAuto) {
|
||||
MOZ_ASSERT(ratio->mYValue.GetUnit() == eCSSUnit_Pair,
|
||||
"auto must be followed by a ratio");
|
||||
ratio = &ratio->mYValue.GetPairValue();
|
||||
}
|
||||
|
||||
float width = 0.0f;
|
||||
float height = 0.0f;
|
||||
SetFactor(ratio->mXValue, width, conditions, 0.0f, 0.0f,
|
||||
SETFCT_POSITIVE);
|
||||
SetFactor(ratio->mYValue, height, conditions, 0.0f, 0.0f,
|
||||
SETFCT_POSITIVE);
|
||||
pos->mAspectRatio = StyleAspectRatio(width, height, hasAuto);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unexpected aspect-ratio unit");
|
||||
break;
|
||||
}
|
||||
|
||||
// box-sizing: enum, inherit, initial
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef nsStyleCoord_h___
|
||||
#define nsStyleCoord_h___
|
||||
|
||||
#include "mozilla/LogicalTypes.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsTArray.h"
|
||||
@@ -17,30 +18,6 @@ namespace mozilla {
|
||||
|
||||
class WritingMode;
|
||||
|
||||
// Logical axis, edge, side and corner constants for use in various places.
|
||||
enum LogicalAxis {
|
||||
eLogicalAxisBlock = 0x0,
|
||||
eLogicalAxisInline = 0x1
|
||||
};
|
||||
enum LogicalEdge {
|
||||
eLogicalEdgeStart = 0x0,
|
||||
eLogicalEdgeEnd = 0x1
|
||||
};
|
||||
enum LogicalSide {
|
||||
eLogicalSideBStart = (eLogicalAxisBlock << 1) | eLogicalEdgeStart, // 0x0
|
||||
eLogicalSideBEnd = (eLogicalAxisBlock << 1) | eLogicalEdgeEnd, // 0x1
|
||||
eLogicalSideIStart = (eLogicalAxisInline << 1) | eLogicalEdgeStart, // 0x2
|
||||
eLogicalSideIEnd = (eLogicalAxisInline << 1) | eLogicalEdgeEnd // 0x3
|
||||
};
|
||||
|
||||
enum LogicalCorner
|
||||
{
|
||||
eLogicalCornerBStartIStart = 0,
|
||||
eLogicalCornerBStartIEnd = 1,
|
||||
eLogicalCornerBEndIEnd = 2,
|
||||
eLogicalCornerBEndIStart = 3
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
enum nsStyleUnit : uint8_t {
|
||||
|
||||
@@ -1372,7 +1372,7 @@ nsStylePosition::nsStylePosition(nsPresContext* aContext)
|
||||
, mGridAutoColumnsMax(eStyleUnit_Auto)
|
||||
, mGridAutoRowsMin(eStyleUnit_Auto)
|
||||
, mGridAutoRowsMax(eStyleUnit_Auto)
|
||||
, mAspectRatio(0.0f)
|
||||
, mAspectRatio()
|
||||
, mGridAutoFlow(NS_STYLE_GRID_AUTO_FLOW_ROW)
|
||||
, mBoxSizing(StyleBoxSizing::Content)
|
||||
, mAlignContent(NS_STYLE_ALIGN_NORMAL)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "imgRequestProxy.h"
|
||||
#include "Orientation.h"
|
||||
#include "CounterStyleManager.h"
|
||||
#include <cmath>
|
||||
#include <cstddef> // offsetof()
|
||||
#include <utility>
|
||||
#include "X11UndefineNone.h"
|
||||
@@ -1679,6 +1680,52 @@ struct nsStyleGridTemplate
|
||||
}
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct StyleAspectRatio {
|
||||
StyleAspectRatio()
|
||||
: mWidth(0.0f)
|
||||
, mHeight(1.0f)
|
||||
, mAuto(true)
|
||||
, mHasRatio(false)
|
||||
{}
|
||||
|
||||
StyleAspectRatio(float aWidth, float aHeight, bool aAuto)
|
||||
: mWidth(aWidth)
|
||||
, mHeight(aHeight)
|
||||
, mAuto(aAuto)
|
||||
, mHasRatio(true)
|
||||
{}
|
||||
|
||||
bool HasRatio() const { return mHasRatio; }
|
||||
|
||||
bool HasUsableRatio() const {
|
||||
return mHasRatio &&
|
||||
mWidth != 0.0f &&
|
||||
mHeight != 0.0f &&
|
||||
std::isfinite(mWidth) &&
|
||||
std::isfinite(mHeight);
|
||||
}
|
||||
|
||||
bool operator==(const StyleAspectRatio& aOther) const {
|
||||
return mWidth == aOther.mWidth &&
|
||||
mHeight == aOther.mHeight &&
|
||||
mAuto == aOther.mAuto &&
|
||||
mHasRatio == aOther.mHasRatio;
|
||||
}
|
||||
|
||||
bool operator!=(const StyleAspectRatio& aOther) const {
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
float mWidth;
|
||||
float mHeight;
|
||||
bool mAuto;
|
||||
bool mHasRatio;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition
|
||||
{
|
||||
explicit nsStylePosition(nsPresContext* aContext);
|
||||
@@ -1743,7 +1790,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition
|
||||
nsStyleCoord mGridAutoColumnsMax; // [reset] coord, percent, enum, calc, flex
|
||||
nsStyleCoord mGridAutoRowsMin; // [reset] coord, percent, enum, calc, flex
|
||||
nsStyleCoord mGridAutoRowsMax; // [reset] coord, percent, enum, calc, flex
|
||||
float mAspectRatio; // [reset] float
|
||||
mozilla::StyleAspectRatio mAspectRatio; // [reset]
|
||||
uint8_t mGridAutoFlow; // [reset] enumerated. See nsStyleConsts.h
|
||||
mozilla::StyleBoxSizing mBoxSizing; // [reset] see nsStyleConsts.h
|
||||
|
||||
|
||||
@@ -1172,8 +1172,30 @@ var gCSSProperties = {
|
||||
inherited: false,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: ["auto"],
|
||||
other_values: ["1", "2"],
|
||||
invalid_values: ["none", "-1", "1px", "1 / -1", "1 /", "auto auto"],
|
||||
other_values: [
|
||||
"1",
|
||||
"2",
|
||||
"3 / 2",
|
||||
"0",
|
||||
"0 / 1",
|
||||
"1 / 0",
|
||||
"auto 16 / 9",
|
||||
"16 / 9 auto",
|
||||
"calc(1 + 1)",
|
||||
"calc(6) / calc(4)",
|
||||
],
|
||||
invalid_values: [
|
||||
"none",
|
||||
"-1",
|
||||
"1px",
|
||||
"1 / -1",
|
||||
"1 /",
|
||||
"auto auto",
|
||||
"1 1",
|
||||
"1 / 1 / 1",
|
||||
"auto 1 auto",
|
||||
"infinity",
|
||||
],
|
||||
},
|
||||
"-moz-border-bottom-colors": {
|
||||
domProp: "MozBorderBottomColors",
|
||||
|
||||
@@ -4,29 +4,76 @@
|
||||
<title>Test CSS aspect-ratio property</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
@keyframes aspect-ratio-interpolation {
|
||||
from { aspect-ratio: 1; }
|
||||
to { aspect-ratio: 4; }
|
||||
}
|
||||
#animated-ratio {
|
||||
animation: aspect-ratio-interpolation 100s linear -50s paused;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container" style="position:absolute; left:0; top:0; width:120px;">
|
||||
<div id="ratio" style="width:120px; aspect-ratio:3 / 2;"></div>
|
||||
<div id="bare-ratio" style="width:120px; aspect-ratio:2;"></div>
|
||||
<div id="wrapper" style="position:relative; width:120px; aspect-ratio:1 / 1;">
|
||||
<div style="position:absolute; inset:0;"></div>
|
||||
</div>
|
||||
<div id="zero-ratio" style="width:120px; aspect-ratio:0;"></div>
|
||||
<div id="border-box-ratio"
|
||||
style="box-sizing:border-box; width:120px; padding:10px;
|
||||
border:10px solid; aspect-ratio:2;"></div>
|
||||
<div id="content-box-ratio"
|
||||
style="box-sizing:content-box; width:120px; padding:10px;
|
||||
border:10px solid; aspect-ratio:2;"></div>
|
||||
<div id="auto-border-box-ratio"
|
||||
style="box-sizing:border-box; width:120px; padding:10px;
|
||||
border:10px solid; aspect-ratio:auto 2;"></div>
|
||||
<div id="animated-ratio" style="width:120px;"></div>
|
||||
<img id="override-natural-ratio"
|
||||
style="display:block; width:120px; height:auto; aspect-ratio:1;"
|
||||
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='20'%3E%3C/svg%3E">
|
||||
<img id="use-natural-ratio"
|
||||
style="display:block; width:120px; height:auto; aspect-ratio:auto 1;"
|
||||
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='20'%3E%3C/svg%3E">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
ok(CSS.supports("aspect-ratio", "1 / 1"),
|
||||
"aspect-ratio accepts ratio syntax");
|
||||
ok(CSS.supports("aspect-ratio", "2"),
|
||||
"aspect-ratio accepts a ratio with an omitted denominator");
|
||||
ok(CSS.supports("aspect-ratio", "auto"),
|
||||
"aspect-ratio accepts auto");
|
||||
ok(CSS.supports("aspect-ratio", "auto 16 / 9"),
|
||||
"aspect-ratio accepts auto plus ratio");
|
||||
ok(CSS.supports("aspect-ratio", "16 / 9 auto"),
|
||||
"aspect-ratio accepts ratio plus auto");
|
||||
ok(CSS.supports("aspect-ratio", "calc(1 + 1)"),
|
||||
"aspect-ratio accepts math functions as numbers");
|
||||
ok(CSS.supports("aspect-ratio", "0 / 1"),
|
||||
"aspect-ratio accepts degenerate ratios");
|
||||
ok(!CSS.supports("aspect-ratio", "1px"),
|
||||
"aspect-ratio rejects lengths");
|
||||
ok(!CSS.supports("aspect-ratio", "-1"),
|
||||
"aspect-ratio rejects negative numbers");
|
||||
ok(!CSS.supports("aspect-ratio", "auto auto"),
|
||||
"aspect-ratio rejects duplicate auto keywords");
|
||||
|
||||
var ratio = document.getElementById("ratio");
|
||||
is(ratio.getBoundingClientRect().height, 80,
|
||||
"aspect-ratio computes an automatic block size from inline size");
|
||||
is(getComputedStyle(ratio).aspectRatio, "3 / 2",
|
||||
"computed aspect-ratio preserves both ratio components");
|
||||
|
||||
var bareRatio = document.getElementById("bare-ratio");
|
||||
is(bareRatio.getBoundingClientRect().height, 60,
|
||||
"a bare number computes an automatic block size");
|
||||
is(getComputedStyle(bareRatio).aspectRatio, "2 / 1",
|
||||
"a ratio with an omitted denominator serializes with denominator 1");
|
||||
|
||||
var wrapper = document.getElementById("wrapper");
|
||||
is(wrapper.getBoundingClientRect().height, 120,
|
||||
@@ -35,6 +82,66 @@ is(wrapper.getBoundingClientRect().height, 120,
|
||||
is(getComputedStyle(wrapper).aspectRatio, "1 / 1",
|
||||
"computed aspect-ratio exposes a ratio value");
|
||||
|
||||
var zeroRatio = document.getElementById("zero-ratio");
|
||||
is(zeroRatio.getBoundingClientRect().height, 0,
|
||||
"a degenerate ratio behaves as auto during layout");
|
||||
is(getComputedStyle(zeroRatio).aspectRatio, "0 / 1",
|
||||
"a degenerate ratio remains a ratio in the computed value");
|
||||
|
||||
is(document.getElementById("border-box-ratio").getBoundingClientRect().height,
|
||||
60, "a specified ratio honors border-box sizing");
|
||||
is(document.getElementById("content-box-ratio").getBoundingClientRect().height,
|
||||
100, "a specified ratio honors content-box sizing");
|
||||
is(document.getElementById("auto-border-box-ratio")
|
||||
.getBoundingClientRect().height,
|
||||
80, "the fallback in auto plus ratio always uses the content box");
|
||||
|
||||
var animatedRatio = document.getElementById("animated-ratio");
|
||||
is(animatedRatio.getBoundingClientRect().height, 60,
|
||||
"aspect-ratio interpolation is logarithmic");
|
||||
is(getComputedStyle(animatedRatio).aspectRatio, "2 / 1",
|
||||
"an interpolated ratio is exposed as a pair of numbers");
|
||||
|
||||
var declaration = document.createElement("div").style;
|
||||
declaration.aspectRatio = "3 / 2 auto";
|
||||
is(declaration.aspectRatio, "auto 3 / 2",
|
||||
"specified aspect-ratio serializes in canonical order");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var images = [
|
||||
document.getElementById("override-natural-ratio"),
|
||||
document.getElementById("use-natural-ratio"),
|
||||
];
|
||||
var pendingImages = images.length;
|
||||
|
||||
function checkReplacedElements() {
|
||||
is(images[0].getBoundingClientRect().height, 120,
|
||||
"a ratio without auto overrides a replaced element's natural ratio");
|
||||
is(images[1].getBoundingClientRect().height, 60,
|
||||
"auto plus ratio uses a replaced element's natural ratio");
|
||||
is(getComputedStyle(images[1]).aspectRatio, "auto 1 / 1",
|
||||
"computed style preserves auto plus ratio");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function imageReady() {
|
||||
if (--pendingImages == 0) {
|
||||
checkReplacedElements();
|
||||
}
|
||||
}
|
||||
|
||||
images.forEach(function(image) {
|
||||
if (image.complete) {
|
||||
imageReady();
|
||||
} else {
|
||||
image.addEventListener("load", imageReady);
|
||||
image.addEventListener("error", function() {
|
||||
ok(false, "test image should load");
|
||||
imageReady();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
@@ -33,6 +33,31 @@ if (sheet) {
|
||||
|
||||
sheet.deleteRule(0);
|
||||
is(sheet.cssRules.length, 0, "deleteRule should remove the rule");
|
||||
|
||||
is(sheet.replaceSync("#test { color: rgb(4, 5, 6); } p { margin-top: 1px; }"),
|
||||
undefined, "replaceSync should return undefined");
|
||||
is(sheet.cssRules.length, 2, "replaceSync should replace with parsed rules");
|
||||
is(sheet.cssRules[0].selectorText, "#test",
|
||||
"replaceSync should expose the first parsed rule");
|
||||
is(sheet.cssRules[1].selectorText, "p",
|
||||
"replaceSync should expose subsequent parsed rules");
|
||||
|
||||
sheet.replaceSync("@import url('neverending_stylesheet_load.sjs'); #test { color: rgb(7, 8, 9); }");
|
||||
is(sheet.cssRules.length, 1, "replaceSync should remove @import rules");
|
||||
is(sheet.cssRules[0].selectorText, "#test",
|
||||
"replaceSync should keep non-import rules after removed imports");
|
||||
|
||||
sheet.replaceSync("}");
|
||||
is(sheet.cssRules.length, 0,
|
||||
"replaceSync should replace with an empty rule list when nothing parses");
|
||||
|
||||
try {
|
||||
document.styleSheets[0].replaceSync("#test { color: rgb(10, 11, 12); }");
|
||||
ok(false, "replaceSync should throw for non-constructed sheets");
|
||||
} catch (e) {
|
||||
is(e.name, "NotAllowedError",
|
||||
"replaceSync should reject non-constructed sheets with NotAllowedError");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -344,7 +344,7 @@ nsSVGOuterSVGFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
||||
}
|
||||
|
||||
return ComputeSizeWithIntrinsicDimensions(aRenderingContext, aWM,
|
||||
intrinsicSize, GetIntrinsicRatio(),
|
||||
intrinsicSize, GetAspectRatio(),
|
||||
cbSize, aMargin, aBorder, aPadding,
|
||||
aFlags);
|
||||
}
|
||||
|
||||
@@ -1358,12 +1358,6 @@ pref("network.notify.IPv6", false);
|
||||
pref("network.notify.IPv6", true);
|
||||
#endif
|
||||
|
||||
// Transmit UDP busy-work to the LAN when anticipating low latency
|
||||
// network reads and on wifi to mitigate 802.11 Power Save Polling delays
|
||||
pref("network.tickle-wifi.enabled", false);
|
||||
pref("network.tickle-wifi.duration", 400);
|
||||
pref("network.tickle-wifi.delay", 16);
|
||||
|
||||
// Turn off interprocess security checks. Needed to run xpcshell tests.
|
||||
pref("network.disable.ipc.security", false);
|
||||
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Tickler.h"
|
||||
|
||||
#ifdef MOZ_USE_WIFI_TICKLER
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prnetdb.h"
|
||||
|
||||
#include "mozilla/jni/Utils.h"
|
||||
#include "GeneratedJNIWrappers.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS(Tickler, nsISupportsWeakReference, Tickler)
|
||||
|
||||
Tickler::Tickler()
|
||||
: mLock("Tickler::mLock")
|
||||
, mActive(false)
|
||||
, mCanceled(false)
|
||||
, mEnabled(false)
|
||||
, mDelay(16)
|
||||
, mDuration(TimeDuration::FromMilliseconds(400))
|
||||
, mFD(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
Tickler::~Tickler()
|
||||
{
|
||||
// non main thread uses of the tickler should hold weak
|
||||
// references to it if they must hold a reference at all
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mThread) {
|
||||
mThread->AsyncShutdown();
|
||||
mThread = nullptr;
|
||||
}
|
||||
|
||||
if (mTimer)
|
||||
mTimer->Cancel();
|
||||
if (mFD)
|
||||
PR_Close(mFD);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Tickler::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mTimer);
|
||||
MOZ_ASSERT(!mActive);
|
||||
MOZ_ASSERT(!mThread);
|
||||
MOZ_ASSERT(!mFD);
|
||||
|
||||
if (jni::IsAvailable()) {
|
||||
java::GeckoAppShell::EnableNetworkNotifications();
|
||||
}
|
||||
|
||||
mFD = PR_OpenUDPSocket(PR_AF_INET);
|
||||
if (!mFD)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// make sure new socket has a ttl of 1
|
||||
// failure is not fatal.
|
||||
PRSocketOptionData opt;
|
||||
opt.option = PR_SockOpt_IpTimeToLive;
|
||||
opt.value.ip_ttl = 1;
|
||||
PR_SetSocketOption(mFD, &opt);
|
||||
|
||||
nsresult rv = NS_NewNamedThread("wifi tickler",
|
||||
getter_AddRefs(mThread));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsITimer> tmpTimer(do_CreateInstance(NS_TIMER_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = tmpTimer->SetTarget(mThread);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mTimer.swap(tmpTimer);
|
||||
|
||||
mAddr.inet.family = PR_AF_INET;
|
||||
mAddr.inet.port = PR_htons (4886);
|
||||
mAddr.inet.ip = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void Tickler::Tickle()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MOZ_ASSERT(mThread);
|
||||
mLastTickle = TimeStamp::Now();
|
||||
if (!mActive)
|
||||
MaybeStartTickler();
|
||||
}
|
||||
|
||||
void Tickler::PostCheckTickler()
|
||||
{
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
mThread->Dispatch(NewRunnableMethod(this, &Tickler::CheckTickler),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
void Tickler::MaybeStartTicklerUnlocked()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MaybeStartTickler();
|
||||
}
|
||||
|
||||
void Tickler::MaybeStartTickler()
|
||||
{
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(
|
||||
NewRunnableMethod(this, &Tickler::MaybeStartTicklerUnlocked));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mPrefs)
|
||||
mPrefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (mPrefs) {
|
||||
int32_t val;
|
||||
bool boolVal;
|
||||
|
||||
if (NS_SUCCEEDED(mPrefs->GetBoolPref("network.tickle-wifi.enabled", &boolVal)))
|
||||
mEnabled = boolVal;
|
||||
|
||||
if (NS_SUCCEEDED(mPrefs->GetIntPref("network.tickle-wifi.duration", &val))) {
|
||||
if (val < 1)
|
||||
val = 1;
|
||||
if (val > 100000)
|
||||
val = 100000;
|
||||
mDuration = TimeDuration::FromMilliseconds(val);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(mPrefs->GetIntPref("network.tickle-wifi.delay", &val))) {
|
||||
if (val < 1)
|
||||
val = 1;
|
||||
if (val > 1000)
|
||||
val = 1000;
|
||||
mDelay = static_cast<uint32_t>(val);
|
||||
}
|
||||
}
|
||||
|
||||
PostCheckTickler();
|
||||
}
|
||||
|
||||
void Tickler::CheckTickler()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MOZ_ASSERT(mThread == NS_GetCurrentThread());
|
||||
|
||||
bool shouldRun = (!mCanceled) &&
|
||||
((TimeStamp::Now() - mLastTickle) <= mDuration);
|
||||
|
||||
if ((shouldRun && mActive) || (!shouldRun && !mActive))
|
||||
return; // no change in state
|
||||
|
||||
if (mActive)
|
||||
StopTickler();
|
||||
else
|
||||
StartTickler();
|
||||
}
|
||||
|
||||
void Tickler::Cancel()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mCanceled = true;
|
||||
if (mThread)
|
||||
PostCheckTickler();
|
||||
}
|
||||
|
||||
void Tickler::StopTickler()
|
||||
{
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(mThread == NS_GetCurrentThread());
|
||||
MOZ_ASSERT(mTimer);
|
||||
MOZ_ASSERT(mActive);
|
||||
|
||||
mTimer->Cancel();
|
||||
mActive = false;
|
||||
}
|
||||
|
||||
class TicklerTimer final : public nsITimerCallback
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
TicklerTimer(Tickler *aTickler)
|
||||
{
|
||||
mTickler = do_GetWeakReference(aTickler);
|
||||
}
|
||||
|
||||
private:
|
||||
~TicklerTimer() {}
|
||||
|
||||
nsWeakPtr mTickler;
|
||||
};
|
||||
|
||||
void Tickler::StartTickler()
|
||||
{
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(mThread == NS_GetCurrentThread());
|
||||
MOZ_ASSERT(!mActive);
|
||||
MOZ_ASSERT(mTimer);
|
||||
|
||||
if (NS_SUCCEEDED(mTimer->InitWithCallback(new TicklerTimer(this),
|
||||
mEnabled ? mDelay : 1000,
|
||||
nsITimer::TYPE_REPEATING_SLACK)))
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
// argument should be in network byte order
|
||||
void Tickler::SetIPV4Address(uint32_t address)
|
||||
{
|
||||
mAddr.inet.ip = address;
|
||||
}
|
||||
|
||||
// argument should be in network byte order
|
||||
void Tickler::SetIPV4Port(uint16_t port)
|
||||
{
|
||||
mAddr.inet.port = port;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(TicklerTimer, nsITimerCallback)
|
||||
|
||||
NS_IMETHODIMP TicklerTimer::Notify(nsITimer *timer)
|
||||
{
|
||||
RefPtr<Tickler> tickler = do_QueryReferent(mTickler);
|
||||
if (!tickler)
|
||||
return NS_ERROR_FAILURE;
|
||||
MutexAutoLock lock(tickler->mLock);
|
||||
|
||||
if (!tickler->mFD) {
|
||||
tickler->StopTickler();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (tickler->mCanceled ||
|
||||
((TimeStamp::Now() - tickler->mLastTickle) > tickler->mDuration)) {
|
||||
tickler->StopTickler();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!tickler->mEnabled)
|
||||
return NS_OK;
|
||||
|
||||
PR_SendTo(tickler->mFD, "", 0, 0, &tickler->mAddr, 0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla::net
|
||||
} // namespace mozilla
|
||||
|
||||
#else // not defined MOZ_USE_WIFI_TICKLER
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
NS_IMPL_ISUPPORTS0(Tickler)
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // defined MOZ_USE_WIFI_TICKLER
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_net_Tickler_h
|
||||
#define mozilla_net_Tickler_h
|
||||
|
||||
// The tickler sends a regular 0 byte UDP heartbeat out to a
|
||||
// particular address for a short time after it has been touched. This
|
||||
// is used on some mobile wifi chipsets to mitigate Power Save Polling
|
||||
// (PSP) Mode when we are anticipating a response packet
|
||||
// soon. Typically PSP adds 100ms of latency to a read event because
|
||||
// the packet delivery is not triggered until the 802.11 beacon is
|
||||
// delivered to the host (100ms is the standard Access Point
|
||||
// configuration for the beacon interval.) Requesting a frequent
|
||||
// transmission and getting a CTS frame from the AP at least that
|
||||
// frequently allows for low latency receives when we have reason to
|
||||
// expect them (e.g a SYN-ACK).
|
||||
//
|
||||
// The tickler is used to allow RTT based phases of web transport to
|
||||
// complete quickly when on wifi - ARP, DNS, TCP handshake, SSL
|
||||
// handshake, HTTP headers, and the TCP slow start phase. The
|
||||
// transaction is given up to 400 miliseconds by default to get
|
||||
// through those phases before the tickler is disabled.
|
||||
//
|
||||
// The tickler only applies to wifi on mobile right now. Hopefully it
|
||||
// can also be restricted to particular handset models in the future.
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsISupports.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef MOZ_USE_WIFI_TICKLER
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "prio.h"
|
||||
|
||||
class nsIPrefBranch;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
#ifdef MOZ_USE_WIFI_TICKLER
|
||||
|
||||
// 8f769ed6-207c-4af9-9f7e-9e832da3754e
|
||||
#define NS_TICKLER_IID \
|
||||
{ 0x8f769ed6, 0x207c, 0x4af9, \
|
||||
{ 0x9f, 0x7e, 0x9e, 0x83, 0x2d, 0xa3, 0x75, 0x4e } }
|
||||
|
||||
class Tickler final : public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_TICKLER_IID)
|
||||
|
||||
// These methods are main thread only
|
||||
Tickler();
|
||||
void Cancel();
|
||||
nsresult Init();
|
||||
void SetIPV4Address(uint32_t address);
|
||||
void SetIPV4Port(uint16_t port);
|
||||
|
||||
// Tickle the tickler to (re-)start the activity.
|
||||
// May call from any thread
|
||||
void Tickle();
|
||||
|
||||
private:
|
||||
~Tickler();
|
||||
|
||||
friend class TicklerTimer;
|
||||
Mutex mLock;
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsIPrefBranch> mPrefs;
|
||||
|
||||
bool mActive;
|
||||
bool mCanceled;
|
||||
bool mEnabled;
|
||||
uint32_t mDelay;
|
||||
TimeDuration mDuration;
|
||||
PRFileDesc* mFD;
|
||||
|
||||
TimeStamp mLastTickle;
|
||||
PRNetAddr mAddr;
|
||||
|
||||
// These functions may be called from any thread
|
||||
void PostCheckTickler();
|
||||
void MaybeStartTickler();
|
||||
void MaybeStartTicklerUnlocked();
|
||||
|
||||
// Tickler thread only
|
||||
void CheckTickler();
|
||||
void StartTickler();
|
||||
void StopTickler();
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(Tickler, NS_TICKLER_IID)
|
||||
|
||||
#else // not defined MOZ_USE_WIFI_TICKLER
|
||||
|
||||
class Tickler final : public nsISupports
|
||||
{
|
||||
~Tickler() { }
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
Tickler() { }
|
||||
nsresult Init() { return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
void Cancel() { }
|
||||
void SetIPV4Address(uint32_t) { };
|
||||
void SetIPV4Port(uint16_t) { }
|
||||
void Tickle() { }
|
||||
};
|
||||
|
||||
#endif // defined MOZ_USE_WIFI_TICKLER
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_Tickler_h
|
||||
@@ -245,7 +245,6 @@ UNIFIED_SOURCES += [
|
||||
'SimpleBuffer.cpp',
|
||||
'StreamingProtocolService.cpp',
|
||||
'ThrottleQueue.cpp',
|
||||
'Tickler.cpp',
|
||||
'TLSServerSocket.cpp',
|
||||
]
|
||||
|
||||
|
||||
@@ -481,7 +481,12 @@ NS_IMETHODIMP CacheEntry::OnFileReady(nsresult aResult, bool aIsNew)
|
||||
|
||||
NS_IMETHODIMP CacheEntry::OnFileDoomed(nsresult aResult)
|
||||
{
|
||||
if (mDoomCallback) {
|
||||
bool doomCallback = false;
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
doomCallback = bool(mDoomCallback);
|
||||
}
|
||||
if (doomCallback) {
|
||||
RefPtr<DoomCallbackRunnable> event =
|
||||
new DoomCallbackRunnable(this, aResult);
|
||||
NS_DispatchToMainThread(event);
|
||||
@@ -1738,8 +1743,13 @@ void CacheEntry::DoomFile()
|
||||
}
|
||||
}
|
||||
|
||||
// Always posts to the main thread.
|
||||
OnFileDoomed(rv);
|
||||
// mLock is already held in the caller; dispatch directly
|
||||
// instead of calling OnFileDoomed() which would deadlock when
|
||||
// re-acquiring the lock.
|
||||
if (mDoomCallback) {
|
||||
RefPtr<DoomCallbackRunnable> event = new DoomCallbackRunnable(this, rv);
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
}
|
||||
|
||||
void CacheEntry::RemoveForcedValidity()
|
||||
|
||||
@@ -29,9 +29,6 @@ uint32_t CacheObserver::sUseNewCache = kDefaultUseNewCache;
|
||||
static int32_t const kAutoDeleteCacheVersion = -1; // Auto-delete off by default
|
||||
static int32_t sAutoDeleteCacheVersion = kAutoDeleteCacheVersion;
|
||||
|
||||
static int32_t const kDefaultHalfLifeExperiment = -1; // Disabled
|
||||
int32_t CacheObserver::sHalfLifeExperiment = kDefaultHalfLifeExperiment;
|
||||
|
||||
static float const kDefaultHalfLifeHours = 1.0F; // 1 hour
|
||||
float CacheObserver::sHalfLifeHours = kDefaultHalfLifeHours;
|
||||
|
||||
@@ -189,51 +186,8 @@ CacheObserver::AttachToPreferences()
|
||||
"browser.cache.disk.parent_directory", NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mCacheParentDirectoryOverride));
|
||||
|
||||
// First check the default value. If it is at -1, the experient
|
||||
// is turned off. If it is at 0, then use the user pref value
|
||||
// instead.
|
||||
sHalfLifeExperiment = mozilla::Preferences::GetDefaultInt(
|
||||
"browser.cache.frecency_experiment", kDefaultHalfLifeExperiment);
|
||||
|
||||
if (sHalfLifeExperiment == 0) {
|
||||
// Default preferences indicate we want to run the experiment,
|
||||
// hence read the user value.
|
||||
sHalfLifeExperiment = mozilla::Preferences::GetInt(
|
||||
"browser.cache.frecency_experiment", sHalfLifeExperiment);
|
||||
}
|
||||
|
||||
if (sHalfLifeExperiment == 0) {
|
||||
// The experiment has not yet been initialized but is engaged, do
|
||||
// the initialization now.
|
||||
srand(time(NULL));
|
||||
sHalfLifeExperiment = (rand() % 4) + 1;
|
||||
// Store the experiemnt value, since we need it not to change between
|
||||
// browser sessions.
|
||||
mozilla::Preferences::SetInt(
|
||||
"browser.cache.frecency_experiment", sHalfLifeExperiment);
|
||||
}
|
||||
|
||||
switch (sHalfLifeExperiment) {
|
||||
case 1: // The experiment is engaged
|
||||
sHalfLifeHours = 0.083F; // ~5 mintues
|
||||
break;
|
||||
case 2:
|
||||
sHalfLifeHours = 0.25F; // 15 mintues
|
||||
break;
|
||||
case 3:
|
||||
sHalfLifeHours = 1.0F;
|
||||
break;
|
||||
case 4:
|
||||
sHalfLifeHours = 6.0F;
|
||||
break;
|
||||
|
||||
case -1:
|
||||
default: // The experiment is off or broken
|
||||
sHalfLifeExperiment = -1;
|
||||
sHalfLifeHours = std::max(0.01F, std::min(1440.0F, mozilla::Preferences::GetFloat(
|
||||
"browser.cache.frecency_half_life_hours", kDefaultHalfLifeHours)));
|
||||
break;
|
||||
}
|
||||
sHalfLifeHours = std::max(0.01F, std::min(1440.0F, mozilla::Preferences::GetFloat(
|
||||
"browser.cache.frecency_half_life_hours", kDefaultHalfLifeHours)));
|
||||
|
||||
mozilla::Preferences::AddBoolVarCache(
|
||||
&sSanitizeOnShutdown, "privacy.sanitize.sanitizeOnShutdown", kDefaultSanitizeOnShutdown);
|
||||
|
||||
@@ -57,8 +57,6 @@ class CacheObserver : public nsIObserver
|
||||
{ return sCompressionLevel; }
|
||||
static uint32_t HalfLifeSeconds()
|
||||
{ return sHalfLifeHours * 60.0F * 60.0F; }
|
||||
static int32_t HalfLifeExperiment()
|
||||
{ return sHalfLifeExperiment; }
|
||||
static bool ClearCacheOnShutdown()
|
||||
{ return sSanitizeOnShutdown && sClearCacheOnShutdown; }
|
||||
static void ParentDirOverride(nsIFile ** aDir);
|
||||
@@ -95,7 +93,6 @@ private:
|
||||
static uint32_t sMaxDiskPriorityChunksMemoryUsage;
|
||||
static uint32_t sCompressionLevel;
|
||||
static float sHalfLifeHours;
|
||||
static int32_t sHalfLifeExperiment;
|
||||
static bool sSanitizeOnShutdown;
|
||||
static bool sClearCacheOnShutdown;
|
||||
static Atomic<uint32_t, Relaxed> sMaxShutdownIOLag;
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "nsAlgorithm.h"
|
||||
#include "ASpdySession.h"
|
||||
#include "EventTokenBucket.h"
|
||||
#include "Tickler.h"
|
||||
#include "nsIXULAppInfo.h"
|
||||
#include "nsICookieService.h"
|
||||
#include "nsIObserverService.h"
|
||||
@@ -396,9 +395,6 @@ nsHttpHandler::Init()
|
||||
}
|
||||
|
||||
MakeNewRequestTokenBucket();
|
||||
mWifiTickler = new Tickler();
|
||||
if (NS_FAILED(mWifiTickler->Init()))
|
||||
mWifiTickler = nullptr;
|
||||
|
||||
nsCOMPtr<nsIParentalControlsService> pc = do_CreateInstance("@mozilla.org/parental-controls-service;1");
|
||||
if (pc) {
|
||||
@@ -2124,8 +2120,6 @@ nsHttpHandler::Observe(nsISupports *subject,
|
||||
// clear cache of all authentication credentials.
|
||||
mAuthCache.ClearAll();
|
||||
mPrivateAuthCache.ClearAll();
|
||||
if (mWifiTickler)
|
||||
mWifiTickler->Cancel();
|
||||
|
||||
// Inform nsIOService that network is tearing down.
|
||||
gIOService->SetHttpHandlerAlreadyShutingDown();
|
||||
@@ -2338,48 +2332,6 @@ nsHttpHandler::SpeculativeAnonymousConnect2(nsIURI *aURI,
|
||||
return SpeculativeConnectInternal(aURI, aPrincipal, aCallbacks, true);
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpHandler::TickleWifi(nsIInterfaceRequestor *cb)
|
||||
{
|
||||
if (!cb || !mWifiTickler)
|
||||
return;
|
||||
|
||||
// If B2G requires a similar mechanism nsINetworkManager, currently only avail
|
||||
// on B2G, contains the necessary information on wifi and gateway
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(cb);
|
||||
nsCOMPtr<nsPIDOMWindowOuter> piWindow = do_QueryInterface(domWindow);
|
||||
if (!piWindow)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMNavigator> domNavigator = piWindow->GetNavigator();
|
||||
nsCOMPtr<nsIMozNavigatorNetwork> networkNavigator =
|
||||
do_QueryInterface(domNavigator);
|
||||
if (!networkNavigator)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsINetworkProperties> networkProperties;
|
||||
networkNavigator->GetProperties(getter_AddRefs(networkProperties));
|
||||
if (!networkProperties)
|
||||
return;
|
||||
|
||||
uint32_t gwAddress;
|
||||
bool isWifi;
|
||||
nsresult rv;
|
||||
|
||||
rv = networkProperties->GetDhcpGateway(&gwAddress);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = networkProperties->GetIsWifi(&isWifi);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
if (!gwAddress || !isWifi)
|
||||
return;
|
||||
|
||||
mWifiTickler->SetIPV4Address(gwAddress);
|
||||
mWifiTickler->Tickle();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpsHandler implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -39,7 +39,6 @@ extern Atomic<PRThread*, Relaxed> gSocketThread;
|
||||
|
||||
class ATokenBucketEvent;
|
||||
class EventTokenBucket;
|
||||
class Tickler;
|
||||
class nsHttpConnection;
|
||||
class nsHttpConnectionInfo;
|
||||
class nsHttpTransaction;
|
||||
@@ -245,7 +244,6 @@ public:
|
||||
nsIInterfaceRequestor *callbacks,
|
||||
uint32_t caps = 0)
|
||||
{
|
||||
TickleWifi(callbacks);
|
||||
RefPtr<nsHttpConnectionInfo> clone = ci->Clone();
|
||||
return mConnMgr->SpeculativeConnect(clone, callbacks, caps);
|
||||
}
|
||||
@@ -645,10 +643,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<Tickler> mWifiTickler;
|
||||
void TickleWifi(nsIInterfaceRequestor *cb);
|
||||
|
||||
private:
|
||||
nsresult SpeculativeConnectInternal(nsIURI *aURI,
|
||||
nsIPrincipal *aPrincipal,
|
||||
|
||||
@@ -318,6 +318,14 @@ sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
|
||||
return;
|
||||
}
|
||||
SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn);
|
||||
if (gap >= (uint32_t)(asoc->mapping_array_size << 3)) {
|
||||
/*
|
||||
* The TSN falls outside the mapping window, e.g. a control
|
||||
* queued before a large FORWARD-TSN moved the window past it.
|
||||
* It has no bit in either map, so there is nothing to mark.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
in_r = SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap);
|
||||
in_nr = SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, gap);
|
||||
KASSERT(in_r || in_nr, ("%s: Things are really messed up now", __func__));
|
||||
|
||||
@@ -258,6 +258,8 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
|
||||
struct sctp_init *init;
|
||||
struct sctp_association *asoc;
|
||||
struct sctp_nets *lnet;
|
||||
struct sctp_stream_reset_list *strrst, *nstrrst;
|
||||
struct sctp_queued_to_read *sq, *nsq;
|
||||
unsigned int i;
|
||||
|
||||
SCTP_TCB_LOCK_ASSERT(stcb);
|
||||
@@ -358,6 +360,27 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
|
||||
asoc->advanced_peer_ack_point = asoc->last_acked_seq;
|
||||
/* open the requested streams */
|
||||
|
||||
/*
|
||||
* Flush inbound stream state carrying stream ids validated against the
|
||||
* old streamincnt before strmin is reallocated below; otherwise a later
|
||||
* drain of pending_reply_queue could index the new (smaller) strmin out
|
||||
* of bounds.
|
||||
*/
|
||||
TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
|
||||
TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
|
||||
SCTP_FREE(strrst, SCTP_M_STRESET);
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(sq, &asoc->pending_reply_queue, next, nsq) {
|
||||
TAILQ_REMOVE(&asoc->pending_reply_queue, sq, next);
|
||||
if (sq->data) {
|
||||
sctp_m_freem(sq->data);
|
||||
sq->data = NULL;
|
||||
}
|
||||
sctp_free_remote_addr(sq->whoFrom);
|
||||
sq->whoFrom = NULL;
|
||||
sq->stcb = NULL;
|
||||
sctp_free_a_readq(stcb, sq);
|
||||
}
|
||||
if (asoc->strmin != NULL) {
|
||||
/* Free the old ones */
|
||||
for (i = 0; i < asoc->streamincnt; i++) {
|
||||
@@ -1475,8 +1498,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
struct sctp_asconf_addr *aparam, *naparam;
|
||||
struct sctp_asconf_ack *aack, *naack;
|
||||
struct sctp_tmit_chunk *chk, *nchk;
|
||||
struct sctp_stream_reset_list *strrst, *nstrrst;
|
||||
struct sctp_queued_to_read *sq, *nsq;
|
||||
struct sctp_nets *net;
|
||||
struct mbuf *op_err;
|
||||
int init_offset, initack_offset, i;
|
||||
@@ -1989,21 +2010,10 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
|
||||
stcb->asoc.strmout[i].sid = i;
|
||||
stcb->asoc.strmout[i].last_msg_incomplete = 0;
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
|
||||
TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
|
||||
SCTP_FREE(strrst, SCTP_M_STRESET);
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(sq, &asoc->pending_reply_queue, next, nsq) {
|
||||
TAILQ_REMOVE(&asoc->pending_reply_queue, sq, next);
|
||||
if (sq->data) {
|
||||
sctp_m_freem(sq->data);
|
||||
sq->data = NULL;
|
||||
}
|
||||
sctp_free_remote_addr(sq->whoFrom);
|
||||
sq->whoFrom = NULL;
|
||||
sq->stcb = NULL;
|
||||
sctp_free_a_readq(stcb, sq);
|
||||
}
|
||||
/*
|
||||
* resetHead and pending_reply_queue are flushed by
|
||||
* sctp_process_init() below, where strmin is reallocated.
|
||||
*/
|
||||
TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
|
||||
TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
|
||||
if (chk->data) {
|
||||
|
||||
@@ -690,6 +690,9 @@ nsHtml5TreeOperation::CreateMathMLElement(nsIAtom* aName,
|
||||
void
|
||||
nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, nsIContent* aParent)
|
||||
{
|
||||
if (aNode->SubtreeRoot() != aParent->SubtreeRoot()) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode));
|
||||
nsCOMPtr<nsIDOMHTMLImageElement> domImageElement = do_QueryInterface(aNode);
|
||||
// NS_ASSERTION(formControl, "Form-associated element did not implement nsIFormControl.");
|
||||
@@ -704,7 +707,9 @@ nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, nsIContent* aParent)
|
||||
RefPtr<dom::HTMLImageElement> imageElement =
|
||||
static_cast<dom::HTMLImageElement*>(domImageElement.get());
|
||||
MOZ_ASSERT(imageElement);
|
||||
imageElement->SetForm(formElement);
|
||||
if (!imageElement->GetForm()) {
|
||||
imageElement->SetForm(formElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "secasn1.h"
|
||||
#include "secitem.h"
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include "secerr.h"
|
||||
#include "certi.h"
|
||||
|
||||
@@ -652,9 +653,18 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue)
|
||||
}
|
||||
|
||||
if (convert != conv_none) {
|
||||
if (avaValue.len > UINT_MAX / 3) {
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
PORT_SetError(SEC_ERROR_INVALID_AVA);
|
||||
return NULL;
|
||||
}
|
||||
unsigned int utf8ValLen = avaValue.len * 3;
|
||||
unsigned char *utf8Val =
|
||||
(unsigned char *)PORT_ArenaZAlloc(&tmpArena.arena, utf8ValLen);
|
||||
if (!utf8Val) {
|
||||
PORT_DestroyCheapArena(&tmpArena);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (convert) {
|
||||
case conv_ucs4:
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* certhtml.c --- convert a cert to html
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "secitem.h"
|
||||
#include "sechash.h"
|
||||
@@ -14,6 +16,7 @@
|
||||
#include "secder.h"
|
||||
#include "prprf.h"
|
||||
#include "secport.h"
|
||||
#include "secerr.h"
|
||||
#include "secasn1.h"
|
||||
#include "pk11func.h"
|
||||
|
||||
@@ -32,6 +35,11 @@ CERT_Hexify(SECItem *i, int do_colon)
|
||||
return PORT_Strdup("00");
|
||||
}
|
||||
|
||||
if (i->len > UINT_MAX / 3) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv = o = (char *)PORT_Alloc(i->len * 3);
|
||||
if (!rv)
|
||||
return rv;
|
||||
|
||||
@@ -696,6 +696,13 @@ SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
|
||||
/* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
|
||||
* followed by the length of the curve oid and the curve oid.
|
||||
*/
|
||||
if (!encodedParams || !encodedParams->data ||
|
||||
encodedParams->len < 2 ||
|
||||
encodedParams->data[0] != SEC_ASN1_OBJECT_ID ||
|
||||
(unsigned)encodedParams->data[1] > encodedParams->len - 2) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DER);
|
||||
return 0;
|
||||
}
|
||||
oid.len = encodedParams->data[1];
|
||||
oid.data = encodedParams->data + 2;
|
||||
if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
|
||||
|
||||
@@ -248,6 +248,11 @@ nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
|
||||
/* default to PKIX */
|
||||
return NSSCertificateType_PKIX;
|
||||
}
|
||||
/* The token controls ulValueLen; reject any size that cannot hold a
|
||||
* full CK_CERTIFICATE_TYPE to avoid an out-of-bounds heap read. */
|
||||
if (attrib->ulValueLen != sizeof(CK_CERTIFICATE_TYPE)) {
|
||||
return NSSCertificateType_Unknown;
|
||||
}
|
||||
ckCertType = *((CK_ULONG *)attrib->pValue);
|
||||
switch (ckCertType) {
|
||||
case CKC_X_509:
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define NSS_VERSION "3.90.12.0 (UXP)" _NSS_CUSTOMIZED
|
||||
#define NSS_VERSION "3.90.13.0 (UXP)" _NSS_CUSTOMIZED
|
||||
#define NSS_VMAJOR 3
|
||||
#define NSS_VMINOR 90
|
||||
#define NSS_VPATCH 12
|
||||
#define NSS_VPATCH 13
|
||||
#define NSS_VBUILD 0
|
||||
#define NSS_BETA PR_FALSE
|
||||
|
||||
|
||||
@@ -2269,11 +2269,20 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot,
|
||||
NSSCertificate **certs;
|
||||
nssList *nameList = NULL;
|
||||
nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
|
||||
if (!nickname || !nickname->data || nickname->len == 0) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
token = PK11Slot_GetNSSToken(slot);
|
||||
if (!token || !nssToken_IsPresent(token)) {
|
||||
(void)nssToken_Destroy(token);
|
||||
return SECSuccess;
|
||||
}
|
||||
if (!nickname || !nickname->data || nickname->len == 0) {
|
||||
(void)nssToken_Destroy(token);
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
if (nickname->data[nickname->len - 1] != '\0') {
|
||||
nick = nssUTF8_Create(NULL, nssStringType_UTF8String,
|
||||
nickname->data, nickname->len);
|
||||
|
||||
@@ -521,7 +521,7 @@ pk11_mergeSecretKey(PK11SlotInfo *targetSlot, PK11SlotInfo *sourceSlot,
|
||||
goto done;
|
||||
}
|
||||
input.len = blockSize;
|
||||
if (input.len == 0) {
|
||||
if (input.len == 0 || input.len > sizeof(testString)) {
|
||||
input.len = sizeof(testString);
|
||||
}
|
||||
while (targetKeyID != CK_INVALID_HANDLE) {
|
||||
|
||||
@@ -1214,6 +1214,12 @@ PK11_UnwrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (usageCount < 0 ||
|
||||
usageCount > (int)(PR_ARRAY_SIZE(keyTemplate) - 8)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ck_id = PK11_MakeIDFromPubKey(idValue);
|
||||
if (!ck_id) {
|
||||
return NULL;
|
||||
|
||||
@@ -371,7 +371,10 @@ PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type,
|
||||
CK_OBJECT_HANDLE keyHandle;
|
||||
|
||||
PK11_EnterSlotMonitor(slot);
|
||||
if (slot->series != series ||
|
||||
/* refKeys is a fixed-size array; bounds-check wrap to match
|
||||
* PK11_SetWrapKey. */
|
||||
if (wrap < 0 || (size_t)wrap >= PR_ARRAY_SIZE(slot->refKeys) ||
|
||||
slot->series != series ||
|
||||
slot->refKeys[wrap] == CK_INVALID_HANDLE) {
|
||||
PK11_ExitSlotMonitor(slot);
|
||||
return NULL;
|
||||
|
||||
@@ -162,6 +162,7 @@ pk11_FreeSlotListStatic(PK11SlotList *list)
|
||||
}
|
||||
list->lock = NULL;
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -820,6 +821,7 @@ pk11_InitSlotListStatic(PK11SlotList *list)
|
||||
{
|
||||
list->lock = PZ_NewLock(nssILockList);
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
}
|
||||
|
||||
/* initialize the system slotlists */
|
||||
|
||||
@@ -1105,7 +1105,7 @@ p12u_DigestClose(void *arg, PRBool removeFile)
|
||||
static int
|
||||
p12u_DigestRead(void *arg, unsigned char *buf, unsigned long len)
|
||||
{
|
||||
int toread = len;
|
||||
int toread;
|
||||
SEC_PKCS12DecoderContext *p12cxt = arg;
|
||||
|
||||
if (!buf || len == 0 || !p12cxt->buffer) {
|
||||
@@ -1113,10 +1113,16 @@ p12u_DigestRead(void *arg, unsigned char *buf, unsigned long len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((p12cxt->filesize - p12cxt->currentpos) < (long)len) {
|
||||
/* trying to read past the end of the buffer */
|
||||
toread = p12cxt->filesize - p12cxt->currentpos;
|
||||
/* Clamp `len` to the bytes left in the buffer. toread is positive here,
|
||||
* so the comparison stays unsigned and `len` cannot wrap. */
|
||||
toread = p12cxt->filesize - p12cxt->currentpos;
|
||||
if (toread <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (len < (unsigned long)toread) {
|
||||
toread = (int)len;
|
||||
}
|
||||
|
||||
memcpy(buf, (char *)p12cxt->buffer + p12cxt->currentpos, toread);
|
||||
p12cxt->currentpos += toread;
|
||||
return toread;
|
||||
@@ -1131,10 +1137,18 @@ p12u_DigestWrite(void *arg, unsigned char *buf, unsigned long len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p12cxt->currentpos + (long)len > p12cxt->filesize) {
|
||||
p12cxt->filesize = p12cxt->currentpos + len;
|
||||
/* The buffer position counters are signed PRInt32. Reject any write
|
||||
* whose length would not fit so that `len` cannot overflow or wrap them
|
||||
* on LLP64 platforms where unsigned long is 32-bit (Win64). */
|
||||
if (len > (unsigned long)(PR_INT32_MAX - p12cxt->currentpos)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p12cxt->currentpos + (PRInt32)len > p12cxt->filesize) {
|
||||
p12cxt->filesize = p12cxt->currentpos + (PRInt32)len;
|
||||
} else {
|
||||
p12cxt->filesize += len;
|
||||
p12cxt->filesize += (PRInt32)len;
|
||||
}
|
||||
if (p12cxt->filesize > p12cxt->allocated) {
|
||||
void *newbuffer;
|
||||
@@ -1693,6 +1707,13 @@ sec_pkcs12_sanitize_nickname(PK11SlotInfo *slot, SECItem *nick)
|
||||
slotName[slotNameLen] = '\0';
|
||||
if (PORT_Strcmp(PK11_GetTokenName(slot), slotName) == 0) {
|
||||
delimitlen = PORT_Strlen(delimit + 1);
|
||||
if (delimitlen == 0) {
|
||||
/* Nickname was exactly "TokenName:" with nothing after the
|
||||
* prefix. Stripping it would yield an empty SECItem, which
|
||||
* is not a useful nickname; leave the original in place. */
|
||||
PORT_Free(slotName);
|
||||
return;
|
||||
}
|
||||
PORT_Memmove(nickname, delimit + 1, delimitlen + 1);
|
||||
nick->len = delimitlen;
|
||||
}
|
||||
|
||||
@@ -606,15 +606,20 @@ SEC_PKCS7DecryptContents(PLArenaPool *poolp,
|
||||
rv = PK11_CipherOp((PK11Context *)cx, dest->data, (int *)(&dest->len),
|
||||
(int)(src->len + 64), src->data, (int)src->len);
|
||||
PK11_DestroyContext((PK11Context *)cx, PR_TRUE);
|
||||
/* PK11_CipherOp may leave dest->len at 0; bail out before the padding
|
||||
* check so dest->len - 1 does not underflow. */
|
||||
if (rv != SECSuccess) {
|
||||
goto loser;
|
||||
}
|
||||
|
||||
bs = PK11_GetBlockSize(cryptoMechType, c_param);
|
||||
if (bs) {
|
||||
/* check for proper badding in block algorithms. this assumes
|
||||
* RC2 cbc or a DES cbc variant. and the padding is thus defined
|
||||
*/
|
||||
if (((int)dest->data[dest->len - 1] <= bs) &&
|
||||
((int)dest->data[dest->len - 1] > 0)) {
|
||||
dest->len -= (int)dest->data[dest->len - 1];
|
||||
/* Check for proper PKCS#7 padding: the last byte gives the number of
|
||||
* pad bytes, which must be in [1, bs]. */
|
||||
unsigned int pad = dest->data[dest->len - 1];
|
||||
if ((dest->len >= (unsigned int)bs) &&
|
||||
pad >= 1 && pad <= (unsigned int)bs) {
|
||||
dest->len -= pad;
|
||||
} else {
|
||||
rv = SECFailure;
|
||||
/* set an error ? */
|
||||
|
||||
@@ -773,6 +773,12 @@ sftk_ike1_appendix_b_prf(CK_SESSION_HANDLE hSession, const SFTKAttribute *inKey,
|
||||
}
|
||||
|
||||
outKeySize = PR_ROUNDUP(keySize, macSize);
|
||||
/* Reject if PR_ROUNDUP overflowed 32-bit unsigned arithmetic, which
|
||||
* would yield an undersized allocation for the loop below. */
|
||||
if (outKeySize < keySize) {
|
||||
crv = CKR_KEY_SIZE_RANGE;
|
||||
goto fail;
|
||||
}
|
||||
outKeyData = PORT_Alloc(outKeySize);
|
||||
if (outKeyData == NULL) {
|
||||
crv = CKR_HOST_MEMORY;
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define SOFTOKEN_VERSION "3.90.12.0 (UXP)" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VERSION "3.90.13.0 (UXP)" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 90
|
||||
#define SOFTOKEN_VPATCH 12
|
||||
#define SOFTOKEN_VPATCH 13
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
|
||||
|
||||
@@ -722,7 +722,12 @@ ssl_CallCustomExtensionSenders(sslSocket *ss, sslBuffer *buf,
|
||||
if (hook->writer) {
|
||||
/* The writer writes directly into |buf|. Provide space that allows
|
||||
* for the existing extensions, any tail, plus type and length. */
|
||||
unsigned int space = buf->space - (buf->len + tail.len + 4);
|
||||
unsigned int used = buf->len + tail.len + 4;
|
||||
if (used > buf->space) {
|
||||
PORT_SetError(SEC_ERROR_APPLICATION_CALLBACK_ERROR);
|
||||
goto loser;
|
||||
}
|
||||
unsigned int space = buf->space - used;
|
||||
append = (*hook->writer)(ss->fd, message,
|
||||
buf->buf + buf->len + 4, &len, space,
|
||||
hook->writerArg);
|
||||
|
||||
@@ -164,6 +164,12 @@ ssl_BeginClientHandshake(sslSocket *ss)
|
||||
ss->sec.localCert = CERT_DupCertificate(sid->localCert);
|
||||
} else {
|
||||
ssl_UncacheSessionID(ss);
|
||||
if (ss->sec.ci.sid == sid) {
|
||||
/* sid aliases ss->sec.ci.sid (external cache); clear it so
|
||||
* the socket cannot hold a dangling pointer if the
|
||||
* ssl3_NewSessionID allocation below fails. */
|
||||
ss->sec.ci.sid = NULL;
|
||||
}
|
||||
ssl_FreeSID(sid);
|
||||
sid = NULL;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ tls13_HkdfExpandLabelGeneral(CK_MECHANISM_TYPE deriveMech, PK11SymKey *prk,
|
||||
PORT_Assert(keyp);
|
||||
if ((handshakeHashLen > 255) ||
|
||||
(handshakeHash == NULL && handshakeHashLen > 0) ||
|
||||
(labelLen + kLabelPrefixLen > 255)) {
|
||||
(labelLen > 255 - kLabelPrefixLen)) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
|
||||
*/
|
||||
#define NSSUTIL_VERSION "3.90.12.0 (UXP)"
|
||||
#define NSSUTIL_VERSION "3.90.13.0 (UXP)"
|
||||
#define NSSUTIL_VMAJOR 3
|
||||
#define NSSUTIL_VMINOR 90
|
||||
#define NSSUTIL_VPATCH 12
|
||||
#define NSSUTIL_VPATCH 13
|
||||
#define NSSUTIL_VBUILD 0
|
||||
#define NSSUTIL_BETA PR_FALSE
|
||||
|
||||
|
||||
@@ -542,7 +542,7 @@ DecodeGroup(void* dest,
|
||||
rv = SECFailure;
|
||||
}
|
||||
if (SECSuccess == rv) {
|
||||
void* entriesData = (unsigned char*)entries + (unsigned long)(sizeof(void*) * (totalEntries + 1));
|
||||
void* entriesData = (unsigned char*)entries + sizeof(void*) * (totalEntries + 1);
|
||||
/* and fix the pointers in the array */
|
||||
PRUint32 entriesIndex = 0;
|
||||
for (entriesIndex = 0; entriesIndex < totalEntries; entriesIndex++) {
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_PP_JS_MODULES += ['ForgetAboutSite.jsm']
|
||||
EXTRA_JS_MODULES += ['ForgetAboutSite.jsm']
|
||||
Reference in new issue
Block a user