diff --git a/accessible/src/base/Makefile.in b/accessible/src/base/Makefile.in index 9dc49eb30915..7fd861756c47 100644 --- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -75,8 +75,8 @@ CPPSRCS = \ nsCaretAccessible.cpp \ nsTextAccessible.cpp \ nsTextEquivUtils.cpp \ - nsTextAttrs.cpp \ StyleInfo.cpp \ + TextAttrs.cpp \ TextUpdater.cpp \ $(NULL) diff --git a/accessible/src/base/StyleInfo.cpp b/accessible/src/base/StyleInfo.cpp index 4bd503ddcfe1..c3f4c1cf8d4c 100644 --- a/accessible/src/base/StyleInfo.cpp +++ b/accessible/src/base/StyleInfo.cpp @@ -131,3 +131,12 @@ StyleInfo::FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue) nsCSSProps::ValueToKeywordEnum(aValue, nsCSSProps::kFontStyleKTable); AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(keyword), aFormattedValue); } + +void +StyleInfo::FormatTextDecorationStyle(PRUint8 aValue, nsAString& aFormattedValue) +{ + nsCSSKeyword keyword = + nsCSSProps::ValueToKeywordEnum(aValue, + nsCSSProps::kTextDecorationStyleKTable); + AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(keyword), aFormattedValue); +} diff --git a/accessible/src/base/StyleInfo.h b/accessible/src/base/StyleInfo.h index b77cd0485573..3e44d5754d47 100644 --- a/accessible/src/base/StyleInfo.h +++ b/accessible/src/base/StyleInfo.h @@ -62,6 +62,7 @@ public: static void FormatColor(const nscolor& aValue, nsString& aFormattedValue); static void FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue); + static void FormatTextDecorationStyle(PRUint8 aValue, nsAString& aFormattedValue); private: StyleInfo() MOZ_DELETE; diff --git a/accessible/src/base/nsTextAttrs.cpp b/accessible/src/base/TextAttrs.cpp similarity index 59% rename from accessible/src/base/nsTextAttrs.cpp rename to accessible/src/base/TextAttrs.cpp index 9dd2085791c6..bf22eca74a75 100644 --- a/accessible/src/base/nsTextAttrs.cpp +++ b/accessible/src/base/TextAttrs.cpp @@ -36,7 +36,7 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsTextAttrs.h" +#include "TextAttrs.h" #include "nsAccUtils.h" #include "nsCoreUtils.h" @@ -73,28 +73,18 @@ const char* const kCopyValue = nsnull; static nsCSSTextAttrMapItem gCSSTextAttrsMap[] = { - // CSS name CSS value Attribute name Attribute value - { "text-decoration", "line-through", &nsGkAtoms::textLineThroughStyle, "solid" }, - { "text-decoration", "underline", &nsGkAtoms::textUnderlineStyle, "solid" }, + // CSS name CSS value Attribute name Attribute value { "vertical-align", kAnyValue, &nsGkAtoms::textPosition, kCopyValue } }; //////////////////////////////////////////////////////////////////////////////// -// nsTextAttrs +// TextAttrsMgr +//////////////////////////////////////////////////////////////////////////////// -nsTextAttrsMgr::nsTextAttrsMgr(nsHyperTextAccessible *aHyperTextAcc, - bool aIncludeDefAttrs, - nsAccessible *aOffsetAcc, - PRInt32 aOffsetAccIdx) : - mHyperTextAcc(aHyperTextAcc), mIncludeDefAttrs(aIncludeDefAttrs), - mOffsetAcc(aOffsetAcc), mOffsetAccIdx(aOffsetAccIdx) -{ -} - -nsresult -nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes, - PRInt32 *aStartHTOffset, - PRInt32 *aEndHTOffset) +void +TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes, + PRInt32* aStartHTOffset, + PRInt32* aEndHTOffset) { // 1. Hyper text accessible must be specified always. // 2. Offset accessible and result hyper text offsets must be specified in @@ -108,7 +98,7 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes, (!mOffsetAcc && mOffsetAccIdx == -1 && !aStartHTOffset && !aEndHTOffset && mIncludeDefAttrs && aAttributes)), - "Wrong usage of nsTextAttrsMgr!"); + "Wrong usage of TextAttrsMgr!"); // Embedded objects are combined into own range with empty attributes set. if (mOffsetAcc && nsAccUtils::IsEmbeddedObject(mOffsetAcc)) { @@ -130,7 +120,7 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes, (*aEndHTOffset)++; } - return NS_OK; + return; } // Get the content and frame of the accessible. In the case of document @@ -139,7 +129,7 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes, nsIFrame *rootFrame = mHyperTextAcc->GetFrame(); NS_ASSERTION(rootFrame, "No frame for accessible!"); if (!rootFrame) - return NS_OK; + return; nsIContent *offsetNode = nsnull, *offsetElm = nsnull; nsIFrame *frame = nsnull; @@ -149,26 +139,18 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes, frame = offsetElm->GetPrimaryFrame(); } - nsTArray textAttrArray(10); + nsTArray textAttrArray(9); // "language" text attribute - nsLangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode); + LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode); textAttrArray.AppendElement(&langTextAttr); - // "text-line-through-style" text attribute - nsCSSTextAttr lineThroughTextAttr(0, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&lineThroughTextAttr); - - // "text-underline-style" text attribute - nsCSSTextAttr underlineTextAttr(1, hyperTextElm, offsetElm); - textAttrArray.AppendElement(&underlineTextAttr); - // "text-position" text attribute - nsCSSTextAttr posTextAttr(2, hyperTextElm, offsetElm); + CSSTextAttr posTextAttr(0, hyperTextElm, offsetElm); textAttrArray.AppendElement(&posTextAttr); // "background-color" text attribute - nsBGColorTextAttr bgColorTextAttr(rootFrame, frame); + BGColorTextAttr bgColorTextAttr(rootFrame, frame); textAttrArray.AppendElement(&bgColorTextAttr); // "color" text attribute @@ -180,7 +162,7 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes, textAttrArray.AppendElement(&fontFamilyTextAttr); // "font-size" text attribute - nsFontSizeTextAttr fontSizeTextAttr(rootFrame, frame); + FontSizeTextAttr fontSizeTextAttr(rootFrame, frame); textAttrArray.AppendElement(&fontSizeTextAttr); // "font-style" text attribute @@ -188,34 +170,28 @@ nsTextAttrsMgr::GetAttributes(nsIPersistentProperties *aAttributes, textAttrArray.AppendElement(&fontStyleTextAttr); // "font-weight" text attribute - nsFontWeightTextAttr fontWeightTextAttr(rootFrame, frame); + FontWeightTextAttr fontWeightTextAttr(rootFrame, frame); textAttrArray.AppendElement(&fontWeightTextAttr); + // "text-underline(line-through)-style(color)" text attributes + TextDecorTextAttr textDecorTextAttr(rootFrame, frame); + textAttrArray.AppendElement(&textDecorTextAttr); + // Expose text attributes if applicable. if (aAttributes) { PRUint32 len = textAttrArray.Length(); - for (PRUint32 idx = 0; idx < len; idx++) { - nsITextAttr *textAttr = textAttrArray[idx]; - - nsAutoString value; - if (textAttr->GetValue(value, mIncludeDefAttrs)) - nsAccUtils::SetAccAttr(aAttributes, textAttr->GetName(), value); - } + for (PRUint32 idx = 0; idx < len; idx++) + textAttrArray[idx]->Expose(aAttributes, mIncludeDefAttrs); } - nsresult rv = NS_OK; - // Expose text attributes range where they are applied if applicable. if (mOffsetAcc) - rv = GetRange(textAttrArray, aStartHTOffset, aEndHTOffset); - - textAttrArray.Clear(); - return rv; + GetRange(textAttrArray, aStartHTOffset, aEndHTOffset); } -nsresult -nsTextAttrsMgr::GetRange(const nsTArray& aTextAttrArray, - PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset) +void +TextAttrsMgr::GetRange(const nsTArray& aTextAttrArray, + PRInt32* aStartHTOffset, PRInt32* aEndHTOffset) { PRUint32 attrLen = aTextAttrArray.Length(); @@ -228,12 +204,13 @@ nsTextAttrsMgr::GetRange(const nsTArray& aTextAttrArray, if (nsAccUtils::IsEmbeddedObject(currAcc)) break; - nsIContent *currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent()); - NS_ENSURE_STATE(currElm); + nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent()); + if (!currElm) + return; bool offsetFound = false; for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) { - nsITextAttr *textAttr = aTextAttrArray[attrIdx]; + TextAttr* textAttr = aTextAttrArray[attrIdx]; if (!textAttr->Equal(currElm)) { offsetFound = true; break; @@ -253,12 +230,13 @@ nsTextAttrsMgr::GetRange(const nsTArray& aTextAttrArray, if (nsAccUtils::IsEmbeddedObject(currAcc)) break; - nsIContent *currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent()); - NS_ENSURE_STATE(currElm); + nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent()); + if (!currElm) + return; bool offsetFound = false; for (PRUint32 attrIdx = 0; attrIdx < attrLen; attrIdx++) { - nsITextAttr *textAttr = aTextAttrArray[attrIdx]; + TextAttr* textAttr = aTextAttrArray[attrIdx]; // Alter the end offset when text attribute changes its value and stop // the search. @@ -273,69 +251,68 @@ nsTextAttrsMgr::GetRange(const nsTArray& aTextAttrArray, (*aEndHTOffset) += nsAccUtils::TextLength(currAcc); } - - return NS_OK; } -//////////////////////////////////////////////////////////////////////////////// -// nsLangTextAttr -nsLangTextAttr::nsLangTextAttr(nsHyperTextAccessible *aRootAcc, - nsIContent *aRootContent, nsIContent *aContent) : - nsTextAttr(aContent == nsnull), mRootContent(aRootContent) +//////////////////////////////////////////////////////////////////////////////// +// LangTextAttr +//////////////////////////////////////////////////////////////////////////////// + +TextAttrsMgr::LangTextAttr:: + LangTextAttr(nsHyperTextAccessible* aRoot, + nsIContent* aRootElm, nsIContent* aElm) : + TTextAttr(!aElm), mRootContent(aRootElm) { - aRootAcc->Language(mRootNativeValue); + aRoot->Language(mRootNativeValue); mIsRootDefined = !mRootNativeValue.IsEmpty(); - if (aContent) - mIsDefined = GetLang(aContent, mNativeValue); + if (aElm) + mIsDefined = GetLang(aElm, mNativeValue); } bool -nsLangTextAttr::GetValueFor(nsIContent *aElm, nsAutoString *aValue) +TextAttrsMgr::LangTextAttr:: + GetValueFor(nsIContent* aElm, nsString* aValue) { return GetLang(aElm, *aValue); } void -nsLangTextAttr::Format(const nsAutoString& aValue, nsAString& aFormattedValue) +TextAttrsMgr::LangTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue) { - aFormattedValue = aValue; + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::language, aValue); } bool -nsLangTextAttr::GetLang(nsIContent *aContent, nsAString& aLang) +TextAttrsMgr::LangTextAttr:: + GetLang(nsIContent* aElm, nsAString& aLang) { - nsCoreUtils::GetLanguageFor(aContent, mRootContent, aLang); + nsCoreUtils::GetLanguageFor(aElm, mRootContent, aLang); return !aLang.IsEmpty(); } //////////////////////////////////////////////////////////////////////////////// -// nsCSSTextAttr +// CSSTextAttr //////////////////////////////////////////////////////////////////////////////// -nsCSSTextAttr::nsCSSTextAttr(PRUint32 aIndex, nsIContent *aRootContent, - nsIContent *aContent) : - nsTextAttr(aContent == nsnull), mIndex(aIndex) +TextAttrsMgr::CSSTextAttr:: + CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm) : + TTextAttr(!aElm), mIndex(aIndex) { - mIsRootDefined = GetValueFor(aRootContent, &mRootNativeValue); + mIsRootDefined = GetValueFor(aRootElm, &mRootNativeValue); - if (aContent) - mIsDefined = GetValueFor(aContent, &mNativeValue); -} - -nsIAtom* -nsCSSTextAttr::GetName() const -{ - return *gCSSTextAttrsMap[mIndex].mAttrName; + if (aElm) + mIsDefined = GetValueFor(aElm, &mNativeValue); } bool -nsCSSTextAttr::GetValueFor(nsIContent *aContent, nsAutoString *aValue) +TextAttrsMgr::CSSTextAttr:: + GetValueFor(nsIContent* aElm, nsString* aValue) { nsCOMPtr currStyleDecl = - nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aContent); + nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aElm); if (!currStyleDecl) return false; @@ -353,22 +330,30 @@ nsCSSTextAttr::GetValueFor(nsIContent *aContent, nsAutoString *aValue) } void -nsCSSTextAttr::Format(const nsAutoString& aValue, nsAString& aFormattedValue) +TextAttrsMgr::CSSTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue) { - const char *attrValue = gCSSTextAttrsMap[mIndex].mAttrValue; - if (attrValue != kCopyValue) - AppendASCIItoUTF16(attrValue, aFormattedValue); - else - aFormattedValue = aValue; + const char* attrValue = gCSSTextAttrsMap[mIndex].mAttrValue; + if (attrValue != kCopyValue) { + nsAutoString formattedValue; + AppendASCIItoUTF16(attrValue, formattedValue); + nsAccUtils::SetAccAttr(aAttributes, *gCSSTextAttrsMap[mIndex].mAttrName, + formattedValue); + return; + } + + nsAccUtils::SetAccAttr(aAttributes, *gCSSTextAttrsMap[mIndex].mAttrName, + aValue); } //////////////////////////////////////////////////////////////////////////////// -// nsBGColorTextAttr +// BGColorTextAttr //////////////////////////////////////////////////////////////////////////////// -nsBGColorTextAttr::nsBGColorTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) : - nsTextAttr(aFrame == nsnull), mRootFrame(aRootFrame) +TextAttrsMgr::BGColorTextAttr:: + BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr(!aFrame), mRootFrame(aRootFrame) { mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue); if (aFrame) @@ -376,27 +361,28 @@ nsBGColorTextAttr::nsBGColorTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) : } bool -nsBGColorTextAttr::GetValueFor(nsIContent *aContent, nscolor *aValue) +TextAttrsMgr::BGColorTextAttr:: + GetValueFor(nsIContent* aElm, nscolor* aValue) { - nsIFrame *frame = aContent->GetPrimaryFrame(); - if (!frame) - return false; - - return GetColor(frame, aValue); + nsIFrame* frame = aElm->GetPrimaryFrame(); + return frame ? GetColor(frame, aValue) : false; } void -nsBGColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue) +TextAttrsMgr::BGColorTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const nscolor& aValue) { - nsAutoString value; - StyleInfo::FormatColor(aValue, value); - aFormattedValue = value; + nsAutoString formattedValue; + StyleInfo::FormatColor(aValue, formattedValue); + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::backgroundColor, + formattedValue); } bool -nsBGColorTextAttr::GetColor(nsIFrame *aFrame, nscolor *aColor) +TextAttrsMgr::BGColorTextAttr:: + GetColor(nsIFrame* aFrame, nscolor* aColor) { - const nsStyleBackground *styleBackground = aFrame->GetStyleBackground(); + const nsStyleBackground* styleBackground = aFrame->GetStyleBackground(); if (NS_GET_A(styleBackground->mBackgroundColor) > 0) { *aColor = styleBackground->mBackgroundColor; @@ -423,8 +409,9 @@ nsBGColorTextAttr::GetColor(nsIFrame *aFrame, nscolor *aColor) // ColorTextAttr //////////////////////////////////////////////////////////////////////////////// -ColorTextAttr::ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : - nsTextAttr(!aFrame) +TextAttrsMgr::ColorTextAttr:: + ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr(!aFrame) { mRootNativeValue = aRootFrame->GetStyleColor()->mColor; mIsRootDefined = true; @@ -436,9 +423,10 @@ ColorTextAttr::ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : } bool -ColorTextAttr::GetValueFor(nsIContent* aContent, nscolor* aValue) +TextAttrsMgr::ColorTextAttr:: + GetValueFor(nsIContent* aElm, nscolor* aValue) { - nsIFrame* frame = aContent->GetPrimaryFrame(); + nsIFrame* frame = aElm->GetPrimaryFrame(); if (frame) { *aValue = frame->GetStyleColor()->mColor; return true; @@ -448,11 +436,12 @@ ColorTextAttr::GetValueFor(nsIContent* aContent, nscolor* aValue) } void -ColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue) +TextAttrsMgr::ColorTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const nscolor& aValue) { - nsAutoString value; - StyleInfo::FormatColor(aValue, value); - aFormattedValue = value; + nsAutoString formattedValue; + StyleInfo::FormatColor(aValue, formattedValue); + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::color, formattedValue); } @@ -460,8 +449,9 @@ ColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue) // FontFamilyTextAttr //////////////////////////////////////////////////////////////////////////////// -FontFamilyTextAttr::FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : - nsTextAttr(aFrame == nsnull) +TextAttrsMgr::FontFamilyTextAttr:: + FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr(!aFrame) { mIsRootDefined = GetFontFamily(aRootFrame, mRootNativeValue); @@ -470,24 +460,23 @@ FontFamilyTextAttr::FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : } bool -FontFamilyTextAttr::GetValueFor(nsIContent* aElm, nsAutoString* aValue) +TextAttrsMgr::FontFamilyTextAttr:: + GetValueFor(nsIContent* aElm, nsString* aValue) { nsIFrame* frame = aElm->GetPrimaryFrame(); - if (!frame) - return false; - - return GetFontFamily(frame, *aValue); + return frame ? GetFontFamily(frame, *aValue) : false; } void -FontFamilyTextAttr::Format(const nsAutoString& aValue, - nsAString& aFormattedValue) +TextAttrsMgr::FontFamilyTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue) { - aFormattedValue = aValue; + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_family, aValue); } bool -FontFamilyTextAttr::GetFontFamily(nsIFrame* aFrame, nsAutoString& aFamily) +TextAttrsMgr::FontFamilyTextAttr:: + GetFontFamily(nsIFrame* aFrame, nsString& aFamily) { nsRefPtr fm; nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm)); @@ -501,36 +490,40 @@ FontFamilyTextAttr::GetFontFamily(nsIFrame* aFrame, nsAutoString& aFamily) //////////////////////////////////////////////////////////////////////////////// -// nsFontSizeTextAttr +// FontSizeTextAttr //////////////////////////////////////////////////////////////////////////////// -nsFontSizeTextAttr::nsFontSizeTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) : - nsTextAttr(aFrame == nsnull) +TextAttrsMgr::FontSizeTextAttr:: + FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr(!aFrame) { mDC = aRootFrame->PresContext()->DeviceContext(); - mRootNativeValue = GetFontSize(aRootFrame); + mRootNativeValue = aRootFrame->GetStyleFont()->mSize; mIsRootDefined = true; if (aFrame) { - mNativeValue = GetFontSize(aFrame); + mNativeValue = aFrame->GetStyleFont()->mSize; mIsDefined = true; } } bool -nsFontSizeTextAttr::GetValueFor(nsIContent *aContent, nscoord *aValue) +TextAttrsMgr::FontSizeTextAttr:: + GetValueFor(nsIContent* aElm, nscoord* aValue) { - nsIFrame *frame = aContent->GetPrimaryFrame(); - if (!frame) - return false; + nsIFrame* frame = aElm->GetPrimaryFrame(); + if (frame) { + *aValue = frame->GetStyleFont()->mSize; + return true; + } - *aValue = GetFontSize(frame); - return true; + return false; } void -nsFontSizeTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue) +TextAttrsMgr::FontSizeTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const nscoord& aValue) { // Convert from nscoord to pt. // @@ -548,13 +541,8 @@ nsFontSizeTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue) nsAutoString value; value.AppendInt(pts); value.Append(NS_LITERAL_STRING("pt")); - aFormattedValue = value; -} -nscoord -nsFontSizeTextAttr::GetFontSize(nsIFrame *aFrame) -{ - return aFrame->GetStyleFont()->mSize; + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_size, value); } @@ -562,8 +550,9 @@ nsFontSizeTextAttr::GetFontSize(nsIFrame *aFrame) // FontStyleTextAttr //////////////////////////////////////////////////////////////////////////////// -FontStyleTextAttr::FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : - nsTextAttr(!aFrame) +TextAttrsMgr::FontStyleTextAttr:: + FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr(!aFrame) { mRootNativeValue = aRootFrame->GetStyleFont()->mFont.style; mIsRootDefined = true; @@ -575,7 +564,8 @@ FontStyleTextAttr::FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : } bool -FontStyleTextAttr::GetValueFor(nsIContent* aContent, nscoord* aValue) +TextAttrsMgr::FontStyleTextAttr:: + GetValueFor(nsIContent* aContent, nscoord* aValue) { nsIFrame* frame = aContent->GetPrimaryFrame(); if (frame) { @@ -587,19 +577,23 @@ FontStyleTextAttr::GetValueFor(nsIContent* aContent, nscoord* aValue) } void -FontStyleTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue) +TextAttrsMgr::FontStyleTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const nscoord& aValue) { - StyleInfo::FormatFontStyle(aValue, aFormattedValue); + nsAutoString formattedValue; + StyleInfo::FormatFontStyle(aValue, formattedValue); + + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_style, formattedValue); } //////////////////////////////////////////////////////////////////////////////// -// nsFontWeightTextAttr +// FontWeightTextAttr //////////////////////////////////////////////////////////////////////////////// -nsFontWeightTextAttr::nsFontWeightTextAttr(nsIFrame *aRootFrame, - nsIFrame *aFrame) : - nsTextAttr(aFrame == nsnull) +TextAttrsMgr::FontWeightTextAttr:: + FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr(!aFrame) { mRootNativeValue = GetFontWeight(aRootFrame); mIsRootDefined = true; @@ -611,26 +605,31 @@ nsFontWeightTextAttr::nsFontWeightTextAttr(nsIFrame *aRootFrame, } bool -nsFontWeightTextAttr::GetValueFor(nsIContent *aContent, PRInt32 *aValue) +TextAttrsMgr::FontWeightTextAttr:: + GetValueFor(nsIContent* aElm, PRInt32* aValue) { - nsIFrame *frame = aContent->GetPrimaryFrame(); - if (!frame) - return false; + nsIFrame* frame = aElm->GetPrimaryFrame(); + if (frame) { + *aValue = GetFontWeight(frame); + return true; + } - *aValue = GetFontWeight(frame); - return true; + return false; } void -nsFontWeightTextAttr::Format(const PRInt32& aValue, nsAString& aFormattedValue) +TextAttrsMgr::FontWeightTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const PRInt32& aValue) { - nsAutoString value; - value.AppendInt(aValue); - aFormattedValue = value; + nsAutoString formattedValue; + formattedValue.AppendInt(aValue); + + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::fontWeight, formattedValue); } PRInt32 -nsFontWeightTextAttr::GetFontWeight(nsIFrame *aFrame) +TextAttrsMgr::FontWeightTextAttr:: + GetFontWeight(nsIFrame* aFrame) { // nsFont::width isn't suitable here because it's necessary to expose real // value of font weight (used font might not have some font weight values). @@ -664,3 +663,82 @@ nsFontWeightTextAttr::GetFontWeight(nsIFrame *aFrame) return fontEntry->Weight(); #endif } + + +//////////////////////////////////////////////////////////////////////////////// +// TextDecorTextAttr +//////////////////////////////////////////////////////////////////////////////// + +TextAttrsMgr::TextDecorValue:: + TextDecorValue(nsIFrame* aFrame) +{ + const nsStyleTextReset* textReset = aFrame->GetStyleTextReset(); + mStyle = textReset->GetDecorationStyle(); + + bool isForegroundColor = false; + textReset->GetDecorationColor(mColor, isForegroundColor); + if (isForegroundColor) + mColor = aFrame->GetStyleColor()->mColor; + + mLine = textReset->mTextDecorationLine & + (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE | + NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH); +} + +TextAttrsMgr::TextDecorTextAttr:: + TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr(!aFrame) +{ + mRootNativeValue = TextDecorValue(aRootFrame); + mIsRootDefined = mRootNativeValue.IsDefined(); + + if (aFrame) { + mNativeValue = TextDecorValue(aFrame); + mIsDefined = mNativeValue.IsDefined(); + } +} + +bool +TextAttrsMgr::TextDecorTextAttr:: + GetValueFor(nsIContent* aContent, TextDecorValue* aValue) +{ + nsIFrame* frame = aContent->GetPrimaryFrame(); + if (frame) { + *aValue = TextDecorValue(frame); + return aValue->IsDefined(); + } + + return false; +} + +void +TextAttrsMgr::TextDecorTextAttr:: + ExposeValue(nsIPersistentProperties* aAttributes, const TextDecorValue& aValue) +{ + if (aValue.IsUnderline()) { + nsAutoString formattedStyle; + StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle); + nsAccUtils::SetAccAttr(aAttributes, + nsGkAtoms::textUnderlineStyle, + formattedStyle); + + nsAutoString formattedColor; + StyleInfo::FormatColor(aValue.Color(), formattedColor); + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textUnderlineColor, + formattedColor); + return; + } + + if (aValue.IsLineThrough()) { + nsAutoString formattedStyle; + StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle); + nsAccUtils::SetAccAttr(aAttributes, + nsGkAtoms::textLineThroughStyle, + formattedStyle); + + nsAutoString formattedColor; + StyleInfo::FormatColor(aValue.Color(), formattedColor); + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textLineThroughColor, + formattedColor); + } +} diff --git a/accessible/src/base/TextAttrs.h b/accessible/src/base/TextAttrs.h new file mode 100644 index 000000000000..2374b8dc7aee --- /dev/null +++ b/accessible/src/base/TextAttrs.h @@ -0,0 +1,443 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Alexander Surkov (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsTextAttrs_h_ +#define nsTextAttrs_h_ + +#include "nsIContent.h" +#include "nsIFrame.h" +#include "nsIPersistentProperties2.h" +#include "nsStyleConsts.h" + +class nsHyperTextAccessible; + +namespace mozilla { +namespace a11y { + +/** + * Used to expose text attributes for the hyper text accessible (see + * nsHyperTextAccessible class). + * + * @note "invalid: spelling" text attribute is implemented entirely in + * nsHyperTextAccessible class. + */ +class TextAttrsMgr +{ +public: + /** + * Constructor. Used to expose default text attributes. + */ + TextAttrsMgr(nsHyperTextAccessible* aHyperTextAcc) : + mHyperTextAcc(aHyperTextAcc), mIncludeDefAttrs(true), + mOffsetAcc(nsnull), mOffsetAccIdx(-1) { } + + /** + * Constructor. Used to expose text attributes at the given offset. + * + * @param aHyperTextAcc [in] hyper text accessible text attributes are + * calculated for + * @param aIncludeDefAttrs [optional] indicates whether default text + * attributes should be included into list of exposed + * text attributes + * @param oOffsetAcc [optional] offset an accessible the text attributes + * should be calculated for + * @param oOffsetAccIdx [optional] index in parent of offset accessible + */ + TextAttrsMgr(nsHyperTextAccessible* aHyperTextAcc, + bool aIncludeDefAttrs, + nsAccessible* aOffsetAcc, + PRInt32 aOffsetAccIdx) : + mHyperTextAcc(aHyperTextAcc), mIncludeDefAttrs(aIncludeDefAttrs), + mOffsetAcc(aOffsetAcc), mOffsetAccIdx(aOffsetAccIdx) { } + + /* + * Return text attributes and hyper text offsets where these attributes are + * applied. Offsets are calculated in the case of non default attributes. + * + * @note In the case of default attributes pointers on hyper text offsets + * must be skipped. + * + * @param aAttributes [in, out] text attributes list + * @param aStartHTOffset [out, optional] start hyper text offset + * @param aEndHTOffset [out, optional] end hyper text offset + */ + void GetAttributes(nsIPersistentProperties* aAttributes, + PRInt32* aStartHTOffset = nsnull, + PRInt32* aEndHTOffset = nsnull); + +protected: + /** + * Calculates range (start and end offsets) of text where the text attributes + * are stretched. New offsets may be smaller if one of text attributes changes + * its value before or after the given offsets. + * + * @param aTextAttrArray [in] text attributes array + * @param aStartHTOffset [in, out] the start offset + * @param aEndHTOffset [in, out] the end offset + */ + class TextAttr; + void GetRange(const nsTArray& aTextAttrArray, + PRInt32* aStartHTOffset, PRInt32* aEndHTOffset); + +private: + nsHyperTextAccessible* mHyperTextAcc; + + bool mIncludeDefAttrs; + + nsAccessible* mOffsetAcc; + PRInt32 mOffsetAccIdx; + +protected: + + /** + * Interface class of text attribute class implementations. + */ + class TextAttr + { + public: + /** + * Expose the text attribute to the given attribute set. + * + * @param aAttributes [in] the given attribute set + * @param aIncludeDefAttrValue [in] if true then attribute is exposed even + * if its value is the same as default one + */ + virtual void Expose(nsIPersistentProperties* aAttributes, + bool aIncludeDefAttrValue) = 0; + + /** + * Return true if the text attribute value on the given element equals with + * predefined attribute value. + */ + virtual bool Equal(nsIContent* aElm) = 0; + }; + + + /** + * Base class to work with text attributes. See derived classes below. + */ + template + class TTextAttr : public TextAttr + { + public: + TTextAttr(bool aGetRootValue) : mGetRootValue(aGetRootValue) {} + + // ITextAttr + virtual void Expose(nsIPersistentProperties* aAttributes, + bool aIncludeDefAttrValue) + { + if (mGetRootValue) { + if (mIsRootDefined) + ExposeValue(aAttributes, mRootNativeValue); + return; + } + + if (mIsDefined) { + if (aIncludeDefAttrValue || mRootNativeValue != mNativeValue) + ExposeValue(aAttributes, mNativeValue); + return; + } + + if (aIncludeDefAttrValue && mIsRootDefined) + ExposeValue(aAttributes, mRootNativeValue); + } + + virtual bool Equal(nsIContent* aElm) + { + T nativeValue; + bool isDefined = GetValueFor(aElm, &nativeValue); + + if (!mIsDefined && !isDefined) + return true; + + if (mIsDefined && isDefined) + return nativeValue == mNativeValue; + + if (mIsDefined) + return mNativeValue == mRootNativeValue; + + return nativeValue == mRootNativeValue; + } + + protected: + + // Expose the text attribute with the given value to attribute set. + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const T& aValue) = 0; + + // Return native value for the given DOM element. + virtual bool GetValueFor(nsIContent* aElm, T* aValue) = 0; + + // Indicates if root value should be exposed. + bool mGetRootValue; + + // Native value and flag indicating if the value is defined (initialized in + // derived classes). Note, undefined native value means it is inherited + // from root. + T mNativeValue; + bool mIsDefined; + + // Native root value and flag indicating if the value is defined (initialized + // in derived classes). + T mRootNativeValue; + bool mIsRootDefined; + }; + + + /** + * Class is used for the work with 'language' text attribute. + */ + class LangTextAttr : public TTextAttr + { + public: + LangTextAttr(nsHyperTextAccessible* aRoot, nsIContent* aRootElm, + nsIContent* aElm); + virtual ~LangTextAttr() { } + + protected: + + // TextAttr + virtual bool GetValueFor(nsIContent* aElm, nsString* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nsString& aValue); + + private: + bool GetLang(nsIContent* aElm, nsAString& aLang); + nsCOMPtr mRootContent; + }; + + + /** + * Class is used for the work with CSS based text attributes. + */ + class CSSTextAttr : public TTextAttr + { + public: + CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm); + virtual ~CSSTextAttr() { } + + protected: + + // TextAttr + virtual bool GetValueFor(nsIContent* aElm, nsString* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nsString& aValue); + + private: + PRInt32 mIndex; + }; + + + /** + * Class is used for the work with 'background-color' text attribute. + */ + class BGColorTextAttr : public TTextAttr + { + public: + BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~BGColorTextAttr() { } + + protected: + + // TextAttr + virtual bool GetValueFor(nsIContent* aElm, nscolor* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nscolor& aValue); + + private: + bool GetColor(nsIFrame* aFrame, nscolor* aColor); + nsIFrame* mRootFrame; + }; + + + /** + * Class is used for the work with 'color' text attribute. + */ + class ColorTextAttr : public TTextAttr + { + public: + ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~ColorTextAttr() { } + + protected: + + // TTextAttr + virtual bool GetValueFor(nsIContent* aElm, nscolor* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nscolor& aValue); + }; + + + /** + * Class is used for the work with "font-family" text attribute. + */ + class FontFamilyTextAttr : public TTextAttr + { + public: + FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~FontFamilyTextAttr() { } + + protected: + + // TTextAttr + virtual bool GetValueFor(nsIContent* aElm, nsString* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nsString& aValue); + + private: + + bool GetFontFamily(nsIFrame* aFrame, nsString& aFamily); + }; + + + /** + * Class is used for the work with "font-size" text attribute. + */ + class FontSizeTextAttr : public TTextAttr + { + public: + FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~FontSizeTextAttr() { } + + protected: + + // TTextAttr + virtual bool GetValueFor(nsIContent* aElm, nscoord* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nscoord& aValue); + + private: + nsDeviceContext* mDC; + }; + + + /** + * Class is used for the work with "font-style" text attribute. + */ + class FontStyleTextAttr : public TTextAttr + { + public: + FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~FontStyleTextAttr() { } + + protected: + + // TTextAttr + virtual bool GetValueFor(nsIContent* aContent, nscoord* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nscoord& aValue); + }; + + + /** + * Class is used for the work with "font-weight" text attribute. + */ + class FontWeightTextAttr : public TTextAttr + { + public: + FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~FontWeightTextAttr() { } + + protected: + + // TTextAttr + virtual bool GetValueFor(nsIContent* aElm, PRInt32* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const PRInt32& aValue); + + private: + PRInt32 GetFontWeight(nsIFrame* aFrame); + }; + + + /** + * TextDecorTextAttr class is used for the work with + * "text-line-through-style", "text-line-through-color", + * "text-underline-style" and "text-underline-color" text attributes. + */ + + class TextDecorValue + { + public: + TextDecorValue() { } + TextDecorValue(nsIFrame* aFrame); + + nscolor Color() const { return mColor; } + PRUint8 Style() const { return mStyle; } + + bool IsDefined() const + { return IsUnderline() || IsLineThrough(); } + bool IsUnderline() const + { return mLine & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; } + bool IsLineThrough() const + { return mLine & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH; } + + bool operator ==(const TextDecorValue& aValue) + { + return mColor == aValue.mColor && mLine == aValue.mLine && + mStyle == aValue.mStyle; + } + bool operator !=(const TextDecorValue& aValue) + { return !(*this == aValue); } + + private: + nscolor mColor; + PRUint8 mLine; + PRUint8 mStyle; + }; + + class TextDecorTextAttr : public TTextAttr + { + public: + TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~TextDecorTextAttr() { } + + protected: + + // TextAttr + virtual bool GetValueFor(nsIContent* aElm, TextDecorValue* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const TextDecorValue& aValue); + }; + +}; // TextAttrMgr + +} // namespace a11y +} // namespace mozilla + +#endif diff --git a/accessible/src/base/nsTextAttrs.h b/accessible/src/base/nsTextAttrs.h deleted file mode 100644 index aadcde7a8e6b..000000000000 --- a/accessible/src/base/nsTextAttrs.h +++ /dev/null @@ -1,426 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Alexander Surkov (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsTextAttrs_h_ -#define nsTextAttrs_h_ - -class nsHyperTextAccessible; - -#include "nsIContent.h" -#include "nsIFrame.h" -#include "nsIPersistentProperties2.h" - -class nsITextAttr; - -/** - * Used to expose text attributes for the hyper text accessible (see - * nsHyperTextAccessible class). It is indended for the work with 'language' and - * CSS based text attributes. - * - * @note "invalid: spelling" text attrbiute is implemented entirerly in - * nsHyperTextAccessible class. - */ -class nsTextAttrsMgr -{ -public: - /** - * Constructor. If instance of the class is intended to expose default text - * attributes then 'aIncludeDefAttrs' and 'aOffsetNode' argument must be - * skiped. - * - * @param aHyperTextAcc hyper text accessible text attributes are - * calculated for - * @param aHyperTextNode DOM node of the given hyper text accessbile - * @param aIncludeDefAttrs [optional] indicates whether default text - * attributes should be included into list of exposed - * text attributes. - * @param oOffsetNode [optional] DOM node represents hyper text offset - * inside hyper text accessible - */ - nsTextAttrsMgr(nsHyperTextAccessible *aHyperTextAcc, - bool aIncludeDefAttrs = true, - nsAccessible *aOffsetAcc = nsnull, - PRInt32 aOffsetAccIdx = -1); - - /* - * Return text attributes and hyper text offsets where these attributes are - * applied. Offsets are calculated in the case of non default attributes. - * - * @note In the case of default attributes pointers on hyper text offsets - * must be skiped. - * - * @param aAttributes [in, out] text attributes list - * @param aStartHTOffset [out, optional] start hyper text offset - * @param aEndHTOffset [out, optional] end hyper text offset - */ - nsresult GetAttributes(nsIPersistentProperties *aAttributes, - PRInt32 *aStartHTOffset = nsnull, - PRInt32 *aEndHTOffset = nsnull); - -protected: - /** - * Calculates range (start and end offsets) of text where the text attributes - * are stretched. New offsets may be smaller if one of text attributes changes - * its value before or after the given offsets. - * - * @param aTextAttrArray [in] text attributes array - * @param aStartHTOffset [in, out] the start offset - * @param aEndHTOffset [in, out] the end offset - */ - nsresult GetRange(const nsTArray& aTextAttrArray, - PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset); - -private: - nsRefPtr mHyperTextAcc; - - bool mIncludeDefAttrs; - - nsRefPtr mOffsetAcc; - PRInt32 mOffsetAccIdx; -}; - - -//////////////////////////////////////////////////////////////////////////////// -// Private implementation details - -/** - * Interface class of text attribute class implementations. - */ -class nsITextAttr -{ -public: - /** - * Return the name of text attribute. - */ - virtual nsIAtom* GetName() const = 0; - - /** - * Retrieve the value of text attribute in out param, return true if differs - * from the default value of text attribute or if include default attribute - * value flag is setted. - * - * @param aValue [in, out] the value of text attribute - * @param aIncludeDefAttrValue [in] include default attribute value flag - * @return true if text attribute value differs from - * default or include default attribute value - * flag is applied - */ - virtual bool GetValue(nsAString& aValue, bool aIncludeDefAttrValue) = 0; - - /** - * Return true if the text attribute value on the given element equals with - * predefined attribute value. - */ - virtual bool Equal(nsIContent *aContent) = 0; -}; - - -/** - * Base class to work with text attributes. See derived classes below. - */ -template -class nsTextAttr : public nsITextAttr -{ -public: - nsTextAttr(bool aGetRootValue) : mGetRootValue(aGetRootValue) {} - - // nsITextAttr - virtual bool GetValue(nsAString& aValue, bool aIncludeDefAttrValue) - { - if (mGetRootValue) { - Format(mRootNativeValue, aValue); - return mIsRootDefined; - } - - bool isDefined = mIsDefined; - T* nativeValue = &mNativeValue; - - if (!isDefined) { - if (aIncludeDefAttrValue) { - isDefined = mIsRootDefined; - nativeValue = &mRootNativeValue; - } - } else if (!aIncludeDefAttrValue) { - isDefined = mRootNativeValue != mNativeValue; - } - - if (!isDefined) - return false; - - Format(*nativeValue, aValue); - return true; - } - - virtual bool Equal(nsIContent *aContent) - { - T nativeValue; - bool isDefined = GetValueFor(aContent, &nativeValue); - - if (!mIsDefined && !isDefined) - return true; - - if (mIsDefined && isDefined) - return nativeValue == mNativeValue; - - if (mIsDefined) - return mNativeValue == mRootNativeValue; - - return nativeValue == mRootNativeValue; - } - -protected: - - // Return native value for the given DOM element. - virtual bool GetValueFor(nsIContent *aContent, T *aValue) = 0; - - // Format native value to text attribute value. - virtual void Format(const T& aValue, nsAString& aFormattedValue) = 0; - - // Indicates if root value should be exposed. - bool mGetRootValue; - - // Native value and flag indicating if the value is defined (initialized in - // derived classes). Note, undefined native value means it is inherited - // from root. - T mNativeValue; - bool mIsDefined; - - // Native root value and flag indicating if the value is defined (initialized - // in derived classes). - T mRootNativeValue; - bool mIsRootDefined; -}; - - -/** - * Class is used for the work with 'language' text attribute in nsTextAttrsMgr - * class. - */ -class nsLangTextAttr : public nsTextAttr -{ -public: - nsLangTextAttr(nsHyperTextAccessible *aRootAcc, nsIContent *aRootContent, - nsIContent *aContent); - - // nsITextAttr - virtual nsIAtom *GetName() const { return nsGkAtoms::language; } - -protected: - - // nsTextAttr - virtual bool GetValueFor(nsIContent *aElm, nsAutoString *aValue); - virtual void Format(const nsAutoString& aValue, nsAString& aFormattedValue); - -private: - bool GetLang(nsIContent *aContent, nsAString& aLang); - nsCOMPtr mRootContent; -}; - - -/** - * Class is used for the work with CSS based text attributes in nsTextAttrsMgr - * class. - */ -class nsCSSTextAttr : public nsTextAttr -{ -public: - nsCSSTextAttr(PRUint32 aIndex, nsIContent *aRootContent, - nsIContent *aContent); - - // nsITextAttr - virtual nsIAtom *GetName() const; - -protected: - - // nsTextAttr - virtual bool GetValueFor(nsIContent *aContent, nsAutoString *aValue); - virtual void Format(const nsAutoString& aValue, nsAString& aFormattedValue); - -private: - PRInt32 mIndex; -}; - - -/** - * Class is used for the work with 'background-color' text attribute in - * nsTextAttrsMgr class. - */ -class nsBGColorTextAttr : public nsTextAttr -{ -public: - nsBGColorTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame); - - // nsITextAttr - virtual nsIAtom *GetName() const { return nsGkAtoms::backgroundColor; } - -protected: - // nsTextAttr - virtual bool GetValueFor(nsIContent *aContent, nscolor *aValue); - virtual void Format(const nscolor& aValue, nsAString& aFormattedValue); - -private: - bool GetColor(nsIFrame *aFrame, nscolor *aColor); - nsIFrame *mRootFrame; -}; - - -/** - * Class is used for the work with 'color' text attribute in nsTextAttrsMgr - * class. - */ -class ColorTextAttr : public nsTextAttr -{ -public: - ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); - - // nsITextAttr - virtual nsIAtom* GetName() const { return nsGkAtoms::color; } - -protected: - // nsTextAttr - virtual bool GetValueFor(nsIContent* aContent, nscolor* aValue); - virtual void Format(const nscolor& aValue, nsAString& aFormattedValue); -}; - - -/** - * Class is used for the work with "font-family" text attribute in - * nsTextAttrsMgr class. - */ -class FontFamilyTextAttr : public nsTextAttr -{ -public: - FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); - - // nsITextAttr - virtual nsIAtom* GetName() const { return nsGkAtoms::font_family; } - -protected: - - // nsTextAttr - virtual bool GetValueFor(nsIContent* aContent, nsAutoString* aValue); - virtual void Format(const nsAutoString& aValue, nsAString& aFormattedValue); - -private: - - bool GetFontFamily(nsIFrame* aFrame, nsAutoString& aFamily); -}; - - -/** - * Class is used for the work with "font-size" text attribute in nsTextAttrsMgr - * class. - */ -class nsFontSizeTextAttr : public nsTextAttr -{ -public: - nsFontSizeTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame); - - // nsITextAttr - virtual nsIAtom *GetName() const { return nsGkAtoms::font_size; } - -protected: - - // nsTextAttr - virtual bool GetValueFor(nsIContent *aContent, nscoord *aValue); - virtual void Format(const nscoord& aValue, nsAString& aFormattedValue); - -private: - - /** - * Return font size for the given frame. - * - * @param aFrame [in] the given frame to query font-size - * @return font size - */ - nscoord GetFontSize(nsIFrame *aFrame); - - nsDeviceContext *mDC; -}; - - -/** - * Class is used for the work with "font-style" text attribute in nsTextAttrsMgr - * class. - */ -class FontStyleTextAttr : public nsTextAttr -{ -public: - FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); - - // nsITextAttr - virtual nsIAtom* GetName() const { return nsGkAtoms::font_style; } - -protected: - - // nsTextAttr - virtual bool GetValueFor(nsIContent* aContent, nscoord* aValue); - virtual void Format(const nscoord &aValue, nsAString &aFormattedValue); -}; - - -/** - * Class is used for the work with "font-weight" text attribute in - * nsTextAttrsMgr class. - */ -class nsFontWeightTextAttr : public nsTextAttr -{ -public: - nsFontWeightTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame); - - // nsITextAttr - virtual nsIAtom *GetName() const { return nsGkAtoms::fontWeight; } - -protected: - - // nsTextAttr - virtual bool GetValueFor(nsIContent *aElm, PRInt32 *aValue); - virtual void Format(const PRInt32& aValue, nsAString& aFormattedValue); - -private: - - /** - * Return font weight for the given frame. - * - * @param aFrame [in] the given frame to query font weight - * @return font weight - */ - PRInt32 GetFontWeight(nsIFrame *aFrame); -}; - -#endif diff --git a/accessible/src/html/nsHyperTextAccessible.cpp b/accessible/src/html/nsHyperTextAccessible.cpp index b51741676bab..77903b195af1 100644 --- a/accessible/src/html/nsHyperTextAccessible.cpp +++ b/accessible/src/html/nsHyperTextAccessible.cpp @@ -42,9 +42,9 @@ #include "nsAccessibilityService.h" #include "nsAccUtils.h" #include "nsDocAccessible.h" -#include "nsTextAttrs.h" #include "Role.h" #include "States.h" +#include "TextAttrs.h" #include "nsIClipboard.h" #include "nsContentUtils.h" @@ -1130,8 +1130,8 @@ nsHyperTextAccessible::GetTextAttributes(bool aIncludeDefAttrs, // default attributes if they were requested, otherwise return empty set. if (aOffset == 0) { if (aIncludeDefAttrs) { - nsTextAttrsMgr textAttrsMgr(this, true, nsnull, -1); - return textAttrsMgr.GetAttributes(*aAttributes); + TextAttrsMgr textAttrsMgr(this); + textAttrsMgr.GetAttributes(*aAttributes); } return NS_OK; } @@ -1143,11 +1143,9 @@ nsHyperTextAccessible::GetTextAttributes(bool aIncludeDefAttrs, PRInt32 endOffset = GetChildOffset(accAtOffsetIdx + 1); PRInt32 offsetInAcc = aOffset - startOffset; - nsTextAttrsMgr textAttrsMgr(this, aIncludeDefAttrs, accAtOffset, - accAtOffsetIdx); - nsresult rv = textAttrsMgr.GetAttributes(*aAttributes, &startOffset, - &endOffset); - NS_ENSURE_SUCCESS(rv, rv); + TextAttrsMgr textAttrsMgr(this, aIncludeDefAttrs, accAtOffset, + accAtOffsetIdx); + textAttrsMgr.GetAttributes(*aAttributes, &startOffset, &endOffset); // Compute spelling attributes on text accessible only. nsIFrame *offsetFrame = accAtOffset->GetFrame(); @@ -1186,8 +1184,9 @@ nsHyperTextAccessible::GetDefaultTextAttributes(nsIPersistentProperties **aAttri NS_ADDREF(*aAttributes = attributes); - nsTextAttrsMgr textAttrsMgr(this, true); - return textAttrsMgr.GetAttributes(*aAttributes); + TextAttrsMgr textAttrsMgr(this); + textAttrsMgr.GetAttributes(*aAttributes); + return NS_OK; } PRInt32 diff --git a/accessible/tests/mochitest/attributes/test_text.html b/accessible/tests/mochitest/attributes/test_text.html index fc4c92f7a594..f695301696dc 100644 --- a/accessible/tests/mochitest/attributes/test_text.html +++ b/accessible/tests/mochitest/attributes/test_text.html @@ -269,13 +269,19 @@ attrs = {}; testTextAttrs(ID, 84, attrs, defAttrs, 83, 91); - attrs = { "text-underline-style": "solid" }; + attrs = { + "text-underline-style": "solid", + "text-underline-color": gComputedStyle.color + }; testTextAttrs(ID, 92, attrs, defAttrs, 91, 101); attrs = {}; testTextAttrs(ID, 102, attrs, defAttrs, 101, 109); - attrs = { "text-line-through-style": "solid" }; + attrs = { + "text-line-through-style": "solid", + "text-line-through-color": gComputedStyle.color + }; testTextAttrs(ID, 110, attrs, defAttrs, 109, 122); attrs = {}; @@ -323,13 +329,19 @@ attrs = {}; testTextAttrs(ID, 85, attrs, defAttrs, 84, 92); - attrs = { "text-underline-style": "solid" }; + attrs = { + "text-underline-style": "solid", + "text-underline-color": gComputedStyle.color + }; testTextAttrs(ID, 93, attrs, defAttrs, 92, 102); attrs = {}; testTextAttrs(ID, 103, attrs, defAttrs, 102, 110); - attrs = { "text-line-through-style": "solid" }; + attrs = { + "text-line-through-style": "solid", + "text-line-through-color": gComputedStyle.color + }; testTextAttrs(ID, 111, attrs, defAttrs, 110, 123); attrs = {}; @@ -437,6 +449,48 @@ attrs = { }; testTextAttrs(ID, 31, attrs, defAttrs, 31, 45); + ////////////////////////////////////////////////////////////////////////// + // area17, "text-decoration" tests + ID = "area17"; + defAttrs = buildDefaultTextAttrs(ID, "12pt"); + testDefaultTextAttrs(ID, defAttrs); + + attrs = { + "text-underline-style": "solid", + "text-underline-color": "rgb(0, 0, 0)", + }; + testTextAttrs(ID, 0, attrs, defAttrs, 0, 10); + + attrs = { + "text-underline-style": "solid", + "text-underline-color": "rgb(0, 0, 255)", + }; + testTextAttrs(ID, 10, attrs, defAttrs, 10, 15); + + attrs = { + "text-underline-style": "dotted", + "text-underline-color": "rgb(0, 0, 0)", + }; + testTextAttrs(ID, 15, attrs, defAttrs, 15, 22); + + attrs = { + "text-line-through-style": "solid", + "text-line-through-color": "rgb(0, 0, 0)", + }; + testTextAttrs(ID, 22, attrs, defAttrs, 22, 34); + + attrs = { + "text-line-through-style": "solid", + "text-line-through-color": "rgb(0, 0, 255)", + }; + testTextAttrs(ID, 34, attrs, defAttrs, 34, 39); + + attrs = { + "text-line-through-style": "wavy", + "text-line-through-color": "rgb(0, 0, 0)", + }; + testTextAttrs(ID, 39, attrs, defAttrs, 39, 44); + SimpleTest.finish(); } @@ -450,12 +504,17 @@ href="https://bugzilla.mozilla.org/show_bug.cgi?id=345759" title="Implement text attributes"> Mozilla Bug 345759 -
+ Mozilla Bug 473576 + + Mozilla Bug 523304 +

@@ -546,5 +605,15 @@
     texttext
     texttext
   

+ +

+ underline + blue + dotted + linethrough + blue + wavy + +

diff --git a/browser/base/content/browser-menubar.inc b/browser/base/content/browser-menubar.inc index c9b5ce07e1ed..a6adbdb85d7c 100644 --- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -291,12 +291,12 @@ - + @@ -2841,15 +2839,19 @@ this.parentNode && this.parentNode.localName == "toolbar" ? this.parentNode : this; ]]> + false + @@ -3080,6 +3082,9 @@ %debuggerDTD; ]> + + + + + + + + + + + + + + + + + +
diff --git a/browser/devtools/debugger/test/Makefile.in b/browser/devtools/debugger/test/Makefile.in index bb3e29eb67bb..0a96d99a7630 100644 --- a/browser/devtools/debugger/test/Makefile.in +++ b/browser/devtools/debugger/test/Makefile.in @@ -74,6 +74,7 @@ _BROWSER_TEST_FILES = \ browser_dbg_select-line.js \ browser_dbg_clean-exit.js \ browser_dbg_bug723069_editor-breakpoints.js \ + browser_dbg_bug731394_editor-contextmenu.js \ head.js \ $(NULL) diff --git a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js new file mode 100644 index 000000000000..e4be65aac2cf --- /dev/null +++ b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js @@ -0,0 +1,102 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Bug 731394: test the debugger source editor default context menu. + */ + +const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html"; + +let gPane = null; +let gTab = null; +let gDebuggee = null; +let gDebugger = null; + +function test() +{ + let tempScope = {}; + Cu.import("resource:///modules/source-editor.jsm", tempScope); + let SourceEditor = tempScope.SourceEditor; + + let contextMenu = null; + + debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) { + gTab = aTab; + gDebuggee = aDebuggee; + gPane = aPane; + gDebugger = gPane.debuggerWindow; + + gPane.activeThread.addOneTimeListener("scriptsadded", function() { + Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0); + }); + gDebuggee.firstCall(); + }); + + function onScriptsAdded() + { + let scripts = gDebugger.DebuggerView.Scripts._scripts; + + is(gDebugger.StackFrames.activeThread.state, "paused", + "Should only be getting stack frames while paused."); + + is(scripts.itemCount, 2, "Found the expected number of scripts."); + + let editor = gDebugger.editor; + + isnot(editor.getText().indexOf("debugger"), -1, + "The correct script was loaded initially."); + + contextMenu = gDebugger.document.getElementById("sourceEditorContextMenu"); + ok(contextMenu, "source editor context menupopup"); + ok(editor.readOnly, "editor is read only"); + + editor.focus(); + editor.setSelection(0, 10); + + contextMenu.addEventListener("popupshown", function onPopupShown() { + contextMenu.removeEventListener("popupshown", onPopupShown, false); + executeSoon(testContextMenu); + }, false); + contextMenu.openPopup(editor.editorElement, "overlap", 0, 0, true, false); + } + + function testContextMenu() + { + let document = gDebugger.document; + + ok(document.getElementById("editMenuCommands"), + "#editMenuCommands found"); + ok(!document.getElementById("editMenuKeys"), + "#editMenuKeys not found"); + ok(document.getElementById("sourceEditorCommands"), + "#sourceEditorCommands found"); + ok(document.getElementById("sourceEditorKeys"), + "#sourceEditorKeys found"); + + // Map command ids to their expected disabled state. + let commands = {"se-cmd-undo": true, "se-cmd-redo": true, + "se-cmd-cut": true, "se-cmd-paste": true, + "se-cmd-delete": true, "cmd_findAgain": true, + "cmd_findPrevious": true, "cmd_find": false, + "cmd_gotoLine": false, "cmd_copy": false, + "se-cmd-selectAll": false}; + for (let id in commands) { + let element = document.getElementById(id); + is(element.hasAttribute("disabled"), commands[id], + id + " hasAttribute('disabled') check"); + } + + executeSoon(function() { + contextMenu.hidePopup(); + gDebugger.StackFrames.activeThread.resume(finish); + }); + } + + registerCleanupFunction(function() { + removeTab(gTab); + gPane = null; + gTab = null; + gDebuggee = null; + gDebugger = null; + }); +} diff --git a/browser/devtools/jar.mn b/browser/devtools/jar.mn index 396a1b302e0e..8c918130825a 100644 --- a/browser/devtools/jar.mn +++ b/browser/devtools/jar.mn @@ -10,7 +10,7 @@ browser.jar: content/browser/devtools/cssruleview.xul (styleinspector/cssruleview.xul) content/browser/devtools/styleinspector.css (styleinspector/styleinspector.css) content/browser/orion.js (sourceeditor/orion/orion.js) - content/browser/source-editor-overlay.xul (sourceeditor/source-editor-overlay.xul) +* content/browser/source-editor-overlay.xul (sourceeditor/source-editor-overlay.xul) * content/browser/debugger.xul (debugger/debugger.xul) content/browser/debugger.css (debugger/debugger.css) content/browser/debugger.js (debugger/debugger.js) diff --git a/browser/devtools/scratchpad/scratchpad.xul b/browser/devtools/scratchpad/scratchpad.xul index 7efe53bed14e..d57cdf95c624 100644 --- a/browser/devtools/scratchpad/scratchpad.xul +++ b/browser/devtools/scratchpad/scratchpad.xul @@ -111,21 +111,6 @@ modifiers="accel"/> --> - - - - - - - - -#ifdef XP_MACOSX - - -#else - - -#endif @@ -219,56 +182,20 @@ - - + onpopupshowing="goUpdateSourceEditorMenuItems()"> + + - - - + + + - + - - + + - + @@ -338,13 +265,13 @@ - - - - + onpopupshowing="goUpdateSourceEditorMenuItems()"> + + + + - + - + diff --git a/browser/devtools/scratchpad/test/browser_scratchpad_bug_699130_edit_ui_updates.js b/browser/devtools/scratchpad/test/browser_scratchpad_bug_699130_edit_ui_updates.js index 72e58eb8b15c..4befa8d690f8 100644 --- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_699130_edit_ui_updates.js +++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_699130_edit_ui_updates.js @@ -27,7 +27,7 @@ function runTests() let doc = gScratchpadWindow.document; let winUtils = gScratchpadWindow.QueryInterface(Ci.nsIInterfaceRequestor). getInterface(Ci.nsIDOMWindowUtils); - let OS = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; + let OS = Services.appinfo.OS; info("will test the Edit menu"); @@ -51,9 +51,9 @@ function runTests() let menuPopup = editMenu.menupopup; ok(menuPopup, "the Edit menupopup"); - let cutItem = doc.getElementById("sp-menu-cut"); + let cutItem = doc.getElementById("se-menu-cut"); ok(cutItem, "the Cut menuitem"); - let pasteItem = doc.getElementById("sp-menu-paste"); + let pasteItem = doc.getElementById("se-menu-paste"); ok(pasteItem, "the Paste menuitem"); let anchor = doc.documentElement; @@ -174,9 +174,9 @@ function runTests() menuPopup = doc.getElementById("scratchpad-text-popup"); ok(menuPopup, "the context menupopup"); - cutItem = doc.getElementById("menu_cut"); + cutItem = doc.getElementById("se-cMenu-cut"); ok(cutItem, "the Cut menuitem"); - pasteItem = doc.getElementById("menu_paste"); + pasteItem = doc.getElementById("se-cMenu-paste"); ok(pasteItem, "the Paste menuitem"); sp.setText("bug 699130: hello world! (context menu)"); diff --git a/browser/devtools/sourceeditor/source-editor-orion.jsm b/browser/devtools/sourceeditor/source-editor-orion.jsm index e7dc16e24e13..fa0408c7c3ce 100644 --- a/browser/devtools/sourceeditor/source-editor-orion.jsm +++ b/browser/devtools/sourceeditor/source-editor-orion.jsm @@ -24,6 +24,7 @@ * Kenny Heaton * Spyros Livathinos * Allen Eubank + * Girish Sharma * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -63,6 +64,14 @@ const ORION_IFRAME = "data:text/html;charset=utf8," + const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; +/** + * Maximum allowed vertical offset for the line index when you call + * SourceEditor.setCaretPosition(). + * + * @type number + */ +const VERTICAL_OFFSET = 3; + /** * The primary selection update delay. On Linux, the X11 primary selection is * updated to hold the currently selected text. @@ -109,6 +118,10 @@ const ORION_ANNOTATION_TYPES = { * Default key bindings in the Orion editor. */ const DEFAULT_KEYBINDINGS = [ + { + action: "enter", + code: Ci.nsIDOMKeyEvent.DOM_VK_ENTER, + }, { action: "undo", code: Ci.nsIDOMKeyEvent.DOM_VK_Z, @@ -465,6 +478,10 @@ SourceEditor.prototype = { */ _doTab: function SE__doTab() { + if (this.readOnly) { + return false; + } + let indent = "\t"; let selection = this.getSelection(); let model = this._model; @@ -515,6 +532,10 @@ SourceEditor.prototype = { */ _doUnindentLines: function SE__doUnindentLines() { + if (this.readOnly) { + return true; + } + let indent = "\t"; let selection = this.getSelection(); @@ -569,6 +590,10 @@ SourceEditor.prototype = { */ _doEnter: function SE__doEnter() { + if (this.readOnly) { + return false; + } + let selection = this.getSelection(); if (selection.start != selection.end) { return false; @@ -1309,10 +1334,56 @@ SourceEditor.prototype = { * The new caret line location. Line numbers start from 0. * @param number [aColumn=0] * Optional. The new caret column location. Columns start from 0. + * @param number [aAlign=0] + * Optional. Position of the line with respect to viewport. + * Allowed values are: + * SourceEditor.VERTICAL_ALIGN.TOP target line at top of view. + * SourceEditor.VERTICAL_ALIGN.CENTER target line at center of view. + * SourceEditor.VERTICAL_ALIGN.BOTTOM target line at bottom of view. */ - setCaretPosition: function SE_setCaretPosition(aLine, aColumn) + setCaretPosition: function SE_setCaretPosition(aLine, aColumn, aAlign) { - this.setCaretOffset(this._model.getLineStart(aLine) + (aColumn || 0)); + let editorHeight = this._view.getClientArea().height; + let lineHeight = this._view.getLineHeight(); + let linesVisible = Math.floor(editorHeight/lineHeight); + let halfVisible = Math.round(linesVisible/2); + let firstVisible = this.getTopIndex(); + let lastVisible = this._view.getBottomIndex(); + let caretOffset = this._model.getLineStart(aLine) + (aColumn || 0); + + this._view.setSelection(caretOffset, caretOffset, false); + + // If the target line is in view, skip the vertical alignment part. + if (aLine <= lastVisible && aLine >= firstVisible) { + this._view.showSelection(); + return; + } + + // Setting the offset so that the line always falls in the upper half + // of visible lines (lower half for BOTTOM aligned). + // VERTICAL_OFFSET is the maximum allowed value. + let offset = Math.min(halfVisible, VERTICAL_OFFSET); + + let topIndex; + switch (aAlign) { + case this.VERTICAL_ALIGN.CENTER: + topIndex = Math.max(aLine - halfVisible, 0); + break; + + case this.VERTICAL_ALIGN.BOTTOM: + topIndex = Math.max(aLine - linesVisible + offset, 0); + break; + + default: // this.VERTICAL_ALIGN.TOP. + topIndex = Math.max(aLine - offset, 0); + break; + } + // Bringing down the topIndex to total lines in the editor if exceeding. + topIndex = Math.min(topIndex, this.getLineCount()); + this.setTopIndex(topIndex); + + let location = this._view.getLocationAtOffset(caretOffset); + this._view.setHorizontalPixel(location.x); }, /** diff --git a/browser/devtools/sourceeditor/source-editor-overlay.xul b/browser/devtools/sourceeditor/source-editor-overlay.xul index 52d2d0684a12..4533e82092b2 100644 --- a/browser/devtools/sourceeditor/source-editor-overlay.xul +++ b/browser/devtools/sourceeditor/source-editor-overlay.xul @@ -35,80 +35,203 @@ - the terms of any one of the MPL, the GPL or the LGPL. - - ***** END LICENSE BLOCK ***** --> - + + %editMenuStrings; + + %sourceEditorStrings; +]> + the source-editor-overlay.xul is loaded. Do not use #editMenuKeys to + avoid conflicts! --> + + + + + + + + +#ifdef XP_UNIX + +#else + +#endif + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/devtools/sourceeditor/source-editor-ui.jsm b/browser/devtools/sourceeditor/source-editor-ui.jsm index c28c590685d7..82fce6a88003 100644 --- a/browser/devtools/sourceeditor/source-editor-ui.jsm +++ b/browser/devtools/sourceeditor/source-editor-ui.jsm @@ -253,6 +253,10 @@ SourceEditorController.prototype = { case "cmd_gotoLine": case "se-cmd-undo": case "se-cmd-redo": + case "se-cmd-cut": + case "se-cmd-paste": + case "se-cmd-delete": + case "se-cmd-selectAll": result = true; break; default: @@ -278,6 +282,7 @@ SourceEditorController.prototype = { switch (aCommand) { case "cmd_find": case "cmd_gotoLine": + case "se-cmd-selectAll": result = true; break; case "cmd_findAgain": @@ -290,6 +295,19 @@ SourceEditorController.prototype = { case "se-cmd-redo": result = this._editor.canRedo(); break; + case "se-cmd-cut": + case "se-cmd-delete": { + let selection = this._editor.getSelection(); + result = selection.start != selection.end && !this._editor.readOnly; + break; + } + case "se-cmd-paste": { + let window = this._editor._view._frameWindow; + let controller = window.controllers.getControllerForCommand("cmd_paste"); + result = !this._editor.readOnly && + controller.isCommandEnabled("cmd_paste"); + break; + } default: result = false; break; @@ -320,12 +338,26 @@ SourceEditorController.prototype = { case "cmd_gotoLine": this._editor.ui.gotoLine(); break; + case "se-cmd-selectAll": + this._editor._view.invokeAction("selectAll"); + break; case "se-cmd-undo": this._editor.undo(); break; case "se-cmd-redo": this._editor.redo(); break; + case "se-cmd-cut": + this._editor.ui._ownerWindow.goDoCommand("cmd_cut"); + break; + case "se-cmd-paste": + this._editor.ui._ownerWindow.goDoCommand("cmd_paste"); + break; + case "se-cmd-delete": { + let selection = this._editor.getSelection(); + this._editor.setText("", selection.start, selection.end); + break; + } } }, diff --git a/browser/devtools/sourceeditor/source-editor.jsm b/browser/devtools/sourceeditor/source-editor.jsm index 7eb31982c65f..3f1598012566 100644 --- a/browser/devtools/sourceeditor/source-editor.jsm +++ b/browser/devtools/sourceeditor/source-editor.jsm @@ -312,6 +312,16 @@ SourceEditor.EVENTS = { DIRTY_CHANGED: "DirtyChanged", }; +/** + * Allowed vertical alignment options for the line index + * when you call SourceEditor.setCaretPosition(). + */ +SourceEditor.VERTICAL_ALIGN = { + TOP: 0, + CENTER: 1, + BOTTOM: 2, +}; + /** * Extend a destination object with properties from a source object. * @@ -336,6 +346,7 @@ extend(SourceEditor.prototype, { MODES: SourceEditor.MODES, THEMES: SourceEditor.THEMES, DEFAULTS: SourceEditor.DEFAULTS, + VERTICAL_ALIGN: SourceEditor.VERTICAL_ALIGN, _lastFind: null, diff --git a/browser/devtools/sourceeditor/test/Makefile.in b/browser/devtools/sourceeditor/test/Makefile.in index 94aaf9beea08..b7c1c5d2309c 100644 --- a/browser/devtools/sourceeditor/test/Makefile.in +++ b/browser/devtools/sourceeditor/test/Makefile.in @@ -60,6 +60,7 @@ _BROWSER_TEST_FILES = \ browser_bug712982_line_ruler_click.js \ browser_bug725618_moveLines_shortcut.js \ browser_bug700893_dirty_state.js \ + browser_bug729480_line_vertical_align.js \ head.js \ libs:: $(_BROWSER_TEST_FILES) diff --git a/browser/devtools/sourceeditor/test/browser_bug729480_line_vertical_align.js b/browser/devtools/sourceeditor/test/browser_bug729480_line_vertical_align.js new file mode 100644 index 000000000000..171141ba5217 --- /dev/null +++ b/browser/devtools/sourceeditor/test/browser_bug729480_line_vertical_align.js @@ -0,0 +1,99 @@ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +let tempScope = {}; +Cu.import("resource:///modules/source-editor.jsm", tempScope); +let SourceEditor = tempScope.SourceEditor; + +let testWin; +let editor; +const VERTICAL_OFFSET = 3; + +function test() +{ + waitForExplicitFinish(); + + const windowUrl = "data:application/vnd.mozilla.xul+xml," + + ""; + const windowFeatures = "chrome,titlebar,toolbar,centerscreen,dialog=no"; + + testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null); + testWin.addEventListener("load", function onWindowLoad() { + testWin.removeEventListener("load", onWindowLoad, false); + waitForFocus(initEditor, testWin); + }, false); +} + +function initEditor() +{ + let box = testWin.document.querySelector("box"); + + editor = new SourceEditor(); + editor.init(box, {showLineNumbers: true}, editorLoaded); +} + +function editorLoaded() +{ + editor.focus(); + + // setting 3 pages of lines containing the line number. + let view = editor._view; + + let lineHeight = view.getLineHeight(); + let editorHeight = view.getClientArea().height; + let linesPerPage = Math.floor(editorHeight / lineHeight); + let totalLines = 3 * linesPerPage; + + let text = ""; + for (let i = 0; i < totalLines; i++) { + text += "Line " + i + "\n"; + } + + editor.setText(text); + editor.setCaretOffset(0); + + let offset = Math.min(Math.round(linesPerPage/2), VERTICAL_OFFSET); + // Building the iterator array. + // [line, alignment, topIndex_check] + let iterateOn = [ + [0, "TOP", 0], + [25, "TOP", 25 - offset], + // Case when the target line is already in view. + [27, "TOP", 25 - offset], + [0, "BOTTOM", 0], + [5, "BOTTOM", 0], + [38, "BOTTOM", 38 - linesPerPage + offset], + [0, "CENTER", 0], + [4, "CENTER", 0], + [34, "CENTER", 34 - Math.round(linesPerPage/2)] + ]; + + function testEnd() { + editor.destroy(); + testWin.close(); + testWin = editor = null; + waitForFocus(finish, window); + } + + function testPosition(pos) { + is(editor.getTopIndex(), iterateOn[pos][2], "scroll is correct for test #" + pos); + iterator(++pos); + } + + function iterator(i) { + if (i == iterateOn.length) { + testEnd(); + } else { + editor.setCaretPosition(iterateOn[i][0], 0, + editor.VERTICAL_ALIGN[iterateOn[i][1]]); + executeSoon(testPosition.bind(this, i)); + } + } + iterator(0); +} diff --git a/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js b/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js index f2431f0e956f..92ec1fbce577 100644 --- a/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js +++ b/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js @@ -201,11 +201,21 @@ function editorLoaded() editor.setText("foobar"); is(editor.getText(), "foobar", "editor allows programmatic changes (setText)"); + EventUtils.synthesizeKey("VK_RETURN", {}, testWin); + is(editor.getText(), "foobar", "Enter key does nothing"); + + EventUtils.synthesizeKey("VK_TAB", {}, testWin); + is(editor.getText(), "foobar", "Tab does nothing"); + + editor.setText(" foobar"); + EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}, testWin); + is(editor.getText(), " foobar", "Shift+Tab does nothing"); + editor.readOnly = false; editor.setCaretOffset(editor.getCharCount()); EventUtils.synthesizeKey("-", {}, testWin); - is(editor.getText(), "foobar-", "editor is now editable again"); + is(editor.getText(), " foobar-", "editor is now editable again"); // Test the Selection event. diff --git a/browser/devtools/styleeditor/styleeditor.xul b/browser/devtools/styleeditor/styleeditor.xul index d27b9db46e1f..57c49cbc38f3 100644 --- a/browser/devtools/styleeditor/styleeditor.xul +++ b/browser/devtools/styleeditor/styleeditor.xul @@ -57,7 +57,22 @@ - + + + + + + + + + + + + + + + @@ -66,7 +81,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/browser/locales/en-US/chrome/browser/devtools/sourceeditor.dtd b/browser/locales/en-US/chrome/browser/devtools/sourceeditor.dtd index e26a92d2d5f8..e512028baa24 100644 --- a/browser/locales/en-US/chrome/browser/devtools/sourceeditor.dtd +++ b/browser/locales/en-US/chrome/browser/devtools/sourceeditor.dtd @@ -10,23 +10,6 @@ - A good criteria is the language in which you'd find the best - documentation on web development on the web. --> - - - - - - - - - - - - - - - - - diff --git a/browser/themes/gnomestripe/devtools/csshtmltree.css b/browser/themes/gnomestripe/devtools/csshtmltree.css index 0ee9c461260e..1cb385a2adf8 100644 --- a/browser/themes/gnomestripe/devtools/csshtmltree.css +++ b/browser/themes/gnomestripe/devtools/csshtmltree.css @@ -205,7 +205,7 @@ .ruleview-rule-source { background-color: -moz-dialog; - color: #0091ff; + color: -moz-dialogText; padding: 2px 5px; cursor: pointer; } diff --git a/browser/themes/pinstripe/devtools/csshtmltree.css b/browser/themes/pinstripe/devtools/csshtmltree.css index e40f46af7247..314c47b1fe4f 100644 --- a/browser/themes/pinstripe/devtools/csshtmltree.css +++ b/browser/themes/pinstripe/devtools/csshtmltree.css @@ -207,7 +207,7 @@ .ruleview-rule-source { background-color: -moz-dialog; - color: #0091ff; + color: -moz-dialogText; padding: 2px 5px; cursor: pointer; } diff --git a/browser/themes/winstripe/devtools/csshtmltree.css b/browser/themes/winstripe/devtools/csshtmltree.css index 42dce67568cc..a88a00803a2d 100644 --- a/browser/themes/winstripe/devtools/csshtmltree.css +++ b/browser/themes/winstripe/devtools/csshtmltree.css @@ -205,7 +205,7 @@ .ruleview-rule-source { background-color: -moz-dialog; - color: #0091ff; + color: -moz-dialogText; padding: 2px 5px; cursor: pointer; } diff --git a/configure.in b/configure.in index d1c61263d283..0a5dd86e59e5 100644 --- a/configure.in +++ b/configure.in @@ -4931,6 +4931,10 @@ MOZ_ARG_HEADER(Toolkit Options) AC_MSG_ERROR([You must specify a default toolkit (perhaps $_PLATFORM_DEFAULT_TOOLKIT).]) fi +MOZ_ARG_WITHOUT_BOOL(x, +[ --without-x Build without X11], + WITHOUT_X11=1) + dnl ======================================================== dnl = Enable the toolkit as needed = dnl ======================================================== @@ -4965,16 +4969,17 @@ cairo-gtk2|cairo-gtk2-x11) cairo-qt) MOZ_WIDGET_TOOLKIT=qt MOZ_ENABLE_QT=1 - MOZ_ENABLE_XREMOTE=1 + if test -z "$WITHOUT_X11"; then + MOZ_ENABLE_XREMOTE=1 + MOZ_WEBGL_GLX=1 + MOZ_X11=1 + AC_DEFINE(MOZ_X11) + XT_LIBS= + fi + MOZ_WEBGL=1 - MOZ_WEBGL_GLX=1 USE_ELF_DYNSTR_GC= - - AC_DEFINE(MOZ_X11) - MOZ_X11=1 USE_FC_FREETYPE=1 - XT_LIBS= - TK_CFLAGS='$(MOZ_QT_CFLAGS)' TK_LIBS='$(MOZ_QT_LIBS)' AC_DEFINE(MOZ_WIDGET_QT) @@ -8843,6 +8848,9 @@ fi dnl Check for missing components if test "$COMPILE_ENVIRONMENT"; then if test "$MOZ_X11"; then + if test "$WITHOUT_X11"; then + AC_MSG_ERROR([--without-x specified and MOZ_X11 still defined]) + fi dnl ==================================================== dnl = Check if X headers exist dnl ==================================================== diff --git a/content/base/public/CORSMode.h b/content/base/public/CORSMode.h new file mode 100644 index 000000000000..0bed540d90d5 --- /dev/null +++ b/content/base/public/CORSMode.h @@ -0,0 +1,32 @@ +/* -*- 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 CORSMode_h_ +#define CORSMode_h_ + +namespace mozilla { + +enum CORSMode { + /** + * The default of not using CORS to validate cross-origin loads. + */ + CORS_NONE, + + /** + * Validate cross-site loads using CORS, but do not send any credentials + * (cookies, HTTP auth logins, etc) along with the request. + */ + CORS_ANONYMOUS, + + /** + * Validate cross-site loads using CORS, and send credentials such as cookies + * and HTTP auth logins along with the request. + */ + CORS_USE_CREDENTIALS +}; + +} // namespace mozilla + +#endif /* CORSMode_h_ */ diff --git a/content/base/public/Makefile.in b/content/base/public/Makefile.in index 3a9f08e5275c..9d002e3cf6d0 100644 --- a/content/base/public/Makefile.in +++ b/content/base/public/Makefile.in @@ -79,13 +79,17 @@ nsXMLNameSpaceMap.h \ nsIXFormsUtilityService.h \ $(NULL) -EXPORTS_NAMESPACES = mozilla/dom +EXPORTS_NAMESPACES = mozilla/dom mozilla EXPORTS_mozilla/dom = \ Element.h \ FromParser.h \ $(NULL) +EXPORTS_mozilla = \ + CORSMode.h \ + $(NULL) + SDK_XPIDLSRCS = \ nsISelection.idl \ $(NULL) @@ -97,7 +101,6 @@ XPIDLSRCS = \ nsIDOMFileReader.idl \ nsIDOMFileList.idl \ nsIDOMFileException.idl \ - nsIDOMFileError.idl \ nsIDOMFormData.idl \ nsIDOMParser.idl \ nsIDOMSerializer.idl \ diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 4fdfaad807ad..ebad26965804 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1619,7 +1619,43 @@ public: * case for ASCII characters a-z. */ static bool EqualsIgnoreASCIICase(const nsAString& aStr1, - const nsAString& aStr2); + const nsAString& aStr2); + + /** + * Case insensitive comparison between a string and an ASCII literal. + * This must ONLY be applied to an actual literal string. Do not attempt + * to use it with a regular char* pointer, or with a char array variable. + * The template trick to acquire the array length at compile time without + * using a macro is due to Corey Kosak, which much thanks. + */ + static bool EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char* aStr2, + const PRUint32 len); +#ifdef NS_DISABLE_LITERAL_TEMPLATE + static inline bool + EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char* aStr2) + { + PRUint32 len = strlen(aStr2); + return EqualsLiteralIgnoreASCIICase(aStr1, aStr2, len); + } +#else + template + static inline bool + EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char (&aStr2)[N]) + { + return EqualsLiteralIgnoreASCIICase(aStr1, aStr2, N-1); + } + template + static inline bool + EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + char (&aStr2)[N]) + { + const char* s = aStr2; + return EqualsLiteralIgnoreASCIICase(aStr1, s, N-1); + } +#endif /** * Convert ASCII A-Z to a-z. diff --git a/content/base/public/nsDOMFile.h b/content/base/public/nsDOMFile.h index d188d4b2e51d..5614b8219d81 100644 --- a/content/base/public/nsDOMFile.h +++ b/content/base/public/nsDOMFile.h @@ -43,7 +43,6 @@ #include "nsIFile.h" #include "nsIDOMFile.h" #include "nsIDOMFileList.h" -#include "nsIDOMFileError.h" #include "nsIInputStream.h" #include "nsIJSNativeInitializer.h" #include "nsIMutable.h" @@ -53,12 +52,13 @@ #include "nsIXMLHttpRequest.h" #include "prmem.h" #include "nsAutoPtr.h" -#include "mozilla/dom/indexedDB/FileInfo.h" -#include "mozilla/dom/indexedDB/FileManager.h" -#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" #include "mozilla/GuardObjects.h" #include "mozilla/StandardInteger.h" +#include "mozilla/dom/DOMError.h" +#include "mozilla/dom/indexedDB/FileInfo.h" +#include "mozilla/dom/indexedDB/FileManager.h" +#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" class nsIFile; class nsIInputStream; @@ -363,18 +363,6 @@ private: nsCOMArray mFiles; }; -class nsDOMFileError : public nsIDOMFileError -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMFILEERROR - - nsDOMFileError(PRUint16 aErrorCode) : mCode(aErrorCode) {} - -private: - PRUint16 mCode; -}; - class NS_STACK_CLASS nsDOMFileInternalUrlHolder { public: nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal diff --git a/content/base/public/nsIDOMFileError.idl b/content/base/public/nsIDOMFileError.idl deleted file mode 100644 index 2bdd2fe21b46..000000000000 --- a/content/base/public/nsIDOMFileError.idl +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "domstubs.idl" - -[scriptable, uuid(4BDAFB64-15E2-49C1-A090-4315A7884A56)] -interface nsIDOMFileError : nsISupports -{ - const unsigned short NOT_FOUND_ERR = 1; - const unsigned short SECURITY_ERR = 2; - const unsigned short ABORT_ERR = 3; - const unsigned short NOT_READABLE_ERR = 4; - const unsigned short ENCODING_ERR = 5; - - readonly attribute unsigned short code; -}; diff --git a/content/base/public/nsIDOMFileReader.idl b/content/base/public/nsIDOMFileReader.idl index 56306a585ee0..1b62c648f51d 100644 --- a/content/base/public/nsIDOMFileReader.idl +++ b/content/base/public/nsIDOMFileReader.idl @@ -39,9 +39,9 @@ interface nsIDOMEventListener; interface nsIDOMBlob; -interface nsIDOMFileError; +interface nsIDOMDOMError; -[scriptable, builtinclass, uuid(d158de26-904e-4731-b42c-8b3a4d172703)] +[scriptable, builtinclass, uuid(faed1779-b523-4060-8c3b-7199f347b273)] interface nsIDOMFileReader : nsIDOMEventTarget { [implicit_jscontext] @@ -59,7 +59,7 @@ interface nsIDOMFileReader : nsIDOMEventTarget [implicit_jscontext] readonly attribute jsval result; - readonly attribute nsIDOMFileError error; + readonly attribute nsIDOMDOMError error; attribute nsIDOMEventListener onloadstart; attribute nsIDOMEventListener onprogress; diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 5402e6ef1f31..f7bbd9ab4d83 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -1424,7 +1424,8 @@ public: /** * Called by nsParser to preload images. Can be removed and code moved * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the - * parser-module is linked with gklayout-module. + * parser-module is linked with gklayout-module. aCrossOriginAttr should + * be a void string if the attr is not present. */ virtual void MaybePreLoadImage(nsIURI* uri, const nsAString& aCrossOriginAttr) = 0; diff --git a/content/base/public/nsIScriptElement.h b/content/base/public/nsIScriptElement.h index d15f0d2a50e8..e6c04b728468 100644 --- a/content/base/public/nsIScriptElement.h +++ b/content/base/public/nsIScriptElement.h @@ -47,6 +47,7 @@ #include "nsIParser.h" #include "nsContentCreatorFunctions.h" #include "nsIDOMHTMLScriptElement.h" +#include "mozilla/CORSMode.h" #define NS_ISCRIPTELEMENT_IID \ { 0x24ab3ff2, 0xd75e, 0x4be4, \ @@ -258,6 +259,15 @@ public: return block; } + /** + * Get the CORS mode of the script element + */ + virtual mozilla::CORSMode GetCORSMode() const + { + /* Default to no CORS */ + return mozilla::CORS_NONE; + } + protected: /** * Processes the script if it's in the document-tree and links to or diff --git a/content/base/src/FileIOObject.cpp b/content/base/src/FileIOObject.cpp index d1f5312db601..813507beadd2 100644 --- a/content/base/src/FileIOObject.cpp +++ b/content/base/src/FileIOObject.cpp @@ -119,13 +119,13 @@ FileIOObject::DispatchError(nsresult rv, nsAString& finalEvent) // Set the status attribute, and dispatch the error event switch (rv) { case NS_ERROR_FILE_NOT_FOUND: - mError = new nsDOMFileError(nsIDOMFileError::NOT_FOUND_ERR); + mError = DOMError::CreateWithName(NS_LITERAL_STRING("NotFoundError")); break; case NS_ERROR_FILE_ACCESS_DENIED: - mError = new nsDOMFileError(nsIDOMFileError::SECURITY_ERR); + mError = DOMError::CreateWithName(NS_LITERAL_STRING("SecurityError")); break; default: - mError = new nsDOMFileError(nsIDOMFileError::NOT_READABLE_ERR); + mError = DOMError::CreateWithName(NS_LITERAL_STRING("NotReadableError")); break; } @@ -258,14 +258,17 @@ FileIOObject::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, NS_IMETHODIMP FileIOObject::Abort() { - if (mReadyState != 1) + if (mReadyState != 1) { + // XXX The spec doesn't say this return NS_ERROR_DOM_FILE_ABORT_ERR; + } ClearProgressEventTimer(); mReadyState = 2; // There are DONE constants on multiple interfaces, // but they all have value 2. - mError = new nsDOMFileError(nsIDOMFileError::ABORT_ERR); + // XXX The spec doesn't say this + mError = DOMError::CreateWithName(NS_LITERAL_STRING("AbortError")); nsString finalEvent; nsresult rv = DoAbort(finalEvent); @@ -285,7 +288,7 @@ FileIOObject::GetReadyState(PRUint16 *aReadyState) } NS_IMETHODIMP -FileIOObject::GetError(nsIDOMFileError** aError) +FileIOObject::GetError(nsIDOMDOMError** aError) { NS_IF_ADDREF(*aError = mError); return NS_OK; diff --git a/content/base/src/FileIOObject.h b/content/base/src/FileIOObject.h index f5df017d4798..3e05dcbaed34 100644 --- a/content/base/src/FileIOObject.h +++ b/content/base/src/FileIOObject.h @@ -45,9 +45,10 @@ #include "nsIDOMFile.h" #include "nsIStreamListener.h" #include "nsITimer.h" - #include "nsCOMPtr.h" +#include "mozilla/dom/DOMError.h" + #define NS_PROGRESS_EVENT_INTERVAL 50 namespace mozilla { @@ -69,7 +70,7 @@ public: // Common methods NS_METHOD Abort(); NS_METHOD GetReadyState(PRUint16* aReadyState); - NS_METHOD GetError(nsIDOMFileError** aError); + NS_METHOD GetError(nsIDOMDOMError** aError); NS_DECL_AND_IMPL_EVENT_HANDLER(abort); NS_DECL_AND_IMPL_EVENT_HANDLER(error); @@ -108,7 +109,7 @@ protected: bool mProgressEventWasDelayed; bool mTimerIsActive; - nsCOMPtr mError; + nsCOMPtr mError; nsCOMPtr mChannel; PRUint16 mReadyState; diff --git a/content/base/src/nsAttrValue.cpp b/content/base/src/nsAttrValue.cpp index 53dffd927e4d..4b80af50f591 100644 --- a/content/base/src/nsAttrValue.cpp +++ b/content/base/src/nsAttrValue.cpp @@ -714,7 +714,7 @@ nsAttrValue::GetEnumString(nsAString& aResult, bool aRealTag) const if (table->value == val) { aResult.AssignASCII(table->tag); if (!aRealTag && allEnumBits & NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER) { - ToUpperCase(aResult); + nsContentUtils::ASCIIToUpper(aResult); } return; } @@ -1316,7 +1316,7 @@ nsAttrValue::ParseEnumValue(const nsAString& aValue, if (!equals) { nsAutoString tag; tag.AssignASCII(tableEntry->tag); - ToUpperCase(tag); + nsContentUtils::ASCIIToUpper(tag); if ((equals = tag.Equals(aValue))) { value |= NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER; } diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index 601e7829c0c2..768acbce10f6 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -617,8 +617,9 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement, if (media.IsEmpty()) { media = value; - // HTML4.0 spec is inconsistent, make it case INSENSITIVE - ToLowerCase(media); + // The HTML5 spec is formulated in terms of the CSS3 spec, + // which specifies that media queries are case insensitive. + nsContentUtils::ASCIIToLower(media); } } else if (attr.LowerCaseEqualsLiteral("anchor")) { if (anchor.IsEmpty()) { @@ -757,7 +758,7 @@ nsContentSink::ProcessMETATag(nsIContent* aContent) nsAutoString result; aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result); if (!result.IsEmpty()) { - ToLowerCase(header); + nsContentUtils::ASCIIToLower(header); nsCOMPtr fieldAtom(do_GetAtom(header)); rv = ProcessHeaderData(fieldAtom, result, aContent); } @@ -769,7 +770,7 @@ nsContentSink::ProcessMETATag(nsIContent* aContent) nsAutoString result; aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result); if (!result.IsEmpty()) { - ToLowerCase(result); + nsContentUtils::ASCIIToLower(result); mDocument->SetHeaderData(nsGkAtoms::handheldFriendly, result); } } diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 3c764c9c32fa..673b1488e41c 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -5393,6 +5393,7 @@ nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) } } +/* static */ bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, const nsAString& aStr2) @@ -5415,7 +5416,7 @@ nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, return false; } - // We know they only differ in the 0x0020 bit. + // We know they can only differ in the 0x0020 bit. // Likely the two chars are the same, so check that first if (c1 != c2) { // They do differ, but since it's only in the 0x0020 bit, check if it's @@ -5430,6 +5431,44 @@ nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, return true; } +/* static */ +bool +nsContentUtils::EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char* aStr2, + const PRUint32 len) +{ + if (aStr1.Length() != len) { + return false; + } + + const PRUnichar* str1 = aStr1.BeginReading(); + const char* str2 = aStr2; + const PRUnichar* end = str1 + len; + + while (str1 < end) { + PRUnichar c1 = *str1++; + PRUnichar c2 = *str2++; + + // First check if any bits other than the 0x0020 differs + if ((c1 ^ c2) & 0xffdf) { + return false; + } + + // We know they can only differ in the 0x0020 bit. + // Likely the two chars are the same, so check that first + if (c1 != c2) { + // They do differ, but since it's only in the 0x0020 bit, check if it's + // the same ascii char, but just differing in case + PRUnichar c1Upper = c1 & 0xffdf; + if (!('A' <= c1Upper && c1Upper <= 'Z')) { + return false; + } + } + } + + return true; +} + /* static */ nsIInterfaceRequestor* nsContentUtils::GetSameOriginChecker() diff --git a/content/base/src/nsDOMAttribute.cpp b/content/base/src/nsDOMAttribute.cpp index 77795865214e..77d13ae228bb 100644 --- a/content/base/src/nsDOMAttribute.cpp +++ b/content/base/src/nsDOMAttribute.cpp @@ -210,11 +210,11 @@ nsDOMAttribute::GetNameAtom(nsIContent* aContent) mNodeInfo->NamespaceID() == kNameSpaceID_None && aContent->IsInHTMLDocument() && aContent->IsHTML()) { - nsAutoString name; - mNodeInfo->NameAtom()->ToString(name); - nsAutoString lower; - ToLowerCase(name, lower); - nsCOMPtr nameAtom = do_GetAtom(lower); + nsString name; + mNodeInfo->GetName(name); + nsAutoString lowercaseName; + nsContentUtils::ASCIIToLower(name, lowercaseName); + nsCOMPtr nameAtom = do_GetAtom(lowercaseName); nameAtom.swap(result); } else { nsCOMPtr nameAtom = mNodeInfo->NameAtom(); diff --git a/content/base/src/nsDOMAttributeMap.cpp b/content/base/src/nsDOMAttributeMap.cpp index 6a6d442d643b..f0617a0e5fa5 100644 --- a/content/base/src/nsDOMAttributeMap.cpp +++ b/content/base/src/nsDOMAttributeMap.cpp @@ -335,9 +335,7 @@ nsDOMAttributeMap::SetNamedItemInternal(nsIDOMNode *aNode, else { if (mContent->IsInHTMLDocument() && mContent->IsHTML()) { - nsAutoString lower; - ToLowerCase(name, lower); - name = lower; + nsContentUtils::ASCIIToLower(name); } rv = mContent->NodeInfo()->NodeInfoManager()-> diff --git a/content/base/src/nsDOMFile.cpp b/content/base/src/nsDOMFile.cpp index a5a8786d9c9f..0919c88cd8ea 100644 --- a/content/base/src/nsDOMFile.cpp +++ b/content/base/src/nsDOMFile.cpp @@ -632,27 +632,6 @@ nsDOMFileList::Item(PRUint32 aIndex, nsIDOMFile **aFile) return NS_OK; } -//////////////////////////////////////////////////////////////////////////// -// nsDOMFileError implementation - -DOMCI_DATA(FileError, nsDOMFileError) - -NS_INTERFACE_MAP_BEGIN(nsDOMFileError) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMFileError) - NS_INTERFACE_MAP_ENTRY(nsIDOMFileError) - NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(FileError) -NS_INTERFACE_MAP_END - -NS_IMPL_ADDREF(nsDOMFileError) -NS_IMPL_RELEASE(nsDOMFileError) - -NS_IMETHODIMP -nsDOMFileError::GetCode(PRUint16* aCode) -{ - *aCode = mCode; - return NS_OK; -} - //////////////////////////////////////////////////////////////////////////// // nsDOMFileInternalUrlHolder implementation diff --git a/content/base/src/nsDOMFileReader.cpp b/content/base/src/nsDOMFileReader.cpp index 48f42da41bd2..6324b968eb0a 100644 --- a/content/base/src/nsDOMFileReader.cpp +++ b/content/base/src/nsDOMFileReader.cpp @@ -255,7 +255,7 @@ nsDOMFileReader::GetResult(JSContext* aCx, jsval* aResult) } NS_IMETHODIMP -nsDOMFileReader::GetError(nsIDOMFileError** aError) +nsDOMFileReader::GetError(nsIDOMDOMError** aError) { return FileIOObject::GetError(aError); } diff --git a/content/base/src/nsDOMFileReader.h b/content/base/src/nsDOMFileReader.h index 38dbe5bfd475..78e29813e512 100644 --- a/content/base/src/nsDOMFileReader.h +++ b/content/base/src/nsDOMFileReader.h @@ -54,7 +54,6 @@ #include "nsIDOMFile.h" #include "nsIDOMFileReader.h" #include "nsIDOMFileList.h" -#include "nsIDOMFileError.h" #include "nsIInputStream.h" #include "nsCOMPtr.h" #include "nsIStreamLoader.h" diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 9cbbd96a346c..7b0f63a0a6ca 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3247,6 +3247,14 @@ nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks) mFrameRequestCallbacks.Clear(); } +PLDHashOperator RequestDiscardEnumerator(imgIRequest* aKey, + PRUint32 aData, + void* userArg) +{ + aKey->RequestDiscard(); + return PL_DHASH_NEXT; +} + void nsDocument::DeleteShell() { @@ -3255,6 +3263,11 @@ nsDocument::DeleteShell() RevokeAnimationFrameNotifications(); } + // When our shell goes away, request that all our images be immediately + // discarded, so we don't carry around decoded image data for a document we + // no longer intend to paint. + mImageTracker.EnumerateRead(RequestDiscardEnumerator, nsnull); + mPresShell = nsnull; } @@ -4414,7 +4427,7 @@ nsDocument::CreateElement(const nsAString& aTagName, bool needsLowercase = IsHTML() && !IsLowercaseASCII(aTagName); nsAutoString lcTagName; if (needsLowercase) { - ToLowerCase(aTagName, lcTagName); + nsContentUtils::ASCIIToLower(aTagName, lcTagName); } rv = CreateElem(needsLowercase ? lcTagName : aTagName, @@ -7724,14 +7737,20 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr) } nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL; - if (aCrossOriginAttr.LowerCaseEqualsLiteral("anonymous")) { + switch (nsGenericElement::StringToCORSMode(aCrossOriginAttr)) { + case CORS_NONE: + // Nothing to do + break; + case CORS_ANONYMOUS: loadFlags |= imgILoader::LOAD_CORS_ANONYMOUS; - } else if (aCrossOriginAttr.LowerCaseEqualsLiteral("use-credentials")) { + break; + case CORS_USE_CREDENTIALS: loadFlags |= imgILoader::LOAD_CORS_USE_CREDENTIALS; + break; + default: + /* should never happen */ + MOZ_NOT_REACHED("Unknown CORS mode!"); } - // else should we err on the side of not doing the preload if - // aCrossOriginAttr is nonempty? Let's err on the side of doing the - // preload as CORS_NONE. // Image not in cache - trigger preload nsCOMPtr request; @@ -8309,26 +8328,32 @@ nsDocument::RemoveImage(imgIRequest* aImage) // If the count is now zero, remove from the tracker. // Otherwise, set the new value. - if (count == 0) { - mImageTracker.Remove(aImage); - } else { + if (count != 0) { mImageTracker.Put(aImage, count); + return NS_OK; } + mImageTracker.Remove(aImage); + nsresult rv = NS_OK; - // If we removed the image from the tracker and we're locking images, unlock - // this image. - if (count == 0 && mLockingImages) + // Now that we're no longer tracking this image, unlock it if we'd + // previously locked it. + if (mLockingImages) { rv = aImage->UnlockImage(); + } - // If we removed the image from the tracker and we're animating images, - // remove our request to animate this image. - if (count == 0 && mAnimatingImages) { + // If we're animating images, remove our request to animate this one. + if (mAnimatingImages) { nsresult rv2 = aImage->DecrementAnimationConsumers(); rv = NS_SUCCEEDED(rv) ? rv2 : rv; } + // Request that the image be discarded if nobody else holds a lock on it. + // Do this even if !mLockingImages, because even if we didn't just unlock + // this image, it might still be a candidate for discarding. + aImage->RequestDiscard(); + return rv; } diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 88f1167a93d0..0badc1cd79f9 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -159,6 +159,8 @@ #include "nsLayoutStatics.h" #include "mozilla/Telemetry.h" +#include "mozilla/CORSMode.h" + using namespace mozilla; using namespace mozilla::dom; @@ -2853,15 +2855,16 @@ nsGenericElement::GetAttributeNS(const nsAString& aNamespaceURI, nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI); if (nsid == kNameSpaceID_Unknown) { - // Unknown namespace means no attr... - - aReturn.Truncate(); - + // Unknown namespace means no attribute. + SetDOMStringToNull(aReturn); return NS_OK; } nsCOMPtr name = do_GetAtom(aLocalName); - GetAttr(nsid, name, aReturn); + bool hasAttr = GetAttr(nsid, name, aReturn); + if (!hasAttr) { + SetDOMStringToNull(aReturn); + } return NS_OK; } @@ -6235,6 +6238,48 @@ nsGenericElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf); } +static const nsAttrValue::EnumTable kCORSAttributeTable[] = { + // Order matters here + // See ParseCORSValue + { "anonymous", CORS_ANONYMOUS }, + { "use-credentials", CORS_USE_CREDENTIALS }, + { 0 } +}; + +/* static */ void +nsGenericElement::ParseCORSValue(const nsAString& aValue, + nsAttrValue& aResult) +{ + DebugOnly success = + aResult.ParseEnumValue(aValue, kCORSAttributeTable, false, + // default value is anonymous if aValue is + // not a value we understand + &kCORSAttributeTable[0]); + MOZ_ASSERT(success); +} + +/* static */ CORSMode +nsGenericElement::StringToCORSMode(const nsAString& aValue) +{ + if (aValue.IsVoid()) { + return CORS_NONE; + } + + nsAttrValue val; + nsGenericElement::ParseCORSValue(aValue, val); + return CORSMode(val.GetEnumValue()); +} + +/* static */ CORSMode +nsGenericElement::AttrValueToCORSMode(const nsAttrValue* aValue) +{ + if (!aValue) { + return CORS_NONE; + } + + return CORSMode(aValue->GetEnumValue()); +} + #define EVENT(name_, id_, type_, struct_) \ NS_IMETHODIMP nsINode::GetOn##name_(JSContext *cx, jsval *vp) { \ nsEventListenerManager *elm = GetListenerManager(false); \ diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index 9553c667bbcc..0f6edf692548 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -65,6 +65,7 @@ #include "nsDOMClassInfoID.h" // DOMCI_DATA #include "nsIDOMTouchEvent.h" #include "nsIInlineEventHandlers.h" +#include "mozilla/CORSMode.h" #include "nsISMILAttr.h" @@ -640,6 +641,25 @@ public: void *aData); static void MarkUserDataHandler(void* aObject, nsIAtom* aKey, void* aChild, void* aData); + + /** + * Parse a string into an nsAttrValue for a CORS attribute. This + * never fails. The resulting value is an enumerated value whose + * GetEnumValue() returns one of the above constants. + */ + static void ParseCORSValue(const nsAString& aValue, nsAttrValue& aResult); + + /** + * Return the CORS mode for a given string + */ + static mozilla::CORSMode StringToCORSMode(const nsAString& aValue); + + /** + * Return the CORS mode for a given nsAttrValue (which may be null, + * but if not should have been parsed via ParseCORSValue). + */ + static mozilla::CORSMode AttrValueToCORSMode(const nsAttrValue* aValue); + protected: /* * Named-bools for use with SetAttrAndNotify to make call sites easier to diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 18578f3a1626..dd3c5afac423 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -2004,8 +2004,10 @@ GK_ATOM(setsize, "setsize") GK_ATOM(tableCellIndex, "table-cell-index") GK_ATOM(textAlign, "text-align") GK_ATOM(textIndent, "text-indent") +GK_ATOM(textLineThroughColor, "text-line-through-color") GK_ATOM(textLineThroughStyle, "text-line-through-style") GK_ATOM(textPosition, "text-position") +GK_ATOM(textUnderlineColor, "text-underline-color") GK_ATOM(textUnderlineStyle, "text-underline-style") GK_ATOM(toolbarname, "toolbarname") GK_ATOM(toolbarseparator, "toolbarseparator") diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp index c7acfb4a11fe..b41e25812392 100644 --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -60,7 +60,7 @@ #include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsAsyncDOMEvent.h" -#include "nsGenericHTMLElement.h" +#include "nsGenericElement.h" #include "nsIPresShell.h" #include "nsEventStates.h" @@ -82,6 +82,8 @@ #include "mozAutoDocUpdate.h" #include "mozilla/dom/Element.h" +using namespace mozilla; + #ifdef DEBUG_chb static void PrintReqURL(imgIRequest* req) { if (!req) { @@ -775,9 +777,9 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI, nsLoadFlags loadFlags = aLoadFlags; PRInt32 corsmode = GetCORSMode(); - if (corsmode == nsGenericHTMLElement::CORS_ANONYMOUS) { + if (corsmode == CORS_ANONYMOUS) { loadFlags |= imgILoader::LOAD_CORS_ANONYMOUS; - } else if (corsmode == nsGenericHTMLElement::CORS_USE_CREDENTIALS) { + } else if (corsmode == CORS_USE_CREDENTIALS) { loadFlags |= imgILoader::LOAD_CORS_USE_CREDENTIALS; } @@ -1187,8 +1189,8 @@ nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) cons aDest->mSuppressed = mSuppressed; } -nsGenericHTMLElement::CORSMode +CORSMode nsImageLoadingContent::GetCORSMode() { - return nsGenericHTMLElement::CORS_NONE; + return CORS_NONE; } diff --git a/content/base/src/nsImageLoadingContent.h b/content/base/src/nsImageLoadingContent.h index 415afe9b7a39..cc788a759f39 100644 --- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -54,6 +54,7 @@ #include "nsString.h" #include "nsEventStates.h" #include "nsGenericHTMLElement.h" +#include "mozilla/CORSMode.h" class nsIURI; class nsIDocument; @@ -183,7 +184,7 @@ protected: * Returns the CORS mode that will be used for all future image loads. The * default implementation returns CORS_NONE unconditionally. */ - virtual nsGenericHTMLElement::CORSMode GetCORSMode(); + virtual mozilla::CORSMode GetCORSMode(); private: /** diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 34b1fce8cc0b..b7559322cb28 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -74,13 +74,17 @@ #include "nsChannelPolicy.h" #include "nsCRT.h" #include "nsContentCreatorFunctions.h" +#include "nsGenericElement.h" +#include "nsCrossSiteListenerProxy.h" #include "mozilla/FunctionTimer.h" +#include "mozilla/CORSMode.h" #ifdef PR_LOGGING static PRLogModuleInfo* gCspPRLog; #endif +using namespace mozilla; using namespace mozilla::dom; ////////////////////////////////////////////////////////////// @@ -90,11 +94,14 @@ using namespace mozilla::dom; class nsScriptLoadRequest : public nsISupports { public: nsScriptLoadRequest(nsIScriptElement* aElement, - PRUint32 aVersion) + PRUint32 aVersion, + CORSMode aCORSMode) : mElement(aElement), mLoading(true), mIsInline(true), - mJSVersion(aVersion), mLineNo(1) + mJSVersion(aVersion), + mLineNo(1), + mCORSMode(aCORSMode) { } @@ -122,6 +129,7 @@ public: nsCOMPtr mURI; nsCOMPtr mOriginPrincipal; PRInt32 mLineNo; + const CORSMode mCORSMode; }; // The nsScriptLoadRequest is passed as the context to necko, and thus @@ -293,7 +301,6 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType) } nsCOMPtr loadGroup = mDocument->GetDocumentLoadGroup(); - nsCOMPtr loader; nsCOMPtr window(do_QueryInterface(mDocument->GetScriptGlobalObject())); if (!window) { @@ -332,10 +339,21 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType) httpChannel->SetReferrer(mDocument->GetDocumentURI()); } + nsCOMPtr loader; rv = NS_NewStreamLoader(getter_AddRefs(loader), this); NS_ENSURE_SUCCESS(rv, rv); - rv = channel->AsyncOpen(loader, aRequest); + nsCOMPtr listener = loader.get(); + + if (aRequest->mCORSMode != CORS_NONE) { + bool withCredentials = (aRequest->mCORSMode == CORS_USE_CREDENTIALS); + listener = + new nsCORSListenerProxy(listener, mDocument->NodePrincipal(), channel, + withCredentials, &rv); + NS_ENSURE_SUCCESS(rv, rv); + } + + rv = channel->AsyncOpen(listener, aRequest); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -551,6 +569,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) if (!scriptURI) { return false; } + CORSMode ourCORSMode = aElement->GetCORSMode(); nsTArray::index_type i = mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator()); if (i != nsTArray::NoIndex) { @@ -565,7 +584,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) // the charset we have now. nsAutoString elementCharset; aElement->GetScriptCharset(elementCharset); - if (elementCharset.Equals(preloadCharset)) { + if (elementCharset.Equals(preloadCharset) && + ourCORSMode == request->mCORSMode) { rv = CheckContentPolicy(mDocument, aElement, request->mURI, type); NS_ENSURE_SUCCESS(rv, false); } else { @@ -576,7 +596,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) if (!request) { // no usable preload - request = new nsScriptLoadRequest(aElement, version); + request = new nsScriptLoadRequest(aElement, version, ourCORSMode); request->mURI = scriptURI; request->mIsInline = false; request->mLoading = true; @@ -697,7 +717,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) } } - request = new nsScriptLoadRequest(aElement, version); + // Inline scripts ignore ther CORS mode and are always CORS_NONE + request = new nsScriptLoadRequest(aElement, version, CORS_NONE); request->mJSVersion = version; request->mLoading = false; request->mIsInline = true; @@ -1228,9 +1249,14 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest, } nsCOMPtr channel = do_QueryInterface(req); - rv = nsContentUtils::GetSecurityManager()-> - GetChannelPrincipal(channel, getter_AddRefs(aRequest->mOriginPrincipal)); - NS_ENSURE_SUCCESS(rv, rv); + // If this load was subject to a CORS check; don't flag it with a + // separate origin principal, so that it will treat our document's + // principal as the origin principal + if (aRequest->mCORSMode == CORS_NONE) { + rv = nsContentUtils::GetSecurityManager()-> + GetChannelPrincipal(channel, getter_AddRefs(aRequest->mOriginPrincipal)); + NS_ENSURE_SUCCESS(rv, rv); + } if (aStringLen) { // Check the charset attribute to determine script charset. @@ -1325,14 +1351,17 @@ nsScriptLoader::ParsingComplete(bool aTerminated) void nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset, - const nsAString &aType) + const nsAString &aType, + const nsAString &aCrossOrigin) { // Check to see if scripts has been turned off. if (!mEnabled || !mDocument->IsScriptEnabled()) { return; } - nsRefPtr request = new nsScriptLoadRequest(nsnull, 0); + nsRefPtr request = + new nsScriptLoadRequest(nsnull, 0, + nsGenericElement::StringToCORSMode(aCrossOrigin)); request->mURI = aURI; request->mIsInline = false; request->mLoading = true; diff --git a/content/base/src/nsScriptLoader.h b/content/base/src/nsScriptLoader.h index d8963249a04a..3d882b944d03 100644 --- a/content/base/src/nsScriptLoader.h +++ b/content/base/src/nsScriptLoader.h @@ -238,9 +238,12 @@ public: * @param aURI The URI of the external script. * @param aCharset The charset parameter for the script. * @param aType The type parameter for the script. + * @param aCrossOrigin The crossorigin attribute for the script. + * Void if not present. */ virtual void PreloadURI(nsIURI *aURI, const nsAString &aCharset, - const nsAString &aType); + const nsAString &aType, + const nsAString &aCrossOrigin); private: /** diff --git a/content/base/src/nsStyleLinkElement.cpp b/content/base/src/nsStyleLinkElement.cpp index 9cb62d9cfd4d..36e923811ba1 100644 --- a/content/base/src/nsStyleLinkElement.cpp +++ b/content/base/src/nsStyleLinkElement.cpp @@ -185,7 +185,7 @@ PRUint32 nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes) while (current != done) { if (nsContentUtils::IsHTMLWhitespace(*current)) { if (inString) { - ToLowerCase(Substring(start, current), subString); + nsContentUtils::ASCIIToLower(Substring(start, current), subString); linkMask |= ToLinkMask(subString); inString = false; } @@ -199,8 +199,8 @@ PRUint32 nsStyleLinkElement::ParseLinkTypes(const nsAString& aTypes) ++current; } if (inString) { - ToLowerCase(Substring(start, current), subString); - linkMask |= ToLinkMask(subString); + nsContentUtils::ASCIIToLower(Substring(start, current), subString); + linkMask |= ToLinkMask(subString); } return linkMask; } diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index a97f7a6e49db..cf348b28ef43 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -562,6 +562,11 @@ _TEST_FILES2 = \ test_bug726364.html \ test_bug698381.html \ test_bug711047.html \ + test_bug696301-1.html \ + test_bug696301-2.html \ + bug696301-script-1.js \ + bug696301-script-1.js^headers^ \ + bug696301-script-2.js \ $(NULL) _CHROME_FILES = \ diff --git a/content/base/test/bug696301-script-1.js b/content/base/test/bug696301-script-1.js new file mode 100644 index 000000000000..b139b2fdfd33 --- /dev/null +++ b/content/base/test/bug696301-script-1.js @@ -0,0 +1,3 @@ +var a = 0; +var global = "ran"; +c(); \ No newline at end of file diff --git a/content/base/test/bug696301-script-1.js^headers^ b/content/base/test/bug696301-script-1.js^headers^ new file mode 100644 index 000000000000..cb762eff8068 --- /dev/null +++ b/content/base/test/bug696301-script-1.js^headers^ @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/content/base/test/bug696301-script-2.js b/content/base/test/bug696301-script-2.js new file mode 100644 index 000000000000..b139b2fdfd33 --- /dev/null +++ b/content/base/test/bug696301-script-2.js @@ -0,0 +1,3 @@ +var a = 0; +var global = "ran"; +c(); \ No newline at end of file diff --git a/content/base/test/test_bug696301-1.html b/content/base/test/test_bug696301-1.html new file mode 100644 index 000000000000..01b6c584d1a2 --- /dev/null +++ b/content/base/test/test_bug696301-1.html @@ -0,0 +1,78 @@ + + + + + + Test for Bug 696301 + + + + +Mozilla Bug 696301 +

+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/content/base/test/test_bug696301-2.html b/content/base/test/test_bug696301-2.html new file mode 100644 index 000000000000..c03e7d6e5068 --- /dev/null +++ b/content/base/test/test_bug696301-2.html @@ -0,0 +1,80 @@ + + + + + + Test for Bug 696301 + + + + +Mozilla Bug 696301 +

+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/content/canvas/crashtests/crashtests.list b/content/canvas/crashtests/crashtests.list index feb59687d5cd..00749276dcb8 100644 --- a/content/canvas/crashtests/crashtests.list +++ b/content/canvas/crashtests/crashtests.list @@ -3,4 +3,5 @@ load 421715-1.html load 553938-1.html load 647480.html load 0px-size-font-667225.html +load texImage2D.html load 729116.html diff --git a/content/canvas/crashtests/texImage2D.html b/content/canvas/crashtests/texImage2D.html new file mode 100644 index 000000000000..370b0085720a --- /dev/null +++ b/content/canvas/crashtests/texImage2D.html @@ -0,0 +1,8 @@ + + + diff --git a/content/canvas/src/CustomQS_WebGL.h b/content/canvas/src/CustomQS_WebGL.h index 507dc957db5b..6d21d6e08a43 100644 --- a/content/canvas/src/CustomQS_WebGL.h +++ b/content/canvas/src/CustomQS_WebGL.h @@ -382,6 +382,133 @@ nsIDOMWebGLRenderingContext_ReadPixels(JSContext *cx, unsigned argc, jsval *vp) } +class CallTexImage2D +{ +private: + nsIDOMWebGLRenderingContext* self; + WebGLenum target; + WebGLint level; + WebGLenum internalformat; + WebGLenum format; + WebGLenum type; + +public: + explicit CallTexImage2D(nsIDOMWebGLRenderingContext* aSelf, + WebGLenum aTarget, + WebGLint aLevel, + WebGLenum aInternalformat, + WebGLenum aFormat, + WebGLenum aType) + : self(aSelf) + , target(aTarget) + , level(aLevel) + , internalformat(aInternalformat) + , format(aFormat) + , type(aType) + {} + + nsresult DoCallForImageData(WebGLsizei width, WebGLsizei height, + JSObject* pixels) + { + return self->TexImage2D_imageData(target, level, internalformat, width, + height, 0, format, type, pixels); + } + nsresult DoCallForElement(mozilla::dom::Element* elt) + { + return self->TexImage2D_dom(target, level, internalformat, format, type, + elt); + } +}; + +class CallTexSubImage2D +{ +private: + nsIDOMWebGLRenderingContext* self; + WebGLenum target; + WebGLint level; + WebGLint xoffset; + WebGLint yoffset; + WebGLenum format; + WebGLenum type; + +public: + explicit CallTexSubImage2D(nsIDOMWebGLRenderingContext* aSelf, + WebGLenum aTarget, + WebGLint aLevel, + WebGLint aXoffset, + WebGLint aYoffset, + WebGLenum aFormat, + WebGLenum aType) + + : self(aSelf) + , target(aTarget) + , level(aLevel) + , xoffset(aXoffset) + , yoffset(aYoffset) + , format(aFormat) + , type(aType) + {} + + nsresult DoCallForImageData(WebGLsizei width, WebGLsizei height, + JSObject* pixels) + { + return self->TexSubImage2D_imageData(target, level, xoffset, yoffset, + width, height, format, type, + pixels); + } + nsresult DoCallForElement(mozilla::dom::Element* elt) + { + return self->TexSubImage2D_dom(target, level, xoffset, yoffset, format, + type, elt); + } +}; + +template +static bool +TexImage2DImageDataOrElement(JSContext* cx, T& self, JS::Value* object) +{ + MOZ_ASSERT(object && object->isObject()); + + nsGenericElement* elt; + xpc_qsSelfRef eltRef; + if (NS_SUCCEEDED(xpc_qsUnwrapArg( + cx, *object, &elt, &eltRef.ptr, object))) { + nsresult rv = self.DoCallForElement(elt); + return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv); + } + + // Failed to interpret object as an Element, now try to interpret it as + // ImageData. + JSObject* imageData = &object->toObject(); + + jsval js_width, js_height, js_data; + if (!JS_GetProperty(cx, imageData, "width", &js_width) || + !JS_GetProperty(cx, imageData, "height", &js_height) || + !JS_GetProperty(cx, imageData, "data", &js_data)) { + return false; + } + if (js_width == JSVAL_VOID || + js_height == JSVAL_VOID || + !js_data.isObject()) + { + return xpc_qsThrow(cx, NS_ERROR_FAILURE); + } + int32_t int_width, int_height; + JSObject *obj_data = JSVAL_TO_OBJECT(js_data); + if (!JS_ValueToECMAInt32(cx, js_width, &int_width) || + !JS_ValueToECMAInt32(cx, js_height, &int_height)) + { + return false; + } + if (!js_IsTypedArray(obj_data)) + { + return xpc_qsThrow(cx, NS_ERROR_FAILURE); + } + + nsresult rv = self.DoCallForImageData(int_width, int_height, obj_data); + return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv); +} + /* * TexImage2D takes: * TexImage2D(uint, int, uint, int, int, int, uint, uint, ArrayBufferView) @@ -412,65 +539,21 @@ nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, unsigned argc, jsval *vp) // arguments common to all cases GET_UINT32_ARG(argv0, 0); GET_INT32_ARG(argv1, 1); + GET_UINT32_ARG(argv2, 2); - if (argc > 5 && - !JSVAL_IS_PRIMITIVE(argv[5])) - { + if (argc > 5 && !JSVAL_IS_PRIMITIVE(argv[5])) { // implement the variants taking a DOMElement as argv[5] - GET_UINT32_ARG(argv2, 2); GET_UINT32_ARG(argv3, 3); GET_UINT32_ARG(argv4, 4); - nsIDOMElement *elt; - xpc_qsSelfRef eltRef; - rv = xpc_qsUnwrapArg(cx, argv[5], &elt, &eltRef.ptr, &argv[5]); - if (NS_FAILED(rv)) return JS_FALSE; - - rv = self->TexImage2D_dom(argv0, argv1, argv2, argv3, argv4, elt); - - // NS_ERROR_DOM_SECURITY_ERR indicates we tried to load a cross-domain element, so - // bail out immediately, don't try to interprete as ImageData - if (rv == NS_ERROR_DOM_SECURITY_ERR) { - xpc_qsThrowBadArg(cx, rv, vp, 5); - return JS_FALSE; + CallTexImage2D selfCaller(self, argv0, argv1, argv2, argv3, argv4); + if (!TexImage2DImageDataOrElement(cx, selfCaller, argv + 5)) { + return false; } - - if (NS_FAILED(rv)) { - // failed to interprete argv[5] as a DOMElement, now try to interprete it as ImageData - JSObject *argv5 = JSVAL_TO_OBJECT(argv[5]); - - jsval js_width, js_height, js_data; - JS_GetProperty(cx, argv5, "width", &js_width); - JS_GetProperty(cx, argv5, "height", &js_height); - JS_GetProperty(cx, argv5, "data", &js_data); - if (js_width == JSVAL_VOID || - js_height == JSVAL_VOID || - !js_data.isObject()) - { - xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 5); - return JS_FALSE; - } - int32_t int_width, int_height; - JSObject *obj_data = JSVAL_TO_OBJECT(js_data); - if (!JS_ValueToECMAInt32(cx, js_width, &int_width) || - !JS_ValueToECMAInt32(cx, js_height, &int_height)) - { - return JS_FALSE; - } - if (!js_IsTypedArray(obj_data)) - { - xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 5); - return JS_FALSE; - } - rv = self->TexImage2D_imageData(argv0, argv1, argv2, - int_width, int_height, 0, - argv3, argv4, js::TypedArray::getTypedArray(obj_data)); - } - } else if (argc > 8 && - JSVAL_IS_OBJECT(argv[8])) // here, we allow null ! - { + rv = NS_OK; + } else if (argc > 8 && JSVAL_IS_OBJECT(argv[8])) { + // here, we allow null ! // implement the variants taking a buffer/array as argv[8] - GET_UINT32_ARG(argv2, 2); GET_INT32_ARG(argv3, 3); GET_INT32_ARG(argv4, 4); GET_INT32_ARG(argv5, 5); @@ -536,61 +619,17 @@ nsIDOMWebGLRenderingContext_TexSubImage2D(JSContext *cx, unsigned argc, jsval *v GET_INT32_ARG(argv2, 2); GET_INT32_ARG(argv3, 3); - if (argc > 6 && - !JSVAL_IS_PRIMITIVE(argv[6])) - { - // implement the variants taking a DOMElement as argv[6] + if (argc > 6 && !JSVAL_IS_PRIMITIVE(argv[6])) { + // implement the variants taking a DOMElement or an ImageData as argv[6] GET_UINT32_ARG(argv4, 4); GET_UINT32_ARG(argv5, 5); - nsIDOMElement *elt; - xpc_qsSelfRef eltRef; - rv = xpc_qsUnwrapArg(cx, argv[6], &elt, &eltRef.ptr, &argv[6]); - if (NS_FAILED(rv)) return JS_FALSE; - - rv = self->TexSubImage2D_dom(argv0, argv1, argv2, argv3, argv4, argv5, elt); - - // NS_ERROR_DOM_SECURITY_ERR indicates we tried to load a cross-domain element, so - // bail out immediately, don't try to interprete as ImageData - if (rv == NS_ERROR_DOM_SECURITY_ERR) { - xpc_qsThrowBadArg(cx, rv, vp, 6); - return JS_FALSE; + CallTexSubImage2D selfCaller(self, argv0, argv1, argv2, argv3, argv4, argv5); + if (!TexImage2DImageDataOrElement(cx, selfCaller, argv + 6)) { + return false; } - - if (NS_FAILED(rv)) { - // failed to interprete argv[6] as a DOMElement, now try to interprete it as ImageData - JSObject *argv6 = JSVAL_TO_OBJECT(argv[6]); - jsval js_width, js_height, js_data; - JS_GetProperty(cx, argv6, "width", &js_width); - JS_GetProperty(cx, argv6, "height", &js_height); - JS_GetProperty(cx, argv6, "data", &js_data); - if (js_width == JSVAL_VOID || - js_height == JSVAL_VOID || - !js_data.isObject()) - { - xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 6); - return JS_FALSE; - } - int32_t int_width, int_height; - JSObject *obj_data = JSVAL_TO_OBJECT(js_data); - if (!JS_ValueToECMAInt32(cx, js_width, &int_width) || - !JS_ValueToECMAInt32(cx, js_height, &int_height)) - { - return JS_FALSE; - } - if (!js_IsTypedArray(obj_data)) - { - xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 6); - return JS_FALSE; - } - rv = self->TexSubImage2D_imageData(argv0, argv1, argv2, argv3, - int_width, int_height, - argv4, argv5, - js::TypedArray::getTypedArray(obj_data)); - } - } else if (argc > 8 && - !JSVAL_IS_PRIMITIVE(argv[8])) - { + rv = NS_OK; + } else if (argc > 8 && !JSVAL_IS_PRIMITIVE(argv[8])) { // implement the variants taking a buffer/array as argv[8] GET_INT32_ARG(argv4, 4); GET_INT32_ARG(argv5, 5); diff --git a/content/canvas/src/WebGLContext.h b/content/canvas/src/WebGLContext.h index ffc1154f159d..208a634711e3 100644 --- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -815,7 +815,7 @@ protected: int dstFormat, bool dstPremultiplied, size_t dstTexelSize); - nsresult DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, + nsresult DOMElementToImageSurface(dom::Element* imageOrCanvas, gfxImageSurface **imageOut, int *format); diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index d76744a99d6c..d446ef5ba1e5 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -70,6 +70,7 @@ #endif using namespace mozilla; +using namespace mozilla::dom; static bool BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *unitSize); static WebGLenum InternalFormatForFormatAndType(WebGLenum format, WebGLenum type, bool isGLES2); @@ -3966,11 +3967,10 @@ WebGLContext::ConvertImage(size_t width, size_t height, size_t srcStride, size_t } nsresult -WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, +WebGLContext::DOMElementToImageSurface(Element* imageOrCanvas, gfxImageSurface **imageOut, int *format) { - nsCOMPtr content = do_QueryInterface(imageOrCanvas); - if (!content) { + if (!imageOrCanvas) { return NS_ERROR_FAILURE; } @@ -3984,7 +3984,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, flags |= nsLayoutUtils::SFE_NO_PREMULTIPLY_ALPHA; nsLayoutUtils::SurfaceFromElementResult res = - nsLayoutUtils::SurfaceFromElement(content->AsElement(), flags); + nsLayoutUtils::SurfaceFromElement(imageOrCanvas, flags); if (!res.mSurface) return NS_ERROR_FAILURE; if (res.mSurface->GetType() != gfxASurface::SurfaceTypeImage) { @@ -4016,7 +4016,7 @@ WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, // part 2: if the DOM element is a canvas, check that it's not write-only. // That would indicate a tainted canvas, i.e. a canvas that could contain // cross-domain image data. - if (nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(content)) { + if (nsHTMLCanvasElement* canvas = nsHTMLCanvasElement::FromContent(imageOrCanvas)) { if (canvas->IsWriteOnly()) { LogMessageIfVerbose("The canvas used as source for texImage2D here is tainted (write-only). It is forbidden " "to load a WebGL texture from a tainted canvas. A Canvas becomes tainted for example " @@ -5082,7 +5082,7 @@ WebGLContext::TexImage2D_imageData(WebGLenum target, WebGLint level, WebGLenum i NS_IMETHODIMP WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum internalformat, - WebGLenum format, GLenum type, nsIDOMElement *elt) + WebGLenum format, GLenum type, Element* elt) { if (!IsContextStable()) return NS_OK; @@ -5272,7 +5272,7 @@ NS_IMETHODIMP WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level, WebGLint xoffset, WebGLint yoffset, WebGLenum format, WebGLenum type, - nsIDOMElement *elt) + Element *elt) { if (!IsContextStable()) return NS_OK; diff --git a/content/canvas/test/test_canvas.html b/content/canvas/test/test_canvas.html index e0c78ee46987..6df50da8110e 100644 --- a/content/canvas/test/test_canvas.html +++ b/content/canvas/test/test_canvas.html @@ -7591,7 +7591,7 @@ ok(!_thrown_outer, ctx.canvas.id + ' should not throw exception');

Canvas test: 2d.imageData.create.type - bug 433004

- +

FAIL (fallback content)

diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h index eb38af5b7445..c8a050f51878 100644 --- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -50,6 +50,7 @@ #include "nsIObserver.h" #include "nsAudioStream.h" #include "VideoFrameContainer.h" +#include "mozilla/CORSMode.h" // Define to output information on decoding and painting framerate /* #define DEBUG_FRAME_RATE 1 */ @@ -71,7 +72,7 @@ public: CANPLAY_YES }; - CORSMode GetCORSMode() { + mozilla::CORSMode GetCORSMode() { return mCORSMode; } @@ -781,7 +782,7 @@ protected: bool mMediaSecurityVerified; // The CORS mode when loading the media element - CORSMode mCORSMode; + mozilla::CORSMode mCORSMode; }; #endif diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 6fc86ebd7b74..842b1788db61 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -2488,24 +2488,25 @@ nsGenericHTMLElement::GetContentEditable(nsAString& aContentEditable) nsresult nsGenericHTMLElement::SetContentEditable(const nsAString& aContentEditable) { - nsString contentEditable; - ToLowerCase(aContentEditable, contentEditable); - - if (contentEditable.EqualsLiteral("inherit")) { + if (nsContentUtils::EqualsLiteralIgnoreASCIICase(aContentEditable, "inherit")) { UnsetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, true); return NS_OK; } - if (!contentEditable.EqualsLiteral("true") && - !contentEditable.EqualsLiteral("false")) { - return NS_ERROR_DOM_SYNTAX_ERR; + if (nsContentUtils::EqualsLiteralIgnoreASCIICase(aContentEditable, "true")) { + SetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, NS_LITERAL_STRING("true"), true); + + return NS_OK; + } + + if (nsContentUtils::EqualsLiteralIgnoreASCIICase(aContentEditable, "false")) { + SetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, NS_LITERAL_STRING("false"), true); + + return NS_OK; } - SetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, contentEditable, - true); - - return NS_OK; + return NS_ERROR_DOM_SYNTAX_ERR; } nsresult @@ -2886,14 +2887,6 @@ nsGenericHTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor) return nsGenericHTMLElement::PreHandleEvent(aVisitor); } -const nsAttrValue::EnumTable nsGenericHTMLElement::kCORSAttributeTable[] = { - // Order matters here - // See ParseAttribute in nsHTMLImageElement or nsHTMLMediaElement - { "anonymous", nsGenericHTMLElement::CORS_ANONYMOUS }, - { "use-credentials", nsGenericHTMLElement::CORS_USE_CREDENTIALS }, - { 0 } -}; - /* virtual */ bool nsGenericHTMLFormElement::IsDisabled() const diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 6c7bb6d26b1e..3dedd8c2165e 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -530,7 +530,7 @@ public: * Returns the current disabled state of the element. */ virtual bool IsDisabled() const { - return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled); + return false; } bool IsHidden() const @@ -538,32 +538,6 @@ public: return HasAttr(kNameSpaceID_None, nsGkAtoms::hidden); } - /** - * Shared cross-origin resource sharing attributes so they don't get - * duplicated on every CORS-enabled element - */ - - enum CORSMode { - /** - * The default of not using CORS to validate cross-origin loads. - */ - CORS_NONE, - - /** - * Validate cross-site loads using CORS, but do not send any credentials - * (cookies, HTTP auth logins, etc) along with the request. - */ - CORS_ANONYMOUS, - - /** - * Validate cross-site loads using CORS, and send credentials such as cookies - * and HTTP auth logins along with the request. - */ - CORS_USE_CREDENTIALS - }; - - const static nsAttrValue::EnumTable kCORSAttributeTable[]; - protected: /** * Add/remove this element to the documents name cache diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp index 521c613b8379..50c7edca8906 100644 --- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -363,10 +363,8 @@ nsHTMLImageElement::ParseAttribute(PRInt32 aNamespaceID, return ParseAlignValue(aValue, aResult); } if (aAttribute == nsGkAtoms::crossorigin) { - return aResult.ParseEnumValue(aValue, nsGenericHTMLElement::kCORSAttributeTable, false, - // default value is anonymous if aValue is - // not a value we understand - &nsGenericHTMLElement::kCORSAttributeTable[0]); + ParseCORSValue(aValue, aResult); + return true; } if (ParseImageAttribute(aAttribute, aValue, aResult)) { return true; @@ -662,17 +660,8 @@ nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const return nsGenericHTMLElement::CopyInnerTo(aDest); } -nsGenericHTMLElement::CORSMode +CORSMode nsHTMLImageElement::GetCORSMode() { - nsGenericHTMLElement::CORSMode ret = nsGenericHTMLElement::CORS_NONE; - - const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossorigin); - if (value) { - NS_ASSERTION(value->Type() == nsAttrValue::eEnum, - "Why is this not an enum value?"); - ret = nsGenericHTMLElement::CORSMode(value->GetEnumValue()); - } - - return ret; + return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); } diff --git a/content/html/content/src/nsHTMLLinkElement.cpp b/content/html/content/src/nsHTMLLinkElement.cpp index 693b47a879e7..099c78212ca8 100644 --- a/content/html/content/src/nsHTMLLinkElement.cpp +++ b/content/html/content/src/nsHTMLLinkElement.cpp @@ -436,7 +436,9 @@ nsHTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle, } GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia); - ToLowerCase(aMedia); // HTML4.0 spec is inconsistent, make it case INSENSITIVE + // The HTML5 spec is formulated in terms of the CSSOM spec, which specifies + // that media queries should be ASCII lowercased during serialization. + nsContentUtils::ASCIIToLower(aMedia); nsAutoString mimeType; nsAutoString notUsed; diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 87ad45b768ba..ad8978c99234 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -951,14 +951,7 @@ nsresult nsHTMLMediaElement::LoadResource() } // Set the media element's CORS mode only when loading a resource - // By default, it's CORS_NONE - mCORSMode = CORS_NONE; - const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossorigin); - if (value) { - NS_ASSERTION(value->Type() == nsAttrValue::eEnum, - "Why is this not an enum value?"); - mCORSMode = CORSMode(value->GetEnumValue()); - } + mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); nsHTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc); if (other) { @@ -1604,10 +1597,8 @@ bool nsHTMLMediaElement::ParseAttribute(PRInt32 aNamespaceID, return true; } if (aAttribute == nsGkAtoms::crossorigin) { - return aResult.ParseEnumValue(aValue, kCORSAttributeTable, false, - // default value is anonymous if aValue is - // not a value we understand - &kCORSAttributeTable[0]); + ParseCORSValue(aValue, aResult); + return true; } if (aAttribute == nsGkAtoms::preload) { return aResult.ParseEnumValue(aValue, kPreloadTable, false); diff --git a/content/html/content/src/nsHTMLOptGroupElement.cpp b/content/html/content/src/nsHTMLOptGroupElement.cpp index 49507f473806..a97680dec5be 100644 --- a/content/html/content/src/nsHTMLOptGroupElement.cpp +++ b/content/html/content/src/nsHTMLOptGroupElement.cpp @@ -85,6 +85,10 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; virtual nsXPCClassInfo* GetClassInfo(); + + virtual bool IsDisabled() const { + return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled); + } protected: /** diff --git a/content/html/content/src/nsHTMLOptionElement.h b/content/html/content/src/nsHTMLOptionElement.h index 67856a5a3a44..49021e08d9d4 100644 --- a/content/html/content/src/nsHTMLOptionElement.h +++ b/content/html/content/src/nsHTMLOptionElement.h @@ -104,6 +104,10 @@ public: nsresult CopyInnerTo(nsGenericElement* aDest) const; virtual nsXPCClassInfo* GetClassInfo(); + + virtual bool IsDisabled() const { + return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled); + } protected: /** * Get the select content element that contains this option, this diff --git a/content/html/content/src/nsHTMLScriptElement.cpp b/content/html/content/src/nsHTMLScriptElement.cpp index ec626bee430d..88a25dffaf5d 100644 --- a/content/html/content/src/nsHTMLScriptElement.cpp +++ b/content/html/content/src/nsHTMLScriptElement.cpp @@ -57,6 +57,7 @@ #include "nsTArray.h" #include "nsDOMJSUtils.h" +using namespace mozilla; using namespace mozilla::dom; class nsHTMLScriptElement : public nsGenericHTMLElement, @@ -108,11 +109,16 @@ public: virtual void GetScriptText(nsAString& text); virtual void GetScriptCharset(nsAString& charset); virtual void FreezeUriAsyncDefer(); + virtual CORSMode GetCORSMode() const; // nsIContent virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, bool aCompileEventHandlers); + virtual bool ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult); virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; @@ -178,6 +184,22 @@ nsHTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, return NS_OK; } +bool +nsHTMLScriptElement::ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + if (aNamespaceID == kNameSpaceID_None && + aAttribute == nsGkAtoms::crossorigin) { + ParseCORSValue(aValue, aResult); + return true; + } + + return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, + aResult); +} + nsresult nsHTMLScriptElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const { @@ -311,6 +333,12 @@ nsHTMLScriptElement::FreezeUriAsyncDefer() mFrozen = true; } +CORSMode +nsHTMLScriptElement::GetCORSMode() const +{ + return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); +} + bool nsHTMLScriptElement::HasScriptContent() { diff --git a/content/html/content/src/nsHTMLStyleElement.cpp b/content/html/content/src/nsHTMLStyleElement.cpp index 935af2a8e601..8d87a269e56e 100644 --- a/content/html/content/src/nsHTMLStyleElement.cpp +++ b/content/html/content/src/nsHTMLStyleElement.cpp @@ -340,7 +340,9 @@ nsHTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle, aTitle.Assign(title); GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia); - ToLowerCase(aMedia); // HTML4.0 spec is inconsistent, make it case INSENSITIVE + // The HTML5 spec is formulated in terms of the CSSOM spec, which specifies + // that media queries should be ASCII lowercased during serialization. + nsContentUtils::ASCIIToLower(aMedia); GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType); diff --git a/content/html/content/test/test_bug430351.html b/content/html/content/test/test_bug430351.html index d1e7caff6738..04587c9710c0 100644 --- a/content/html/content/test/test_bug430351.html +++ b/content/html/content/test/test_bug430351.html @@ -61,6 +61,7 @@ var focusableElements = [ "
", "
", "
", + "
", "", "", @@ -165,7 +166,17 @@ var focusableElements = [ "", "", "", - "" + "", + + "", + "", + "", + "", + + "", + "", + "", + "" ]; var nonFocusableElements = [ @@ -182,7 +193,6 @@ var nonFocusableElements = [ "", "
", - "
", "
", "", @@ -243,7 +253,13 @@ var nonFocusableElements = [ "", "", - "" + "", + + "", + "", + + "", + "" ]; var focusableInContentEditable = [ @@ -268,6 +284,7 @@ var focusableInContentEditable = [ "
", "
", "
", + "
", "", "", @@ -365,7 +382,15 @@ var focusableInContentEditable = [ "", "", "", - "" + "", + + "", + "", + "", + + "", + "", + "" ]; var focusableInDesignMode = [ diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 3f94697e4878..bcf83fca84c1 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1358,7 +1358,7 @@ nsHTMLDocument::Open(const nsAString& aContentTypeOrUrl, contentType.AssignLiteral("text/html"); if (aOptionalArgCount > 0) { nsAutoString type; - ToLowerCase(aContentTypeOrUrl, type); + nsContentUtils::ASCIIToLower(aContentTypeOrUrl, type); nsCAutoString actualType, dummy; NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy); if (!actualType.EqualsLiteral("text/html") && diff --git a/content/svg/content/src/nsSVGScriptElement.cpp b/content/svg/content/src/nsSVGScriptElement.cpp index 932de2764831..1ec932912949 100644 --- a/content/svg/content/src/nsSVGScriptElement.cpp +++ b/content/svg/content/src/nsSVGScriptElement.cpp @@ -86,6 +86,7 @@ public: virtual void GetScriptText(nsAString& text); virtual void GetScriptCharset(nsAString& charset); virtual void FreezeUriAsyncDefer(); + virtual CORSMode GetCORSMode() const; // nsScriptElement virtual bool HasScriptContent(); @@ -96,6 +97,10 @@ public: bool aCompileEventHandlers); virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify); + virtual bool ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult); virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; @@ -288,3 +293,26 @@ nsSVGScriptElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, return nsSVGScriptElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aNotify); } + +bool +nsSVGScriptElement::ParseAttribute(PRInt32 aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + if (aNamespaceID == kNameSpaceID_None && + aAttribute == nsGkAtoms::crossorigin) { + ParseCORSValue(aValue, aResult); + return true; + } + + return nsSVGScriptElementBase::ParseAttribute(aNamespaceID, aAttribute, + aValue, aResult); +} + +CORSMode +nsSVGScriptElement::GetCORSMode() const +{ + return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); +} + diff --git a/content/svg/content/src/nsSVGStyleElement.cpp b/content/svg/content/src/nsSVGStyleElement.cpp index 181ef23b450e..14204e643cc9 100644 --- a/content/svg/content/src/nsSVGStyleElement.cpp +++ b/content/svg/content/src/nsSVGStyleElement.cpp @@ -337,9 +337,9 @@ nsSVGStyleElement::GetStyleSheetInfo(nsAString& aTitle, aTitle.Assign(title); GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia); - // SVG spec refers to the HTML4.0 spec which is inconsistent, make it - // case INSENSITIVE - ToLowerCase(aMedia); + // The SVG spec is formulated in terms of the CSS2 spec, + // which specifies that media queries are case insensitive. + nsContentUtils::ASCIIToLower(aMedia); GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType); if (aType.IsEmpty()) { diff --git a/content/xbl/src/nsXBLPrototypeHandler.cpp b/content/xbl/src/nsXBLPrototypeHandler.cpp index 017e762d0206..0b2a36ad9f2c 100644 --- a/content/xbl/src/nsXBLPrototypeHandler.cpp +++ b/content/xbl/src/nsXBLPrototypeHandler.cpp @@ -932,21 +932,18 @@ nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement, if (!key.IsEmpty()) { if (mKeyMask == 0) mKeyMask = cAllModifiers; - ToLowerCase(key); + nsContentUtils::ASCIIToLower(key); // We have a charcode. mMisc = 1; mDetail = key[0]; const PRUint8 GTK2Modifiers = cShift | cControl | cShiftMask | cControlMask; if ((mKeyMask & GTK2Modifiers) == GTK2Modifiers && - modifiers.First() != PRUnichar(',') && - (mDetail == 'u' || mDetail == 'U')) + modifiers.First() != PRUnichar(',') && mDetail == 'u') ReportKeyConflict(key.get(), modifiers.get(), aKeyElement, "GTK2Conflict"); const PRUint8 WinModifiers = cControl | cAlt | cControlMask | cAltMask; if ((mKeyMask & WinModifiers) == WinModifiers && - modifiers.First() != PRUnichar(',') && - (('A' <= mDetail && mDetail <= 'Z') || - ('a' <= mDetail && mDetail <= 'z'))) + modifiers.First() != PRUnichar(',') && ('a' <= mDetail && mDetail <= 'z')) ReportKeyConflict(key.get(), modifiers.get(), aKeyElement, "WinConflict"); } else { diff --git a/content/xslt/src/base/txStringUtils.h b/content/xslt/src/base/txStringUtils.h index fe0b0e9c5c9f..262396d91724 100644 --- a/content/xslt/src/base/txStringUtils.h +++ b/content/xslt/src/base/txStringUtils.h @@ -44,8 +44,6 @@ #include "nsIAtom.h" #include "nsUnicharUtils.h" -#define TX_ToLowerCase ToLowerCase - typedef nsCaseInsensitiveStringComparator txCaseInsensitiveStringComparator; /** @@ -62,7 +60,7 @@ TX_ToLowerCaseAtom(nsIAtom* aAtom) { nsAutoString str; aAtom->ToString(str); - TX_ToLowerCase(str); + nsContentUtils::ASCIIToLower(str); return do_GetAtom(str); } diff --git a/content/xslt/src/xpath/txExprParser.cpp b/content/xslt/src/xpath/txExprParser.cpp index d9c970b6db45..7f901b1869ec 100644 --- a/content/xslt/src/xpath/txExprParser.cpp +++ b/content/xslt/src/xpath/txExprParser.cpp @@ -938,7 +938,7 @@ txExprParser::resolveQName(const nsAString& aQName, *aPrefix = 0; if (aIsNameTest && aContext->caseInsensitiveNameTests()) { nsAutoString lcname; - TX_ToLowerCase(aQName, lcname); + nsContentUtils::ASCIIToLower(aQName, lcname); *aLocalName = NS_NewAtom(lcname); } else { diff --git a/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp b/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp index 91331748bca0..143533523355 100644 --- a/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp +++ b/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp @@ -453,7 +453,7 @@ txXPathNodeUtils::getLocalName(const txXPathNode& aNode, nsAString& aLocalName) // Check for html if (aNode.Content()->NodeInfo()->NamespaceEquals(kNameSpaceID_None) && aNode.Content()->IsHTML()) { - ToUpperCase(aLocalName); + nsContentUtils::ASCIIToUpper(aLocalName); } } diff --git a/content/xslt/src/xpath/txResultRecycler.cpp b/content/xslt/src/xpath/txResultRecycler.cpp index 611f7a0162c1..2bd3e6b1d4cf 100644 --- a/content/xslt/src/xpath/txResultRecycler.cpp +++ b/content/xslt/src/xpath/txResultRecycler.cpp @@ -228,23 +228,6 @@ txResultRecycler::getNodeSet(const txXPathNode& aNode, txAExprResult** aResult) return NS_OK; } -nsresult -txResultRecycler::getNodeSet(const txXPathNode& aNode, txNodeSet** aResult) -{ - if (mNodeSetResults.isEmpty()) { - *aResult = new txNodeSet(aNode, this); - NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); - } - else { - *aResult = static_cast(mNodeSetResults.pop()); - (*aResult)->append(aNode); - (*aResult)->mRecycler = this; - } - NS_ADDREF(*aResult); - - return NS_OK; -} - nsresult txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult) { diff --git a/content/xslt/src/xpath/txResultRecycler.h b/content/xslt/src/xpath/txResultRecycler.h index b087abff425f..93da7a29c6ff 100644 --- a/content/xslt/src/xpath/txResultRecycler.h +++ b/content/xslt/src/xpath/txResultRecycler.h @@ -86,7 +86,6 @@ public: nsresult getNodeSet(txNodeSet** aResult); nsresult getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult); nsresult getNodeSet(const txXPathNode& aNode, txAExprResult** aResult); - nsresult getNodeSet(const txXPathNode& aNode, txNodeSet** aResult); nsresult getNumberResult(double aValue, txAExprResult** aResult); /** diff --git a/content/xslt/src/xslt/txMozillaXMLOutput.cpp b/content/xslt/src/xslt/txMozillaXMLOutput.cpp index 3af32c19f390..51fd9b26b0bf 100644 --- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp +++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp @@ -160,7 +160,7 @@ txMozillaXMLOutput::attribute(nsIAtom* aPrefix, if (mOpenedElementIsHTML && aNsID == kNameSpaceID_None) { nsAutoString lnameStr; - ToLowerCase(aLocalName, lnameStr); + nsContentUtils::ASCIIToLower(aLocalName, lnameStr); lname = do_GetAtom(lnameStr); } else { @@ -499,7 +499,7 @@ txMozillaXMLOutput::startElement(nsIAtom* aPrefix, nsId = kNameSpaceID_XHTML; nsAutoString lnameStr; - ToLowerCase(aLocalName, lnameStr); + nsContentUtils::ASCIIToLower(aLocalName, lnameStr); lname = do_GetAtom(lnameStr); } else { @@ -802,7 +802,7 @@ txMozillaXMLOutput::endHTMLElement(nsIContent* aElement) nsAutoString value; aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::content, value); if (!value.IsEmpty()) { - ToLowerCase(httpEquiv); + nsContentUtils::ASCIIToLower(httpEquiv); nsCOMPtr header = do_GetAtom(httpEquiv); processHTTPEquiv(header, value); } diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index a2e221c60d0a..040491b9ed7b 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -788,11 +788,7 @@ nsXULPDGlobalObject::ClearGlobalObjectOwner() if (this != nsXULPrototypeDocument::gSystemGlobal) mCachedPrincipal = mGlobalObjectOwner->DocumentPrincipal(); - if (mContext) { - mContext->FinalizeContext(); - mContext = NULL; - } - + mContext = NULL; mGlobalObjectOwner = NULL; } diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 115d59ab4bd1..a490bcc61fa9 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -452,7 +452,6 @@ #include "nsDOMFile.h" #include "nsDOMFileReader.h" #include "nsIDOMFileException.h" -#include "nsIDOMFileError.h" #include "nsIDOMFormData.h" #include "nsIDOMDOMStringMap.h" @@ -1394,8 +1393,6 @@ static nsDOMClassInfoData sClassInfoData[] = { DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(FileException, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) - NS_DEFINE_CLASSINFO_DATA(FileError, nsDOMGenericSH, - DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(FileReader, nsEventTargetSH, EVENTTARGET_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(MozURLProperty, nsDOMGenericSH, @@ -3964,10 +3961,6 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileList) DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(FileError, nsIDOMFileError) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileError) - DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob) DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob) DOM_CLASSINFO_MAP_END diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h index 14c7e78114ac..5885454b460b 100644 --- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -402,7 +402,6 @@ DOMCI_CLASS(FileList) DOMCI_CLASS(Blob) DOMCI_CLASS(File) DOMCI_CLASS(FileException) -DOMCI_CLASS(FileError) DOMCI_CLASS(FileReader) DOMCI_CLASS(MozURLProperty) DOMCI_CLASS(MozBlobBuilder) diff --git a/dom/base/nsDOMJSUtils.h b/dom/base/nsDOMJSUtils.h index 9fb31cc2a9dc..ec0defc48fc6 100644 --- a/dom/base/nsDOMJSUtils.h +++ b/dom/base/nsDOMJSUtils.h @@ -5,6 +5,8 @@ #include "jsapi.h" #include "nsIScriptContext.h" +class nsIJSArgArray; + // seems like overkill for just this 1 function - but let's see what else // falls out first. inline nsIScriptContext * @@ -50,6 +52,6 @@ GetScriptContextPrincipalFromJSContext(JSContext *cx) // rooted, but all items remain NULL. This presumably means the caller will // then QI us for nsIJSArgArray, and set our array elements. nsresult NS_CreateJSArgv(JSContext *aContext, PRUint32 aArgc, void *aArgv, - nsIArray **aArray); + nsIJSArgArray **aArray); #endif // nsDOMJSUtils_h__ diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 5a6c2c24db3c..6ccba831e0f6 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2402,7 +2402,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) if (mContext) { mContext->GC(js::gcreason::SET_DOC_SHELL); - mContext->FinalizeContext(); mContext = nsnull; } @@ -5932,7 +5931,7 @@ nsGlobalWindow::OpenDialog(const nsAString& aUrl, const nsAString& aName, // Strip the url, name and options from the args seen by scripts. PRUint32 argOffset = argc < 3 ? argc : 3; - nsCOMPtr argvArray; + nsCOMPtr argvArray; rv = NS_CreateJSArgv(cx, argc - argOffset, argv + argOffset, getter_AddRefs(argvArray)); NS_ENSURE_SUCCESS(rv, rv); @@ -6532,7 +6531,6 @@ nsGlobalWindow::ForceClose() nsresult nsGlobalWindow::FinalClose() { - nsresult rv; // Flag that we were closed. mIsClosed = true; @@ -6549,38 +6547,24 @@ nsGlobalWindow::FinalClose() nsIScriptContext *currentCX = nsJSUtils::GetDynamicScriptContext(cx); if (currentCX && currentCX == GetContextInternal()) { - // We ignore the return value here. If setting the termination function - // fails, it's better to fail to close the window than it is to crash - // (which is what would tend to happen if we did this synchronously - // here). - rv = currentCX->SetTerminationFunction(CloseWindow, - static_cast - (this)); - if (NS_SUCCEEDED(rv)) { - mHavePendingClose = true; - } + currentCX->SetTerminationFunction(CloseWindow, this); + mHavePendingClose = true; return NS_OK; } } - // We may have plugins on the page that have issued this close from their // event loop and because we currently destroy the plugin window with // frames, we crash. So, if we are called from Javascript, post an event // to really close the window. - rv = NS_ERROR_FAILURE; - if (!nsContentUtils::IsCallerChrome()) { - rv = nsCloseEvent::PostCloseEvent(this); - } - - if (NS_FAILED(rv)) { + if (nsContentUtils::IsCallerChrome() || + NS_FAILED(nsCloseEvent::PostCloseEvent(this))) { ReallyCloseWindow(); - rv = NS_OK; } else { mHavePendingClose = true; } - - return rv; + + return NS_OK; } @@ -8867,8 +8851,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName, if (mContext == GetScriptContextFromJSContext(aJSCallerContext)) { mBlockScriptedClosingFlag = true; mContext->SetTerminationFunction(CloseBlockScriptTerminationFunc, - static_cast - (this)); + this); } } diff --git a/dom/base/nsIScriptContext.h b/dom/base/nsIScriptContext.h index 6be0faf4198f..ac8683b02ab8 100644 --- a/dom/base/nsIScriptContext.h +++ b/dom/base/nsIScriptContext.h @@ -56,6 +56,7 @@ class nsIObjectInputStream; class nsIObjectOutputStream; template class nsScriptObjectHolder; class nsIScriptObjectPrincipal; +class nsIDOMWindow; typedef void (*nsScriptTerminationFunc)(nsISupports* aRef); @@ -75,8 +76,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal, NS_ISCRIPTCONTEXTPRINCIPAL_IID) #define NS_ISCRIPTCONTEXT_IID \ -{ 0x6d69fbee, 0x0723, 0x48f5, \ - { 0x82, 0x48, 0xcd, 0xcf, 0x88, 0xac, 0x25, 0x74 } } +{ 0xdfaea249, 0xaaad, 0x48bd, \ + { 0xb8, 0x04, 0x92, 0xad, 0x30, 0x88, 0xd0, 0xc6 } } /* This MUST match JSVERSION_DEFAULT. This version stuff if we don't know what language we have is a little silly... */ @@ -344,11 +345,6 @@ public: */ virtual bool IsContextInitialized() = 0; - /** - * Called as the global object discards its reference to the context. - */ - virtual void FinalizeContext() = 0; - /** * For garbage collected systems, do a synchronous collection pass. * May be a no-op on other systems @@ -389,8 +385,8 @@ public: * * @throws NS_ERROR_OUT_OF_MEMORY if that happens */ - virtual nsresult SetTerminationFunction(nsScriptTerminationFunc aFunc, - nsISupports* aRef) = 0; + virtual void SetTerminationFunction(nsScriptTerminationFunc aFunc, + nsIDOMWindow* aRef) = 0; /** * Called to disable/enable script execution in this context. @@ -400,7 +396,7 @@ public: // SetProperty is suspect and jst believes should not be needed. Currenly // used only for "arguments". - virtual nsresult SetProperty(void *aTarget, const char *aPropName, nsISupports *aVal) = 0; + virtual nsresult SetProperty(JSObject* aTarget, const char* aPropName, nsISupports* aVal) = 0; /** * Called to set/get information if the script context is * currently processing a script tag diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 94b8f64bf738..71768d0de64a 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2293,7 +2293,7 @@ nsJSContext::InitializeExternalClasses() } nsresult -nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArgs) +nsJSContext::SetProperty(JSObject* aTarget, const char* aPropName, nsISupports* aArgs) { PRUint32 argc; jsval *argv = nsnull; @@ -2302,8 +2302,8 @@ nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArg Maybe tempStorage; - nsresult rv; - rv = ConvertSupportsTojsvals(aArgs, GetNativeGlobal(), &argc, &argv, tempStorage); + nsresult rv = + ConvertSupportsTojsvals(aArgs, GetNativeGlobal(), &argc, &argv, tempStorage); NS_ENSURE_SUCCESS(rv, rv); jsval vargs; @@ -2327,11 +2327,9 @@ nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArg // Make sure to use JS_DefineProperty here so that we can override // readonly XPConnect properties here as well (read dialogArguments). - rv = ::JS_DefineProperty(mContext, reinterpret_cast(aTarget), - aPropName, vargs, nsnull, nsnull, 0) ? - NS_OK : NS_ERROR_FAILURE; - - return rv; + return JS_DefineProperty(mContext, aTarget, aPropName, vargs, NULL, NULL, 0) + ? NS_OK + : NS_ERROR_FAILURE; } nsresult @@ -2360,7 +2358,7 @@ nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs, if (!aArgs) return NS_OK; - PRUint32 argCtr, argCount; + PRUint32 argCount; // This general purpose function may need to convert an arg array // (window.arguments, event-handler args) and a generic property. nsCOMPtr argsArray(do_QueryInterface(aArgs)); @@ -2381,7 +2379,7 @@ nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs, jsval *argv = aTempStorage.ref().Elements(); if (argsArray) { - for (argCtr = 0; argCtr < argCount && NS_SUCCEEDED(rv); argCtr++) { + for (PRUint32 argCtr = 0; argCtr < argCount && NS_SUCCEEDED(rv); argCtr++) { nsCOMPtr arg; jsval *thisval = argv + argCtr; argsArray->QueryElementAt(argCtr, NS_GET_IID(nsISupports), @@ -2975,12 +2973,6 @@ nsJSContext::IsContextInitialized() return mIsInitialized; } -void -nsJSContext::FinalizeContext() -{ - ; -} - void nsJSContext::ScriptEvaluated(bool aTerminated) { @@ -3006,20 +2998,15 @@ nsJSContext::ScriptEvaluated(bool aTerminated) } } -nsresult +void nsJSContext::SetTerminationFunction(nsScriptTerminationFunc aFunc, - nsISupports* aRef) + nsIDOMWindow* aRef) { NS_PRECONDITION(GetExecutingScript(), "should be executing script"); nsJSContext::TerminationFuncClosure* newClosure = new nsJSContext::TerminationFuncClosure(aFunc, aRef, mTerminations); - if (!newClosure) { - return NS_ERROR_OUT_OF_MEMORY; - } - mTerminations = newClosure; - return NS_OK; } bool @@ -3922,7 +3909,7 @@ nsresult NS_CreateJSRuntime(nsIScriptRuntime **aRuntime) // to/from nsISupports. // When consumed by non-JS (eg, another script language), conversion is done // on-the-fly. -class nsJSArgArray : public nsIJSArgArray, public nsIArray { +class nsJSArgArray : public nsIJSArgArray { public: nsJSArgArray(JSContext *aContext, PRUint32 argc, jsval *argv, nsresult *prv); ~nsJSArgArray(); @@ -4062,7 +4049,7 @@ NS_IMETHODIMP nsJSArgArray::Enumerate(nsISimpleEnumerator **_retval) // The factory function nsresult NS_CreateJSArgv(JSContext *aContext, PRUint32 argc, void *argv, - nsIArray **aArray) + nsIJSArgArray **aArray) { nsresult rv; nsJSArgArray *ret = new nsJSArgArray(aContext, argc, diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index 1ff03dab63b5..22d202a48781 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -47,6 +47,7 @@ #include "prtime.h" #include "nsCycleCollectionParticipant.h" #include "nsIXPConnect.h" +#include "nsIArray.h" class nsIXPConnectJSObjectHolder; class nsRootedJSValueArray; @@ -143,15 +144,14 @@ public: virtual nsresult SetOuterObject(JSObject* aOuterObject); virtual nsresult InitOuterWindow(); virtual bool IsContextInitialized(); - virtual void FinalizeContext(); virtual void ScriptEvaluated(bool aTerminated); - virtual nsresult SetTerminationFunction(nsScriptTerminationFunc aFunc, - nsISupports* aRef); + virtual void SetTerminationFunction(nsScriptTerminationFunc aFunc, + nsIDOMWindow* aRef); virtual bool GetScriptsEnabled(); virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts); - virtual nsresult SetProperty(void *aTarget, const char *aPropName, nsISupports *aVal); + virtual nsresult SetProperty(JSObject* aTarget, const char* aPropName, nsISupports* aVal); virtual bool GetProcessingScriptTag(); virtual void SetProcessingScriptTag(bool aResult); @@ -348,11 +348,10 @@ public: // nsISupports conversion. If this interface is not supported, the object will // be queried for nsIArray, and everything converted via xpcom objects. #define NS_IJSARGARRAY_IID \ - { /*{E96FB2AE-CB4F-44a0-81F8-D91C80AFE9A3} */ \ - 0xe96fb2ae, 0xcb4f, 0x44a0, \ - { 0x81, 0xf8, 0xd9, 0x1c, 0x80, 0xaf, 0xe9, 0xa3 } } +{ 0xb6acdac8, 0xf5c6, 0x432c, \ + { 0xa8, 0x6e, 0x33, 0xee, 0xb1, 0xb0, 0xcd, 0xdc } } -class nsIJSArgArray: public nsISupports +class nsIJSArgArray : public nsIArray { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSARGARRAY_IID) diff --git a/dom/base/nsJSTimeoutHandler.cpp b/dom/base/nsJSTimeoutHandler.cpp index 97e4e32f3b3e..f4fe1f283f85 100644 --- a/dom/base/nsJSTimeoutHandler.cpp +++ b/dom/base/nsJSTimeoutHandler.cpp @@ -101,7 +101,7 @@ private: nsCString mFileName; PRUint32 mLineNo; PRUint32 mVersion; - nsCOMPtr mArgv; + nsCOMPtr mArgv; // The JS expression to evaluate or function to call, if !mExpr JSFlatString *mExpr; @@ -326,7 +326,7 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval, // to setTimeout or setInterval; the first two are our callback // and the delay, so only arguments after that need to go in our // array. - nsCOMPtr array; + nsCOMPtr array; // NS_MAX(argc - 2, 0) wouldn't work right because argc is unsigned. rv = NS_CreateJSArgv(cx, NS_MAX(argc, 2u) - 2, nsnull, getter_AddRefs(array)); @@ -336,8 +336,7 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval, PRUint32 dummy; jsval *jsargv = nsnull; - nsCOMPtr jsarray(do_QueryInterface(array)); - jsarray->GetArgs(&dummy, reinterpret_cast(&jsargv)); + array->GetArgs(&dummy, reinterpret_cast(&jsargv)); // jsargv might be null if we have argc <= 2 if (jsargv) { diff --git a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl index 81ecd91d011c..735f2afbd8e7 100644 --- a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl +++ b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl @@ -59,16 +59,18 @@ typedef float WebGLclampf; // for jsval #include "jsapi.h" -namespace js { -struct ArrayBuffer; -struct TypedArray; -} +namespace mozilla { +namespace dom { +class Element; +} // namespace dom +} // namespace mozilla /* Avoid conflict with WinAPI */ #undef NO_ERROR %} [ptr] native WebGLJSObjectPtr (JSObject); +[ptr] native Element (mozilla::dom::Element); // // OpenGL object wrappers @@ -175,7 +177,7 @@ interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension const WebGLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF; }; -[scriptable, builtinclass, uuid(f000afac-11b3-4c06-a35f-8db411f1cf54)] +[scriptable, builtinclass, uuid(020474b1-2d3f-403b-b85d-11d9082ccd92)] interface nsIDOMWebGLRenderingContext : nsISupports { // @@ -786,7 +788,7 @@ interface nsIDOMWebGLRenderingContext : nsISupports // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement [noscript] void texImage2D_dom(in WebGLenum target, in WebGLint level, in WebGLenum internalformat, - in WebGLenum format, in WebGLenum type, in nsIDOMElement element); + in WebGLenum format, in WebGLenum type, in Element element); void texSubImage2D([optional] in long dummy); [noscript] void texSubImage2D_array(in WebGLenum target, in WebGLint level, @@ -798,7 +800,7 @@ interface nsIDOMWebGLRenderingContext : nsISupports // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement [noscript] void texSubImage2D_dom(in WebGLenum target, in WebGLint level, in WebGLint xoffset, in WebGLint yoffset, in WebGLenum format, in WebGLenum type, - in nsIDOMElement element); + in Element element); // Modified: This replaces glTexParameterf, glTexParameterfv, glTexParameteri and glTexParameteriv void texParameterf(in WebGLenum target, in WebGLenum pname, in WebGLfloat param); diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp index fdff85f66bb5..7610a0e1cc05 100644 --- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -2363,7 +2363,7 @@ NS_IMETHODIMP nsDOMStorageEvent::GetStorageArea(nsIDOMStorage * *aStorageArea) { NS_ENSURE_ARG_POINTER(aStorageArea); - NS_ADDREF(*aStorageArea = mStorageArea); + NS_IF_ADDREF(*aStorageArea = mStorageArea); return NS_OK; } diff --git a/dom/system/nsDeviceMotion.cpp b/dom/system/nsDeviceMotion.cpp index 639a588d0b73..9c2230c63893 100644 --- a/dom/system/nsDeviceMotion.cpp +++ b/dom/system/nsDeviceMotion.cpp @@ -199,12 +199,15 @@ NS_IMETHODIMP nsDeviceMotion::RemoveListener(nsIDeviceMotionListener *aListener) NS_IMETHODIMP nsDeviceMotion::AddWindowListener(nsIDOMWindow *aWindow) { + if (mWindowListeners.IndexOf(aWindow) != NoIndex) + return NS_OK; + if (mStarted == false) { mStarted = true; Startup(); } - if (mWindowListeners.IndexOf(aWindow) == NoIndex) - mWindowListeners.AppendElement(aWindow); + + mWindowListeners.AppendElement(aWindow); return NS_OK; } @@ -224,28 +227,34 @@ nsDeviceMotion::DeviceMotionChanged(PRUint32 type, double x, double y, double z) if (!mEnabled) return NS_ERROR_NOT_INITIALIZED; - for (PRUint32 i = mListeners.Count(); i > 0 ; ) { + nsCOMArray listeners = mListeners; + for (PRUint32 i = listeners.Count(); i > 0 ; ) { --i; nsRefPtr a = new nsDeviceMotionData(type, x, y, z); - mListeners[i]->OnMotionChange(a); + listeners[i]->OnMotionChange(a); } - for (PRUint32 i = mWindowListeners.Length(); i > 0 ; ) { + nsCOMArray windowListeners; + for (PRUint32 i = 0; i < mWindowListeners.Length(); i++) { + windowListeners.AppendObject(mWindowListeners[i]); + } + + for (PRUint32 i = windowListeners.Count(); i > 0 ; ) { --i; // check to see if this window is in the background. if // it is, don't send any device motion to it. - nsCOMPtr pwindow = do_QueryInterface(mWindowListeners[i]); + nsCOMPtr pwindow = do_QueryInterface(windowListeners[i]); if (!pwindow || !pwindow->GetOuterWindow() || pwindow->GetOuterWindow()->IsBackground()) continue; nsCOMPtr domdoc; - mWindowListeners[i]->GetDocument(getter_AddRefs(domdoc)); + windowListeners[i]->GetDocument(getter_AddRefs(domdoc)); if (domdoc) { - nsCOMPtr target = do_QueryInterface(mWindowListeners[i]); + nsCOMPtr target = do_QueryInterface(windowListeners[i]); if (type == nsIDeviceMotionData::TYPE_ACCELERATION) FireDOMMotionEvent(domdoc, target, x, y, z); else if (type == nsIDeviceMotionData::TYPE_ORIENTATION) diff --git a/dom/tests/mochitest/dom-level2-core/test_getAttributeNS03.html b/dom/tests/mochitest/dom-level2-core/test_getAttributeNS03.html index e9dfcb64e682..5a5a33594643 100644 --- a/dom/tests/mochitest/dom-level2-core/test_getAttributeNS03.html +++ b/dom/tests/mochitest/dom-level2-core/test_getAttributeNS03.html @@ -105,7 +105,7 @@ function getAttributeNS03() { assertNotNull("empAddrNotNull",testAddr); testAddr.removeAttributeNS(namespaceURI,localName); attrValue = testAddr.getAttributeNS(namespaceURI,localName); - assertEquals("throw_Equals","",attrValue); + assertEquals("throw_Equals",null,attrValue); } diff --git a/gfx/cairo/README b/gfx/cairo/README index 09d6a30821df..eb8428ea1270 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -10,10 +10,6 @@ VERSIONS: cairo (12d521df8acc483b2daa844d4f05dc2fe2765ba6) pixman (2f4f2fb4859931bf6dc5632d8c919e7296736427) -***** NOTE FOR VISUAL C++ 6.0 ***** - -VC6 is not supported. Please upgrade to VC8. - ==== Patches ==== Some specific things: diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp index 1873edba8e37..5994257b5238 100644 --- a/gfx/gl/GLContextProviderEGL.cpp +++ b/gfx/gl/GLContextProviderEGL.cpp @@ -2087,7 +2087,7 @@ GLContextEGL::CreateTextureImage(const nsIntSize& aSize, { nsRefPtr t = new gl::TiledTextureImage(this, aSize, aContentType, aUseNearestFilter); return t.forget(); -}; +} already_AddRefed GLContextEGL::TileGenFunc(const nsIntSize& aSize, diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index e8b04770d371..a7cca0aa019a 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -419,12 +419,7 @@ gfxWindowsPlatform::UpdateRenderMode() PRInt32 status; if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT2D, &status))) { if (status != nsIGfxInfo::FEATURE_NO_INFO) { - d2dDisabled = true; - if (status == nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION || - status == nsIGfxInfo::FEATURE_BLOCKED_DEVICE) - { - d2dBlocked = true; - } + d2dBlocked = true; } } } @@ -526,7 +521,6 @@ gfxWindowsPlatform::VerifyD2DDevice(bool aAttemptForce) return; } - nsRefPtr adapter1; hr = factory1->EnumAdapters1(0, getter_AddRefs(adapter1)); if (SUCCEEDED(hr) && adapter1) { diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl index 5a632215103f..14d22f2c554b 100644 --- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -93,7 +93,7 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter); * * Internally, imgIContainer also manages animation of images. */ -[scriptable, uuid(2506249c-e0a1-4d8f-846c-2d478247f8d8)] +[scriptable, uuid(8bf87433-be67-413b-9497-00071c5002bd)] interface imgIContainer : nsISupports { /** @@ -283,6 +283,12 @@ interface imgIContainer : nsISupports */ void unlockImage(); + /** + * If this image is unlocked, discard its decoded data. If the image is + * locked or has already been discarded, do nothing. + */ + void requestDiscard(); + /** * Indicates that this imgIContainer has been triggered to update * its internal animation state. Likely this should only be called diff --git a/image/public/imgIRequest.idl b/image/public/imgIRequest.idl index 9d3cfb75b925..080e2f9661ba 100644 --- a/image/public/imgIRequest.idl +++ b/image/public/imgIRequest.idl @@ -52,7 +52,7 @@ interface nsIPrincipal; * @version 0.1 * @see imagelib2 */ -[scriptable, uuid(c3bf4e2a-f64b-4ac1-a84e-18631b1802ab)] +[scriptable, uuid(d35a9adb-8328-4b64-b06f-72a165acd080)] interface imgIRequest : nsIRequest { /** @@ -194,6 +194,12 @@ interface imgIRequest : nsIRequest */ void unlockImage(); + /** + * If this image is unlocked, discard the image's decoded data. If the image + * is locked or is already discarded, do nothing. + */ + void requestDiscard(); + /** * If this request is for an animated image, the method creates a new * request which contains the current frame of the image. diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 6f7787455803..e3669f723336 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -2696,6 +2696,18 @@ RasterImage::UnlockImage() return NS_OK; } +//****************************************************************************** +/* void requestDiscard() */ +NS_IMETHODIMP +RasterImage::RequestDiscard() +{ + if (CanDiscard()) { + ForceDiscard(); + } + + return NS_OK; +} + // Flushes up to aMaxBytes to the decoder. nsresult RasterImage::DecodeSomeData(PRUint32 aMaxBytes) diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index 16d86344a0e6..8b61f170628a 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -198,6 +198,7 @@ public: NS_SCRIPTABLE NS_IMETHOD RequestDecode(void); NS_SCRIPTABLE NS_IMETHOD LockImage(void); NS_SCRIPTABLE NS_IMETHOD UnlockImage(void); + NS_SCRIPTABLE NS_IMETHOD RequestDiscard(void); NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void); NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime); // END NS_DECL_IMGICONTAINER diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index f263f29d5034..530602d1b085 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -626,6 +626,15 @@ VectorImage::UnlockImage() return NS_OK; } +//****************************************************************************** +/* void requestDiscard() */ +NS_IMETHODIMP +VectorImage::RequestDiscard() +{ + // This method is for image-discarding, which only applies to RasterImages. + return NS_OK; +} + //****************************************************************************** /* void resetAnimation (); */ NS_IMETHODIMP diff --git a/image/src/VectorImage.h b/image/src/VectorImage.h index bd1e9b4ad497..a10a347eacc7 100644 --- a/image/src/VectorImage.h +++ b/image/src/VectorImage.h @@ -81,6 +81,7 @@ public: NS_SCRIPTABLE NS_IMETHOD RequestDecode(void); NS_SCRIPTABLE NS_IMETHOD LockImage(void); NS_SCRIPTABLE NS_IMETHOD UnlockImage(void); + NS_SCRIPTABLE NS_IMETHOD RequestDiscard(void); NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void); NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime); // END NS_DECL_IMGICONTAINER diff --git a/image/src/imgRequestProxy.cpp b/image/src/imgRequestProxy.cpp index 477ee29343a6..32edcc9360a4 100644 --- a/image/src/imgRequestProxy.cpp +++ b/image/src/imgRequestProxy.cpp @@ -370,6 +370,16 @@ imgRequestProxy::UnlockImage() return NS_OK; } +/* void requestDiscard (); */ +NS_IMETHODIMP +imgRequestProxy::RequestDiscard() +{ + if (mImage) { + return mImage->RequestDiscard(); + } + return NS_OK; +} + NS_IMETHODIMP imgRequestProxy::IncrementAnimationConsumers() { diff --git a/image/test/mochitest/Makefile.in b/image/test/mochitest/Makefile.in index e673798cdff6..39548c1d5a6f 100644 --- a/image/test/mochitest/Makefile.in +++ b/image/test/mochitest/Makefile.in @@ -88,6 +88,7 @@ _TEST_FILES = imgutils.js \ test_bug671906.html \ test_error_events.html \ error-early.png \ + test_drawDiscardedImage.html \ $(NULL) # Tests disabled due to intermittent orange diff --git a/image/test/mochitest/test_drawDiscardedImage.html b/image/test/mochitest/test_drawDiscardedImage.html new file mode 100644 index 000000000000..7c99ba50461a --- /dev/null +++ b/image/test/mochitest/test_drawDiscardedImage.html @@ -0,0 +1,85 @@ + + + + + Test for Bug 731419 - Draw an ostensibly discarded image to a canvas + + + + + + + + + + + + + + + + + diff --git a/js/public/Utility.h b/js/public/Utility.h index c3027269b71f..f5294e369075 100644 --- a/js/public/Utility.h +++ b/js/public/Utility.h @@ -45,6 +45,11 @@ #include #include +#ifdef JS_OOM_DO_BACKTRACES +#include +#include +#endif + #include "jstypes.h" #ifdef __cplusplus @@ -112,10 +117,43 @@ extern JS_PUBLIC_API(void) JS_Abort(void); */ extern JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations; /* set from shell/js.cpp */ extern JS_PUBLIC_DATA(uint32_t) OOM_counter; /* data race, who cares. */ + +#ifdef JS_OOM_DO_BACKTRACES +#define JS_OOM_BACKTRACE_SIZE 32 +static JS_ALWAYS_INLINE void +PrintBacktrace() +{ + void* OOM_trace[JS_OOM_BACKTRACE_SIZE]; + char** OOM_traceSymbols = NULL; + int32_t OOM_traceSize = 0; + int32_t OOM_traceIdx = 0; + OOM_traceSize = backtrace(OOM_trace, JS_OOM_BACKTRACE_SIZE); + OOM_traceSymbols = backtrace_symbols(OOM_trace, OOM_traceSize); + + if (!OOM_traceSymbols) + return; + + for (OOM_traceIdx = 0; OOM_traceIdx < OOM_traceSize; ++OOM_traceIdx) { + fprintf(stderr, "#%d %s\n", OOM_traceIdx, OOM_traceSymbols[OOM_traceIdx]); + } + + free(OOM_traceSymbols); +} + +#define JS_OOM_EMIT_BACKTRACE() \ + do {\ + fprintf(stderr, "Forcing artificial memory allocation function failure:\n");\ + PrintBacktrace();\ + } while (0) +# else +# define JS_OOM_EMIT_BACKTRACE() do {} while(0) +#endif /* JS_OOM_DO_BACKTRACES */ + # define JS_OOM_POSSIBLY_FAIL() \ do \ { \ if (++OOM_counter > OOM_maxAllocations) { \ + JS_OOM_EMIT_BACKTRACE();\ return NULL; \ } \ } while (0) diff --git a/js/src/configure.in b/js/src/configure.in index a6277a51ed75..f767a37b1d76 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -4527,6 +4527,18 @@ if test -n "$JS_MORE_DETERMINISTIC"; then AC_DEFINE(JS_MORE_DETERMINISTIC) fi +dnl ======================================================== +dnl Enable output of backtraces on artificial OOMs +dnl ======================================================== +MOZ_ARG_ENABLE_BOOL(oom-backtrace, +[ --enable-oom-backtrace + Enable output of backtraces on artificial OOMs (-A)], + JS_OOM_DO_BACKTRACES=1, + JS_OOM_DO_BACKTRACES= ) +if test -n "$JS_OOM_DO_BACKTRACES"; then + AC_DEFINE(JS_OOM_DO_BACKTRACES) +fi + dnl ====================================================== dnl = Enable compiling with ccache dnl ====================================================== diff --git a/js/src/ds/LifoAlloc.h b/js/src/ds/LifoAlloc.h index 4d269fba483f..715d241bafb9 100644 --- a/js/src/ds/LifoAlloc.h +++ b/js/src/ds/LifoAlloc.h @@ -221,6 +221,8 @@ class LifoAlloc JS_ALWAYS_INLINE void *alloc(size_t n) { + JS_OOM_POSSIBLY_FAIL(); + void *result; if (latest && (result = latest->tryAlloc(n))) return result; diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 823f6a289935..c1cd20e4fc21 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -3846,10 +3846,9 @@ mjit::stubs::NewDenseUnallocatedArray(VMFrame &f, uint32_t length) { JSObject *proto = (JSObject *) f.scratch; JSObject *obj = NewArray(f.cx, length, proto); - if (!obj) { - js_ReportOutOfMemory(f.cx); + if (!obj) THROWV(NULL); - } + return obj; } #endif diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 5f9e9330dc9e..feb489a0d8ae 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -407,6 +407,9 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize) JS_ASSERT(!cx->runtime->gcRunning); JS_ASSERT(!cx->runtime->noGCOrAllocationCheck); + /* For testing out of memory conditions */ + JS_OOM_POSSIBLY_FAIL(); + #ifdef JS_GC_ZEAL if (cx->runtime->needZealousGC()) js::gc::RunDebugGC(cx); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 4f62733e0140..8d93467a097d 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -1076,8 +1076,10 @@ JSObject::createDenseArray(JSContext *cx, js::gc::AllocKind kind, uint32_t capacity = js::gc::GetGCKindSlots(kind) - js::ObjectElements::VALUES_PER_HEADER; JSObject *obj = js_NewGCObject(cx, kind); - if (!obj) + if (!obj) { + js_ReportOutOfMemory(cx); return NULL; + } obj->shape_.init(shape); obj->type_.init(type); diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 53f381a56ede..c79011f433a7 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -451,8 +451,10 @@ JSObject::toDictionaryMode(JSContext *cx) JS_ASSERT(!shape->inDictionary()); Shape *dprop = js_NewGCShape(cx); - if (!dprop) + if (!dprop) { + js_ReportOutOfMemory(cx); return false; + } HeapPtrShape *listp = dictionaryShape ? &dictionaryShape->parent @@ -466,8 +468,10 @@ JSObject::toDictionaryMode(JSContext *cx) shape = shape->previous(); } - if (!root->hashify(cx)) + if (!root->hashify(cx)) { + js_ReportOutOfMemory(cx); return false; + } JS_ASSERT((Shape **) root->listp == root.address()); root->listp = &self->shape_; diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 04c339d8738c..aff5cc39773d 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -408,8 +408,10 @@ mjit::Compiler::pushActiveFrame(JSScript *script, uint32_t argc) script->initCounts(cx); ActiveFrame *newa = OffTheBooks::new_(cx); - if (!newa) + if (!newa) { + js_ReportOutOfMemory(cx); return Compile_Error; + } newa->parent = a; if (a) @@ -624,8 +626,10 @@ mjit::Compiler::prepareInferenceTypes(JSScript *script, ActiveFrame *a) a->varTypes = (VarType *) OffTheBooks::calloc_(TotalSlots(script) * sizeof(VarType)); - if (!a->varTypes) + if (!a->varTypes) { + js_ReportOutOfMemory(cx); return Compile_Error; + } for (uint32_t slot = ArgSlot(0); slot < TotalSlots(script); slot++) { VarType &vt = a->varTypes[slot]; @@ -6998,8 +7002,10 @@ mjit::Compiler::startLoop(jsbytecode *head, Jump entry, jsbytecode *entryTarget) } LoopState *nloop = OffTheBooks::new_(cx, &ssa, this, &frame); - if (!nloop || !nloop->init(head, entry, entryTarget)) + if (!nloop || !nloop->init(head, entry, entryTarget)) { + js_ReportOutOfMemory(cx); return false; + } nloop->outer = loop; loop = nloop; @@ -7175,8 +7181,10 @@ mjit::Compiler::jumpAndRun(Jump j, jsbytecode *target, Jump *slow, bool *trampol RegisterAllocation *&alloc = analysis->getAllocation(target); if (!alloc) { alloc = cx->typeLifoAlloc().new_(false); - if (!alloc) + if (!alloc) { + js_ReportOutOfMemory(cx); return false; + } } lvtarget = alloc; consistent = frame.consistentRegisters(target); diff --git a/js/src/methodjit/FrameState.cpp b/js/src/methodjit/FrameState.cpp index a9b24b677d49..28f91d39950f 100644 --- a/js/src/methodjit/FrameState.cpp +++ b/js/src/methodjit/FrameState.cpp @@ -575,8 +575,10 @@ FrameState::computeAllocation(jsbytecode *target) { JS_ASSERT(cx->typeInferenceEnabled()); RegisterAllocation *alloc = cx->typeLifoAlloc().new_(false); - if (!alloc) + if (!alloc) { + js_ReportOutOfMemory(cx); return NULL; + } /* * State must be synced at exception and switch targets, at traps and when @@ -856,8 +858,10 @@ FrameState::discardForJoin(RegisterAllocation *&alloc, uint32_t stackDepth) * loop head, and for exception, switch target and trap safe points. */ alloc = cx->typeLifoAlloc().new_(false); - if (!alloc) + if (!alloc) { + js_ReportOutOfMemory(cx); return false; + } } resetInternalState(); diff --git a/js/src/methodjit/LoopState.cpp b/js/src/methodjit/LoopState.cpp index 7f78c6bc2b4a..abd36d586fd0 100644 --- a/js/src/methodjit/LoopState.cpp +++ b/js/src/methodjit/LoopState.cpp @@ -158,8 +158,10 @@ LoopState::init(jsbytecode *head, Jump entry, jsbytecode *entryTarget) JS_ASSERT(!alloc); alloc = cx->typeLifoAlloc().new_(true); - if (!alloc) + if (!alloc) { + js_ReportOutOfMemory(cx); return false; + } this->alloc = alloc; this->loopRegs = Registers::AvailAnyRegs; diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index e5a27d0681f1..ae32270c8d7c 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -1,6 +1,5 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version @@ -255,30 +254,12 @@ XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal, mScriptObjectPrincipal = sop; // Lookup 'globalObject.Object.prototype' for our wrapper's proto - { - AutoJSErrorAndExceptionEater eater(ccx); // scoped error eater - - jsval val; - jsid idObj = mRuntime->GetStringID(XPCJSRuntime::IDX_OBJECT); - jsid idProto = mRuntime->GetStringID(XPCJSRuntime::IDX_PROTOTYPE); - - // When creating a new scope to boostrap a new global, we don't yet have - // an XPCWrappedNative associated with the global object. However, the - // resolve hook on the JSClass assumes there is one. So we need to avoid - // resolving anything on the global object until things get a bit further - // along. As such, we manually resolve |Object| before accessing it below. - JSBool didResolve; - - if (JS_ResolveStandardClass(ccx, aGlobal, idObj, &didResolve) && - JS_GetPropertyById(ccx, aGlobal, idObj, &val) && - !JSVAL_IS_PRIMITIVE(val) && - JS_GetPropertyById(ccx, JSVAL_TO_OBJECT(val), idProto, &val) && - !JSVAL_IS_PRIMITIVE(val)) { - mPrototypeJSObject = JSVAL_TO_OBJECT(val); - } else { - NS_ERROR("Can't get globalObject.Object.prototype"); - } - } + JSObject *objectPrototype = + JS_GetObjectPrototype(ccx.GetJSContext(), aGlobal); + if (objectPrototype) + mPrototypeJSObject = objectPrototype; + else + NS_ERROR("Can't get globalObject.Object.prototype"); // Clear the no helper wrapper prototype object so that a new one // gets created if needed. diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 222f8677e32a..737ba901656f 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -3954,30 +3954,6 @@ private: PRInt64 mTimeStamp; }; -/***************************************************************************/ - -class NS_STACK_CLASS AutoJSErrorAndExceptionEater -{ -public: - AutoJSErrorAndExceptionEater(JSContext* aCX - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : mCX(aCX), - mOldErrorReporter(JS_SetErrorReporter(mCX, nsnull)), - mOldExceptionState(JS_SaveExceptionState(mCX)) { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - ~AutoJSErrorAndExceptionEater() - { - JS_SetErrorReporter(mCX, mOldErrorReporter); - JS_RestoreExceptionState(mCX, mOldExceptionState); - } -private: - JSContext* mCX; - JSErrorReporter mOldErrorReporter; - JSExceptionState* mOldExceptionState; - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - /****************************************************************************** * Handles pre/post script processing and the setting/resetting the error * reporter diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index e1f55b2f7391..6eedc39707e8 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -3534,7 +3534,15 @@ const nsCSSFrameConstructor::FrameConstructionData* nsCSSFrameConstructor::FindCanvasData(Element* aElement, nsStyleContext* aStyleContext) { - if (!aElement->OwnerDoc()->IsScriptEnabled()) { + // We want to check whether script is enabled on the document that + // could be painting to the canvas. That's the owner document of + // the canvas, except when the owner document is a static document, + // in which case it's the original document it was cloned from. + nsIDocument* doc = aElement->OwnerDoc(); + if (doc->IsStaticDocument()) { + doc = doc->GetOriginalDocument(); + } + if (!doc->IsScriptEnabled()) { return nsnull; } @@ -3906,6 +3914,12 @@ bool IsXULDisplayType(const nsStyleDisplay* aDisplay) #define SCROLLABLE_XUL_FCDATA(_func) \ FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_SKIP_ABSPOS_PUSH | \ FCDATA_MAY_NEED_SCROLLFRAME, _func) +// .. but we allow some XUL frames to be _containers_ for out-of-flow content +// (This is the same as SCROLLABLE_XUL_FCDATA, but w/o FCDATA_SKIP_ABSPOS_PUSH) +#define SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func) \ + FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | \ + FCDATA_MAY_NEED_SCROLLFRAME, _func) + #define SIMPLE_XUL_CREATE(_tag, _func) \ { &nsGkAtoms::_tag, SIMPLE_XUL_FCDATA(_func) } #define SCROLLABLE_XUL_CREATE(_tag, _func) \ @@ -3914,6 +3928,8 @@ bool IsXULDisplayType(const nsStyleDisplay* aDisplay) { _int, SIMPLE_XUL_FCDATA(_func) } #define SCROLLABLE_XUL_INT_CREATE(_int, _func) \ { _int, SCROLLABLE_XUL_FCDATA(_func) } +#define SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(_int, _func) \ + { _int, SCROLLABLE_ABSPOS_CONTAINER_XUL_FCDATA(_func) } static nsIFrame* NS_NewGridBoxFrame(nsIPresShell* aPresShell, @@ -4109,8 +4125,10 @@ nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay, nsStyleContext* aStyleContext) { static const FrameConstructionDataByInt sXULDisplayData[] = { - SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_BOX, NS_NewBoxFrame), - SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_BOX, NS_NewBoxFrame), + SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_BOX, + NS_NewBoxFrame), + SCROLLABLE_ABSPOS_CONTAINER_XUL_INT_CREATE(NS_STYLE_DISPLAY_BOX, + NS_NewBoxFrame), #ifdef MOZ_XUL SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_INLINE_GRID, NS_NewGridBoxFrame), SCROLLABLE_XUL_INT_CREATE(NS_STYLE_DISPLAY_GRID, NS_NewGridBoxFrame), diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 1a46283afac5..50276c4f1e71 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -90,7 +90,6 @@ #ifdef MOZ_MEDIA #include "nsHTMLVideoElement.h" #endif -#include "nsGenericHTMLElement.h" #include "imgIRequest.h" #include "nsIImageLoadingContent.h" #include "nsCOMPtr.h" @@ -4202,7 +4201,7 @@ nsLayoutUtils::SurfaceFromElement(dom::Element* aElement, surf = imgSurf; } - result.mCORSUsed = video->GetCORSMode() != nsGenericHTMLElement::CORS_NONE; + result.mCORSUsed = video->GetCORSMode() != CORS_NONE; result.mSurface = surf; result.mSize = size; result.mPrincipal = principal.forget(); diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 6b0f5812a1e0..3af971276632 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -2269,7 +2269,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) // The line is empty. Try the next one. NS_ASSERTION(pulledLine->GetChildCount() == 0 && !pulledLine->mFirstChild, "bad empty line"); - aState.FreeLineBox(pulledLine); + FreeLineBox(pulledLine); continue; } @@ -2464,7 +2464,7 @@ nsBlockFrame::DeleteLine(nsBlockReflowState& aState, "but perhaps OK now"); nsLineBox *line = aLine; aLine = mLines.erase(aLine); - aState.FreeLineBox(line); + FreeLineBox(line); // Mark the previous margin of the next line dirty since we need to // recompute its top position. if (aLine != aLineEnd) @@ -2671,16 +2671,14 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState, } // when aFromContainer is 'this', then aLine->LastChild()'s next sibling // is already set correctly. - aLine->SetChildCount(aLine->GetChildCount() + 1); - - PRInt32 fromLineChildCount = fromLine->GetChildCount(); - if (0 != --fromLineChildCount) { + aLine->NoteFrameAdded(frame); + + if (fromLine->GetChildCount() > 1) { // Mark line dirty now that we pulled a child - fromLine->SetChildCount(fromLineChildCount); + fromLine->NoteFrameRemoved(frame); fromLine->MarkDirty(); fromLine->mFirstChild = newFirstChild; - } - else { + } else { // Free up the fromLine now that it's empty // Its bounds might need to be redrawn, though. // XXX WHY do we invalidate the bounds AND the combined area? doesn't @@ -2696,7 +2694,7 @@ nsBlockFrame::PullFrameFrom(nsBlockReflowState& aState, Invalidate(fromLine->GetVisualOverflowArea()); fromLineList->erase(aFromLine); // aFromLine is now invalid - aState.FreeLineBox(fromLine); + FreeLineBox(fromLine); // Put any remaining overflow lines back. if (aFromOverflowLine) { @@ -3305,7 +3303,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState, // Push continuation to a new line, but only if we actually made one. if (madeContinuation) { - nsLineBox* line = aState.NewLineBox(nextFrame, 1, true); + nsLineBox* line = NewLineBox(nextFrame, true); NS_ENSURE_TRUE(line, NS_ERROR_OUT_OF_MEMORY); mLines.after_insert(aLine, line); } @@ -3639,7 +3637,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, nsLineBox *toremove = aLine; aLine = mLines.erase(aLine); NS_ASSERTION(nsnull == toremove->mFirstChild, "bad empty line"); - aState.FreeLineBox(toremove); + FreeLineBox(toremove); } --aLine; @@ -3976,7 +3974,7 @@ nsBlockFrame::CreateContinuationFor(nsBlockReflowState& aState, mFrames.InsertFrame(nsnull, aFrame, newFrame); if (aLine) { - aLine->SetChildCount(aLine->GetChildCount() + 1); + aLine->NoteFrameAdded(newFrame); } aMadeNewFrame = true; @@ -4099,12 +4097,11 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState, #endif // Put frames being split out into their own line - nsLineBox* newLine = aState.NewLineBox(aFrame, pushCount, false); + nsLineBox* newLine = NewLineBox(aLine, aFrame, pushCount); if (!newLine) { return NS_ERROR_OUT_OF_MEMORY; } mLines.after_insert(aLine, newLine); - aLine->SetChildCount(aLine->GetChildCount() - pushCount); #ifdef DEBUG if (gReallyNoisyReflow) { newLine->List(stdout, gNoiseIndent+1); @@ -4874,8 +4871,6 @@ nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling) aPrevSibling = GetInsideBullet(); } - nsIPresShell *presShell = PresContext()->PresShell(); - // Attempt to find the line that contains the previous sibling FrameLines* overflowLines; nsLineList* lineList = &mLines; @@ -4922,12 +4917,11 @@ nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling) PRInt32 rem = prevSibLine->GetChildCount() - prevSiblingIndex - 1; if (rem) { // Split the line in two where the frame(s) are being inserted. - nsLineBox* line = NS_NewLineBox(presShell, aPrevSibling->GetNextSibling(), rem, false); + nsLineBox* line = NewLineBox(prevSibLine, aPrevSibling->GetNextSibling(), rem); if (!line) { return NS_ERROR_OUT_OF_MEMORY; } lineList->after_insert(prevSibLine, line); - prevSibLine->SetChildCount(prevSibLine->GetChildCount() - rem); // Mark prevSibLine dirty and as needing textrun invalidation, since // we may be breaking up text in the line. Its previous line may also // need to be invalidated because it may be able to pull some text up. @@ -4968,7 +4962,7 @@ nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling) (aPrevSibling && ShouldPutNextSiblingOnNewLine(aPrevSibling))) { // Create a new line for the frame and add its line to the line // list. - nsLineBox* line = NS_NewLineBox(presShell, newFrame, 1, isBlock); + nsLineBox* line = NewLineBox(newFrame, isBlock); if (!line) { return NS_ERROR_OUT_OF_MEMORY; } @@ -4984,7 +4978,7 @@ nsBlockFrame::AddFrames(nsFrameList& aFrameList, nsIFrame* aPrevSibling) } } else { - prevSibLine->SetChildCount(prevSibLine->GetChildCount() + 1); + prevSibLine->NoteFrameAdded(newFrame); // We're adding inline content to prevSibLine, so we need to mark it // dirty, ensure its textruns are recomputed, and possibly do the same // to its previous line since that line may be able to pull content up. @@ -5506,9 +5500,7 @@ nsBlockFrame::DoRemoveFrame(nsIFrame* aDeletedFrame, PRUint32 aFlags) } // Update the child count of the line to be accurate - PRInt32 lineChildCount = line->GetChildCount(); - lineChildCount--; - line->SetChildCount(lineChildCount); + line->NoteFrameRemoved(aDeletedFrame); // Destroy frame; capture its next continuation first in case we need // to destroy that too. @@ -5535,7 +5527,7 @@ nsBlockFrame::DoRemoveFrame(nsIFrame* aDeletedFrame, PRUint32 aFlags) bool haveAdvancedToNextLine = false; // If line is empty, remove it now. - if (0 == lineChildCount) { + if (0 == line->GetChildCount()) { #ifdef NOISY_REMOVE_FRAME printf("DoRemoveFrame: %s line=%p became empty so it will be removed\n", searchingOverflowList?"overflow":"normal", line.get()); @@ -5688,12 +5680,10 @@ nsBlockFrame::StealFrame(nsPresContext* aPresContext, } // Register removal with the line boxes - PRInt32 count = line->GetChildCount(); - line->SetChildCount(--count); - if (count > 0) { + line->NoteFrameRemoved(frame); + if (line->GetChildCount() > 0) { line->MarkDirty(); - } - else { + } else { // Remove the line box nsLineBox* lineBox = line; if (searchingOverflowList) { @@ -5712,8 +5702,7 @@ nsBlockFrame::StealFrame(nsPresContext* aPresContext, line_end = mLines.end(); line = line_end; } - } - else { + } else { line = mLines.erase(line); } lineBox->Destroy(aPresContext->PresShell()); diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index b61207fdc3b2..dfbb1ec62072 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -354,6 +354,16 @@ protected: #endif #endif + nsLineBox* NewLineBox(nsIFrame* aFrame, bool aIsBlock) { + return NS_NewLineBox(PresContext()->PresShell(), aFrame, aIsBlock); + } + nsLineBox* NewLineBox(nsLineBox* aFromLine, nsIFrame* aFrame, PRInt32 aCount) { + return NS_NewLineBox(PresContext()->PresShell(), aFromLine, aFrame, aCount); + } + void FreeLineBox(nsLineBox* aLine) { + aLine->Destroy(PresContext()->PresShell()); + } + void TryAllLines(nsLineList::iterator* aIterator, nsLineList::iterator* aStartIterator, nsLineList::iterator* aEndIterator, diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index 144606a5e88f..b62d989a4c5e 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -149,22 +149,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState, mMinLineHeight = aReflowState.CalcLineHeight(); } -nsLineBox* -nsBlockReflowState::NewLineBox(nsIFrame* aFrame, - PRInt32 aCount, - bool aIsBlock) -{ - return NS_NewLineBox(mPresContext->PresShell(), aFrame, aCount, aIsBlock); -} - -void -nsBlockReflowState::FreeLineBox(nsLineBox* aLine) -{ - if (aLine) { - aLine->Destroy(mPresContext->PresShell()); - } -} - void nsBlockReflowState::ComputeReplacedBlockOffsetsForFloats(nsIFrame* aFrame, const nsRect& aFloatAvailableSpace, diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index f8a022ea2e26..a27925b686a3 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -179,10 +179,6 @@ public: } } - nsLineBox* NewLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock); - - void FreeLineBox(nsLineBox* aLine); - //---------------------------------------- // This state is the "global" state computed once for the reflow of diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index a82bc6afde07..2fddfaddd876 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -7560,6 +7560,20 @@ nsFrame::DoLayout(nsBoxLayoutState& aState) desiredSize.width = size.width; desiredSize.height = size.height; desiredSize.UnionOverflowAreasWithDesiredBounds(); + + if (HasAbsolutelyPositionedChildren()) { + // Set up a |reflowState| to pass into ReflowAbsoluteFrames + nsHTMLReflowState reflowState(aState.PresContext(), this, + aState.GetRenderingContext(), + nsSize(size.width, NS_UNCONSTRAINEDSIZE)); + + // Set up a |reflowStatus| to pass into ReflowAbsoluteFrames + // (just a dummy value; hopefully that's OK) + nsReflowStatus reflowStatus = NS_FRAME_COMPLETE; + ReflowAbsoluteFrames(aState.PresContext(), desiredSize, + reflowState, reflowStatus); + } + FinishAndStoreOverflow(desiredSize.mOverflowAreas, size); SyncLayout(aState); diff --git a/layout/generic/nsLineBox.cpp b/layout/generic/nsLineBox.cpp index 6ef3a1fc40bc..728b2d6eac17 100644 --- a/layout/generic/nsLineBox.cpp +++ b/layout/generic/nsLineBox.cpp @@ -55,6 +55,11 @@ static PRInt32 ctorCount; PRInt32 nsLineBox::GetCtorCount() { return ctorCount; } #endif +#ifndef _MSC_VER +// static nsLineBox constant; initialized in the header file. +const PRUint32 nsLineBox::kMinChildCountForHashtable; +#endif + nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock) : mFirstChild(aFrame), mBounds(0, 0, 0, 0), @@ -76,7 +81,7 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock) #if NS_STYLE_CLEAR_NONE > 0 mFlags.mBreakType = NS_STYLE_CLEAR_NONE; #endif - SetChildCount(aCount); + mChildCount = aCount; MarkDirty(); mFlags.mBlock = aIsBlock; } @@ -84,14 +89,88 @@ nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, bool aIsBlock) nsLineBox::~nsLineBox() { MOZ_COUNT_DTOR(nsLineBox); + if (NS_UNLIKELY(mFlags.mHasHashedFrames)) { + delete mFrames; + } Cleanup(); } nsLineBox* -NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame, - PRInt32 aCount, bool aIsBlock) +NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame, bool aIsBlock) { - return new (aPresShell)nsLineBox(aFrame, aCount, aIsBlock); + return new (aPresShell) nsLineBox(aFrame, 1, aIsBlock); +} + +nsLineBox* +NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine, + nsIFrame* aFrame, PRInt32 aCount) +{ + nsLineBox* newLine = new (aPresShell) nsLineBox(aFrame, aCount, false); + if (newLine) { + newLine->NoteFramesMovedFrom(aFromLine); + } + return newLine; +} + +void +nsLineBox::StealHashTableFrom(nsLineBox* aFromLine, PRUint32 aFromLineNewCount) +{ + MOZ_ASSERT(!mFlags.mHasHashedFrames); + MOZ_ASSERT(GetChildCount() >= PRInt32(aFromLineNewCount)); + mFrames = aFromLine->mFrames; + mFlags.mHasHashedFrames = 1; + aFromLine->mFlags.mHasHashedFrames = 0; + aFromLine->mChildCount = aFromLineNewCount; + // remove aFromLine's frames that aren't on this line + nsIFrame* f = aFromLine->mFirstChild; + for (PRUint32 i = 0; i < aFromLineNewCount; f = f->GetNextSibling(), ++i) { + mFrames->RemoveEntry(f); + } +} + +void +nsLineBox::NoteFramesMovedFrom(nsLineBox* aFromLine) +{ + PRUint32 fromCount = aFromLine->GetChildCount(); + PRUint32 toCount = GetChildCount(); + MOZ_ASSERT(toCount <= fromCount, "moved more frames than aFromLine has"); + PRUint32 fromNewCount = fromCount - toCount; + if (NS_LIKELY(!aFromLine->mFlags.mHasHashedFrames)) { + aFromLine->mChildCount = fromNewCount; + MOZ_ASSERT(toCount < kMinChildCountForHashtable); + } else if (fromNewCount < kMinChildCountForHashtable) { + // aFromLine has a hash table but will not have it after moving the frames + // so this line can steal the hash table if it needs it. + if (toCount >= kMinChildCountForHashtable) { + StealHashTableFrom(aFromLine, fromNewCount); + } else { + delete aFromLine->mFrames; + aFromLine->mFlags.mHasHashedFrames = 0; + aFromLine->mChildCount = fromNewCount; + } + } else { + // aFromLine still needs a hash table. + if (toCount < kMinChildCountForHashtable) { + // remove the moved frames from it + nsIFrame* f = mFirstChild; + for (PRUint32 i = 0; i < toCount; f = f->GetNextSibling(), ++i) { + aFromLine->mFrames->RemoveEntry(f); + } + } else if (toCount <= fromNewCount) { + // This line needs a hash table, allocate a hash table for it since that + // means fewer hash ops. + nsIFrame* f = mFirstChild; + for (PRUint32 i = 0; i < toCount; f = f->GetNextSibling(), ++i) { + aFromLine->mFrames->RemoveEntry(f); // toCount RemoveEntry + } + SwitchToHashtable(); // toCount PutEntry + } else { + // This line needs a hash table, but it's fewer hash ops to steal + // aFromLine's hash table and allocate a new hash table for that line. + StealHashTableFrom(aFromLine, fromNewCount); // fromNewCount RemoveEntry + aFromLine->SwitchToHashtable(); // fromNewCount PutEntry + } + } } // Overloaded new operator. Uses an arena (which comes from the presShell) @@ -102,21 +181,11 @@ nsLineBox::operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW return aPresShell->AllocateMisc(sz); } -// Overloaded delete operator. Doesn't actually free the memory, because we -// use an arena -void -nsLineBox::operator delete(void* aPtr, size_t sz) -{ -} - void nsLineBox::Destroy(nsIPresShell* aPresShell) { - // Destroy the object. This won't actually free the memory, though - delete this; - - // Have the pres shell recycle the memory - aPresShell->FreeMisc(sizeof(*this), (void*)this); + this->nsLineBox::~nsLineBox(); + aPresShell->FreeMisc(sizeof(*this), this); } void @@ -365,10 +434,18 @@ nsLineBox::RFindLineContaining(nsIFrame* aFrame, PRInt32* aFrameIndexInLine) { NS_PRECONDITION(aFrame, "null ptr"); + nsIFrame* curFrame = aLastFrameBeforeEnd; while (aBegin != aEnd) { --aEnd; NS_ASSERTION(aEnd->LastChild() == curFrame, "Unexpected curFrame"); + if (NS_UNLIKELY(aEnd->mFlags.mHasHashedFrames) && + !aEnd->Contains(aFrame)) { + if (aEnd->mFirstChild) { + curFrame = aEnd->mFirstChild->GetPrevSibling(); + } + continue; + } // i is the index of curFrame in aEnd PRInt32 i = aEnd->GetChildCount() - 1; while (i >= 0) { @@ -379,6 +456,7 @@ nsLineBox::RFindLineContaining(nsIFrame* aFrame, --i; curFrame = curFrame->GetPrevSibling(); } + MOZ_ASSERT(!aEnd->mFlags.mHasHashedFrames, "Contains lied to us!"); } *aFrameIndexInLine = -1; return false; diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h index f20023e30878..a024ed48be26 100644 --- a/layout/generic/nsLineBox.h +++ b/layout/generic/nsLineBox.h @@ -182,9 +182,21 @@ protected: need to rearrange the mBits bitfield; #endif -// Funtion to create a line box +/** + * Function to create a line box and initialize it with a single frame. + * If the frame was moved from another line then you're responsible + * for notifying that line using NoteFrameRemoved(). Alternatively, + * it's better to use the next function that does that for you in an + * optimal way. + */ nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame, - PRInt32 aCount, bool aIsBlock); + bool aIsBlock); +/** + * Function to create a line box and initialize it with aCount frames + * that are currently on aFromLine. + */ +nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine, + nsIFrame* aFrame, PRInt32 aCount); class nsLineList; @@ -232,13 +244,14 @@ private: // Overloaded new operator. Uses an arena (which comes from the presShell) // to perform the allocation. void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW; - void operator delete(void* aPtr, size_t sz); + void operator delete(void* aPtr, size_t sz) MOZ_DELETE; public: - // Use these two functions to allocate and destroy line boxes + // Use these functions to allocate and destroy line boxes friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame, - PRInt32 aCount, bool aIsBlock); - + bool aIsBlock); + friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine, + nsIFrame* aFrame, PRInt32 aCount); void Destroy(nsIPresShell* aPresShell); // mBlock bit @@ -284,7 +297,6 @@ public: // mImpactedByFloat bit void SetLineIsImpactedByFloat(bool aValue) { - NS_ASSERTION((false==aValue || true==aValue), "somebody is playing fast and loose with bools and bits!"); mFlags.mImpactedByFloat = aValue; } bool IsImpactedByFloat() const { @@ -293,7 +305,6 @@ public: // mLineWrapped bit void SetLineWrapped(bool aOn) { - NS_ASSERTION((false==aOn || true==aOn), "somebody is playing fast and loose with bools and bits!"); mFlags.mLineWrapped = aOn; } bool IsLineWrapped() const { @@ -302,7 +313,6 @@ public: // mInvalidateTextRuns bit void SetInvalidateTextRuns(bool aOn) { - NS_ASSERTION((false==aOn || true==aOn), "somebody is playing fast and loose with bools and bits!"); mFlags.mInvalidateTextRuns = aOn; } bool GetInvalidateTextRuns() const { @@ -344,20 +354,76 @@ public: return mFlags.mHadFloatPushed; } +private: + // Add a hash table for fast lookup when the line has more frames than this. + static const PRUint32 kMinChildCountForHashtable = 200; - // mChildCount value - PRInt32 GetChildCount() const { - return (PRInt32) mFlags.mChildCount; + /** + * Take ownership of aFromLine's hash table and remove the frames that + * stay on aFromLine from it, i.e. aFromLineNewCount frames starting with + * mFirstChild. This method is used to optimize moving a large number + * of frames from one line to the next. + */ + void StealHashTableFrom(nsLineBox* aFromLine, PRUint32 aFromLineNewCount); + + /** + * Does the equivalent of this->NoteFrameAdded and aFromLine->NoteFrameRemoved + * for each frame on this line, but in a optimized way. + */ + void NoteFramesMovedFrom(nsLineBox* aFromLine); + + void SwitchToHashtable() + { + MOZ_ASSERT(!mFlags.mHasHashedFrames); + PRUint32 count = GetChildCount(); + mFrames = new nsTHashtable< nsPtrHashKey >(); + mFlags.mHasHashedFrames = 1; + PRUint32 minSize = + NS_MAX(kMinChildCountForHashtable, PRUint32(PL_DHASH_MIN_SIZE)); + mFrames->Init(NS_MAX(count, minSize)); + for (nsIFrame* f = mFirstChild; count-- > 0; f = f->GetNextSibling()) { + mFrames->PutEntry(f); + } } - void SetChildCount(PRInt32 aNewCount) { - if (aNewCount < 0) { - NS_WARNING("negative child count"); - aNewCount = 0; + void SwitchToCounter() { + MOZ_ASSERT(mFlags.mHasHashedFrames); + PRUint32 count = GetChildCount(); + delete mFrames; + mFlags.mHasHashedFrames = 0; + mChildCount = count; + } + +public: + PRInt32 GetChildCount() const { + return NS_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Count() : mChildCount; + } + + /** + * Register that aFrame is now on this line. + */ + void NoteFrameAdded(nsIFrame* aFrame) { + if (NS_UNLIKELY(mFlags.mHasHashedFrames)) { + mFrames->PutEntry(aFrame); + } else { + if (++mChildCount >= kMinChildCountForHashtable) { + SwitchToHashtable(); + } } - if (aNewCount > LINE_MAX_CHILD_COUNT) { - aNewCount = LINE_MAX_CHILD_COUNT; + } + + /** + * Register that aFrame is not on this line anymore. + */ + void NoteFrameRemoved(nsIFrame* aFrame) { + MOZ_ASSERT(GetChildCount() > 0); + if (NS_UNLIKELY(mFlags.mHasHashedFrames)) { + mFrames->RemoveEntry(aFrame); + if (mFrames->Count() < kMinChildCountForHashtable) { + SwitchToCounter(); + } + } else { + --mChildCount; } - mFlags.mChildCount = aNewCount; } // mBreakType value @@ -473,10 +539,13 @@ public: nsIFrame* LastChild() const; #endif +private: PRInt32 IndexOf(nsIFrame* aFrame) const; +public: bool Contains(nsIFrame* aFrame) const { - return IndexOf(aFrame) >= 0; + return NS_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Contains(aFrame) + : IndexOf(aFrame) >= 0; } // whether the line box is "logically" empty (just like nsIFrame::IsEmpty) @@ -504,6 +573,12 @@ public: nsRect mBounds; + // mFlags.mHasHashedFrames says which one to use + union { + nsTHashtable< nsPtrHashKey >* mFrames; + PRUint32 mChildCount; + }; + struct FlagBits { PRUint32 mDirty : 1; PRUint32 mPreviousMarginDirty : 1; @@ -521,10 +596,8 @@ public: // Indicates that this line *may* have a placeholder for a float // that was pushed to a later column or page. PRUint32 mHadFloatPushed : 1; + PRUint32 mHasHashedFrames: 1; PRUint32 mBreakType : 4; - - // FIXME: Move this out of FlagBits - PRUint32 mChildCount; }; struct ExtraData { diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 2d26bde5a3ab..45364479f1be 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -5692,24 +5692,23 @@ nsTypedSelection::NotifySelectionListeners() if (!mFrameSelection) return NS_OK;//nothing to do - if (mFrameSelection->GetBatching()){ + if (mFrameSelection->GetBatching()) { mFrameSelection->SetDirty(); return NS_OK; } - PRInt32 cnt = mSelectionListeners.Count(); nsCOMArray selectionListeners(mSelectionListeners); - + PRInt32 cnt = selectionListeners.Count(); + if (cnt != mSelectionListeners.Count()) { + return NS_ERROR_OUT_OF_MEMORY; // nsCOMArray is fallible + } nsCOMPtr domdoc; nsCOMPtr shell; nsresult rv = GetPresShell(getter_AddRefs(shell)); if (NS_SUCCEEDED(rv) && shell) domdoc = do_QueryInterface(shell->GetDocument()); short reason = mFrameSelection->PopReason(); - for (PRInt32 i = 0; i < cnt; i++) - { - nsISelectionListener* thisListener = selectionListeners[i]; - if (thisListener) - thisListener->NotifySelectionChanged(domdoc, this, reason); + for (PRInt32 i = 0; i < cnt; i++) { + selectionListeners[i]->NotifySelectionChanged(domdoc, this, reason); } return NS_OK; } diff --git a/layout/reftests/box/flexbox-abspos-container-1-ref.html b/layout/reftests/box/flexbox-abspos-container-1-ref.html new file mode 100644 index 000000000000..fbeaabf32aa5 --- /dev/null +++ b/layout/reftests/box/flexbox-abspos-container-1-ref.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/box/flexbox-abspos-container-1a.html b/layout/reftests/box/flexbox-abspos-container-1a.html new file mode 100644 index 000000000000..1f6ee21a70d9 --- /dev/null +++ b/layout/reftests/box/flexbox-abspos-container-1a.html @@ -0,0 +1,30 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/box/flexbox-abspos-container-1b.html b/layout/reftests/box/flexbox-abspos-container-1b.html new file mode 100644 index 000000000000..b19072382add --- /dev/null +++ b/layout/reftests/box/flexbox-abspos-container-1b.html @@ -0,0 +1,29 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/box/flexbox-abspos-container-1c.html b/layout/reftests/box/flexbox-abspos-container-1c.html new file mode 100644 index 000000000000..553c9fc1b78c --- /dev/null +++ b/layout/reftests/box/flexbox-abspos-container-1c.html @@ -0,0 +1,33 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/box/flexbox-abspos-container-1d.html b/layout/reftests/box/flexbox-abspos-container-1d.html new file mode 100644 index 000000000000..78bb84fa75d7 --- /dev/null +++ b/layout/reftests/box/flexbox-abspos-container-1d.html @@ -0,0 +1,31 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/box/flexbox-abspos-container-2-ref.html b/layout/reftests/box/flexbox-abspos-container-2-ref.html new file mode 100644 index 000000000000..d3ef61188765 --- /dev/null +++ b/layout/reftests/box/flexbox-abspos-container-2-ref.html @@ -0,0 +1,27 @@ + + + + + + +
+
+
+ + diff --git a/layout/reftests/box/flexbox-abspos-container-2.html b/layout/reftests/box/flexbox-abspos-container-2.html new file mode 100644 index 000000000000..aa3013f534e0 --- /dev/null +++ b/layout/reftests/box/flexbox-abspos-container-2.html @@ -0,0 +1,31 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/box/flexbox-child-is-abspos-container-1-ref.html b/layout/reftests/box/flexbox-child-is-abspos-container-1-ref.html new file mode 100644 index 000000000000..8e62ec1815a4 --- /dev/null +++ b/layout/reftests/box/flexbox-child-is-abspos-container-1-ref.html @@ -0,0 +1,29 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/box/flexbox-child-is-abspos-container-1.html b/layout/reftests/box/flexbox-child-is-abspos-container-1.html new file mode 100644 index 000000000000..c5892758dc42 --- /dev/null +++ b/layout/reftests/box/flexbox-child-is-abspos-container-1.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/box/flexbox-child-is-abspos-container-2-ref.html b/layout/reftests/box/flexbox-child-is-abspos-container-2-ref.html new file mode 100644 index 000000000000..de5abf137d6b --- /dev/null +++ b/layout/reftests/box/flexbox-child-is-abspos-container-2-ref.html @@ -0,0 +1,30 @@ + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/box/flexbox-child-is-abspos-container-2.html b/layout/reftests/box/flexbox-child-is-abspos-container-2.html new file mode 100644 index 000000000000..dad64a157946 --- /dev/null +++ b/layout/reftests/box/flexbox-child-is-abspos-container-2.html @@ -0,0 +1,34 @@ + + + + + + + +
+
+
+
+
+ + diff --git a/layout/reftests/box/reftest.list b/layout/reftests/box/reftest.list index 7acadb49d0ea..c1056b78e15d 100644 --- a/layout/reftests/box/reftest.list +++ b/layout/reftests/box/reftest.list @@ -1,4 +1,11 @@ +== flexbox-abspos-container-1a.html flexbox-abspos-container-1-ref.html +== flexbox-abspos-container-1b.html flexbox-abspos-container-1-ref.html +== flexbox-abspos-container-1c.html flexbox-abspos-container-1-ref.html +== flexbox-abspos-container-1d.html flexbox-abspos-container-1-ref.html +== flexbox-abspos-container-2.html flexbox-abspos-container-2-ref.html == flexbox-attributes-no-box-horizontal.xhtml flexbox-attributes-no-box-horizontal-ref.xhtml == flexbox-attributes-no-box-vertical.xhtml flexbox-attributes-no-box-vertical-ref.xhtml == flexbox-attributes-no-input-horizontal.xhtml flexbox-attributes-no-input-horizontal-ref.xhtml == flexbox-attributes-no-input-vertical.xhtml flexbox-attributes-no-input-vertical-ref.xhtml +== flexbox-child-is-abspos-container-1.html flexbox-child-is-abspos-container-1-ref.html +== flexbox-child-is-abspos-container-2.html flexbox-child-is-abspos-container-2-ref.html diff --git a/layout/svg/base/src/nsISVGChildFrame.h b/layout/svg/base/src/nsISVGChildFrame.h index 38c73eec57ed..faa457ece7d7 100644 --- a/layout/svg/base/src/nsISVGChildFrame.h +++ b/layout/svg/base/src/nsISVGChildFrame.h @@ -57,6 +57,13 @@ class SVGLengthList; class SVGUserUnitList; } +/** + * This class is not particularly well named. It is inherited by some, but + * not all SVG frame classes that can be descendants of an + * nsSVGOuterSVGFrame in the frame tree. Note specifically that SVG container + * frames that do not inherit nsSVGDisplayContainerFrame do not inherit this + * class (so that's classes that only inherit nsSVGContainerFrame). + */ class nsISVGChildFrame : public nsQueryFrame { public: @@ -91,13 +98,16 @@ public: // Flags to pass to NotifySVGChange: // - // SUPPRESS_INVALIDATION - do not invalidate rendered areas (only to be - // used in conjunction with TRANSFORM_CHANGED) + // DO_NOT_NOTIFY_RENDERING_OBSERVERS - this should only be used when + // updating the descendant frames of a clipPath, + // mask, pattern or marker frame (or other similar + // NS_STATE_SVG_NONDISPLAY_CHILD frame) immediately + // prior to painting that frame's descendants. // TRANSFORM_CHANGED - the current transform matrix for this frame has changed // COORD_CONTEXT_CHANGED - the dimensions of this frame's coordinate context has // changed (percentage lengths must be reevaluated) enum SVGChangedFlags { - SUPPRESS_INVALIDATION = 0x01, + DO_NOT_NOTIFY_RENDERING_OBSERVERS = 0x01, TRANSFORM_CHANGED = 0x02, COORD_CONTEXT_CHANGED = 0x04 }; diff --git a/layout/svg/base/src/nsSVGAFrame.cpp b/layout/svg/base/src/nsSVGAFrame.cpp index a0eb9a480341..56fa7fc6d4c1 100644 --- a/layout/svg/base/src/nsSVGAFrame.cpp +++ b/layout/svg/base/src/nsSVGAFrame.cpp @@ -159,6 +159,13 @@ nsSVGAFrame::GetType() const void nsSVGAFrame::NotifySVGChanged(PRUint32 aFlags) { + NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || + (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), + "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); + + NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); + if (aFlags & TRANSFORM_CHANGED) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; diff --git a/layout/svg/base/src/nsSVGClipPathFrame.cpp b/layout/svg/base/src/nsSVGClipPathFrame.cpp index 881878e4a53d..a375f1e1f73d 100644 --- a/layout/svg/base/src/nsSVGClipPathFrame.cpp +++ b/layout/svg/base/src/nsSVGClipPathFrame.cpp @@ -102,8 +102,9 @@ nsSVGClipPathFrame::ClipPaint(nsRenderingContext* aContext, nsISVGChildFrame* SVGFrame = do_QueryFrame(kid); if (SVGFrame) { // The CTM of each frame referencing us can be different. - SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | - nsISVGChildFrame::TRANSFORM_CHANGED); + SVGFrame->NotifySVGChanged( + nsISVGChildFrame::DO_NOT_NOTIFY_RENDERING_OBSERVERS | + nsISVGChildFrame::TRANSFORM_CHANGED); bool isOK = true; nsSVGClipPathFrame *clipPathFrame = diff --git a/layout/svg/base/src/nsSVGClipPathFrame.h b/layout/svg/base/src/nsSVGClipPathFrame.h index a569ad608350..8c1d8a9d5710 100644 --- a/layout/svg/base/src/nsSVGClipPathFrame.h +++ b/layout/svg/base/src/nsSVGClipPathFrame.h @@ -49,9 +49,12 @@ class nsSVGClipPathFrame : public nsSVGClipPathFrameBase friend nsIFrame* NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); protected: - nsSVGClipPathFrame(nsStyleContext* aContext) : - nsSVGClipPathFrameBase(aContext), - mInUse(false) {} + nsSVGClipPathFrame(nsStyleContext* aContext) + : nsSVGClipPathFrameBase(aContext) + , mInUse(false) + { + AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD); + } public: NS_DECL_FRAMEARENA_HELPERS diff --git a/layout/svg/base/src/nsSVGContainerFrame.cpp b/layout/svg/base/src/nsSVGContainerFrame.cpp index fafc65e62f0e..42ab5e452897 100644 --- a/layout/svg/base/src/nsSVGContainerFrame.cpp +++ b/layout/svg/base/src/nsSVGContainerFrame.cpp @@ -51,7 +51,12 @@ nsIFrame* NS_NewSVGContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) { - return new (aPresShell) nsSVGContainerFrame(aContext); + nsIFrame *frame = new (aPresShell) nsSVGContainerFrame(aContext); + // If we were called directly, then the frame is for a or + // an unknown element type. In both cases we prevent the content + // from displaying directly. + frame->AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD); + return frame; } NS_IMPL_FRAMEARENA_HELPERS(nsSVGContainerFrame) @@ -88,16 +93,6 @@ nsSVGContainerFrame::RemoveFrame(ChildListID aListID, return NS_OK; } -NS_IMETHODIMP -nsSVGContainerFrame::Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow) -{ - AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD); - nsresult rv = nsSVGContainerFrameBase::Init(aContent, aParent, aPrevInFlow); - return rv; -} - NS_IMETHODIMP nsSVGDisplayContainerFrame::Init(nsIContent* aContent, nsIFrame* aParent, @@ -108,7 +103,7 @@ nsSVGDisplayContainerFrame::Init(nsIContent* aContent, (NS_STATE_SVG_NONDISPLAY_CHILD | NS_STATE_SVG_CLIPPATH_CHILD | NS_STATE_SVG_REDRAW_SUSPENDED)); } - nsresult rv = nsSVGContainerFrameBase::Init(aContent, aParent, aPrevInFlow); + nsresult rv = nsSVGContainerFrame::Init(aContent, aParent, aPrevInFlow); return rv; } @@ -232,8 +227,12 @@ nsSVGDisplayContainerFrame::InitialUpdate() void nsSVGDisplayContainerFrame::NotifySVGChanged(PRUint32 aFlags) { - NS_ASSERTION(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), - "Invalidation logic may need adjusting"); + NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || + (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), + "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); + + NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); nsSVGUtils::NotifyChildrenOfSVGChange(this, aFlags); } diff --git a/layout/svg/base/src/nsSVGContainerFrame.h b/layout/svg/base/src/nsSVGContainerFrame.h index 60ac96faf528..7ebdb7406261 100644 --- a/layout/svg/base/src/nsSVGContainerFrame.h +++ b/layout/svg/base/src/nsSVGContainerFrame.h @@ -47,6 +47,13 @@ class nsRenderingContext; typedef nsContainerFrame nsSVGContainerFrameBase; +/** + * Base class for SVG container frames. Frame sub-classes that do not + * display their contents directly (such as the frames for or + * ) just inherit this class. Frame sub-classes that do or can + * display their contents directly (such as the frames for inner- or + * ) inherit our nsDisplayContainerFrame sub-class. + */ class nsSVGContainerFrame : public nsSVGContainerFrameBase { friend nsIFrame* NS_NewSVGContainerFrame(nsIPresShell* aPresShell, @@ -71,9 +78,6 @@ public: nsFrameList& aFrameList); NS_IMETHOD RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame); - NS_IMETHOD Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow); virtual bool IsFrameOfType(PRUint32 aFlags) const { @@ -82,6 +86,10 @@ public: } }; +/** + * Frame class or base-class for SVG containers that can or do display their + * contents directly. + */ class nsSVGDisplayContainerFrame : public nsSVGContainerFrame, public nsISVGChildFrame { diff --git a/layout/svg/base/src/nsSVGFilterFrame.h b/layout/svg/base/src/nsSVGFilterFrame.h index 7f2659639b03..001e3e17be7f 100644 --- a/layout/svg/base/src/nsSVGFilterFrame.h +++ b/layout/svg/base/src/nsSVGFilterFrame.h @@ -49,7 +49,11 @@ class nsSVGFilterFrame : public nsSVGFilterFrameBase friend nsIFrame* NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); protected: - nsSVGFilterFrame(nsStyleContext* aContext) : nsSVGFilterFrameBase(aContext) {} + nsSVGFilterFrame(nsStyleContext* aContext) + : nsSVGFilterFrameBase(aContext) + { + AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD); + } public: NS_DECL_FRAMEARENA_HELPERS diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp index 73474c6f03dd..0d9a7b642c93 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp @@ -394,6 +394,13 @@ nsSVGForeignObjectFrame::InitialUpdate() void nsSVGForeignObjectFrame::NotifySVGChanged(PRUint32 aFlags) { + NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || + (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), + "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); + + NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); + bool reflow = false; if (aFlags & TRANSFORM_CHANGED) { @@ -405,7 +412,7 @@ nsSVGForeignObjectFrame::NotifySVGChanged(PRUint32 aFlags) // We also seem to get some sort of infinite loop post bug 421584 if we // reflow. mCanvasTM = nsnull; - if (!(aFlags & SUPPRESS_INVALIDATION)) { + if (!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS)) { UpdateGraphic(); } diff --git a/layout/svg/base/src/nsSVGGFrame.cpp b/layout/svg/base/src/nsSVGGFrame.cpp index 3f518cc3a2a2..1217d5dd6e56 100644 --- a/layout/svg/base/src/nsSVGGFrame.cpp +++ b/layout/svg/base/src/nsSVGGFrame.cpp @@ -80,6 +80,13 @@ nsSVGGFrame::GetType() const void nsSVGGFrame::NotifySVGChanged(PRUint32 aFlags) { + NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || + (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), + "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); + + NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); + if (aFlags & TRANSFORM_CHANGED) { // make sure our cached transform matrix gets (lazily) updated mCanvasTM = nsnull; diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp index d5c639ba2c4c..8b5cef7b616b 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.cpp +++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp @@ -521,10 +521,17 @@ nsSVGGlyphFrame::InitialUpdate() void nsSVGGlyphFrame::NotifySVGChanged(PRUint32 aFlags) { + NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || + (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), + "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); + + NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); + if (aFlags & TRANSFORM_CHANGED) { ClearTextRun(); } - if (!(aFlags & SUPPRESS_INVALIDATION)) { + if (!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS)) { nsSVGUtils::UpdateGraphic(this); } } diff --git a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp index 1bc90d1104d6..5d3b8db4a260 100644 --- a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp +++ b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp @@ -113,6 +113,13 @@ nsSVGInnerSVGFrame::PaintSVG(nsRenderingContext *aContext, void nsSVGInnerSVGFrame::NotifySVGChanged(PRUint32 aFlags) { + NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || + (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), + "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); + + NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); + if (aFlags & COORD_CONTEXT_CHANGED) { nsSVGSVGElement *svg = static_cast(mContent); diff --git a/layout/svg/base/src/nsSVGMarkerFrame.cpp b/layout/svg/base/src/nsSVGMarkerFrame.cpp index b45d94229979..faf6ee95e5aa 100644 --- a/layout/svg/base/src/nsSVGMarkerFrame.cpp +++ b/layout/svg/base/src/nsSVGMarkerFrame.cpp @@ -163,8 +163,9 @@ nsSVGMarkerFrame::PaintMark(nsRenderingContext *aContext, nsISVGChildFrame* SVGFrame = do_QueryFrame(kid); if (SVGFrame) { // The CTM of each frame referencing us may be different. - SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | - nsISVGChildFrame::TRANSFORM_CHANGED); + SVGFrame->NotifySVGChanged( + nsISVGChildFrame::DO_NOT_NOTIFY_RENDERING_OBSERVERS | + nsISVGChildFrame::TRANSFORM_CHANGED); nsSVGUtils::PaintFrameWithEffects(aContext, nsnull, kid); } } diff --git a/layout/svg/base/src/nsSVGMarkerFrame.h b/layout/svg/base/src/nsSVGMarkerFrame.h index d7204ebe5653..80ad9323570f 100644 --- a/layout/svg/base/src/nsSVGMarkerFrame.h +++ b/layout/svg/base/src/nsSVGMarkerFrame.h @@ -54,11 +54,14 @@ class nsSVGMarkerFrame : public nsSVGMarkerFrameBase friend nsIFrame* NS_NewSVGMarkerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); protected: - nsSVGMarkerFrame(nsStyleContext* aContext) : - nsSVGMarkerFrameBase(aContext), - mMarkedFrame(nsnull), - mInUse(false), - mInUse2(false) {} + nsSVGMarkerFrame(nsStyleContext* aContext) + : nsSVGMarkerFrameBase(aContext) + , mMarkedFrame(nsnull) + , mInUse(false) + , mInUse2(false) + { + AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD); + } public: NS_DECL_FRAMEARENA_HELPERS diff --git a/layout/svg/base/src/nsSVGMaskFrame.cpp b/layout/svg/base/src/nsSVGMaskFrame.cpp index 896086d87abb..ba92b9f7eecf 100644 --- a/layout/svg/base/src/nsSVGMaskFrame.cpp +++ b/layout/svg/base/src/nsSVGMaskFrame.cpp @@ -128,8 +128,9 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsRenderingContext *aContext, // The CTM of each frame referencing us can be different nsISVGChildFrame* SVGFrame = do_QueryFrame(kid); if (SVGFrame) { - SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | - nsISVGChildFrame::TRANSFORM_CHANGED); + SVGFrame->NotifySVGChanged( + nsISVGChildFrame::DO_NOT_NOTIFY_RENDERING_OBSERVERS | + nsISVGChildFrame::TRANSFORM_CHANGED); } nsSVGUtils::PaintFrameWithEffects(&tmpCtx, nsnull, kid); } diff --git a/layout/svg/base/src/nsSVGMaskFrame.h b/layout/svg/base/src/nsSVGMaskFrame.h index d524bc102d16..0eb040c2e333 100644 --- a/layout/svg/base/src/nsSVGMaskFrame.h +++ b/layout/svg/base/src/nsSVGMaskFrame.h @@ -51,9 +51,12 @@ class nsSVGMaskFrame : public nsSVGMaskFrameBase friend nsIFrame* NS_NewSVGMaskFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); protected: - nsSVGMaskFrame(nsStyleContext* aContext) : - nsSVGMaskFrameBase(aContext), - mInUse(false) {} + nsSVGMaskFrame(nsStyleContext* aContext) + : nsSVGMaskFrameBase(aContext) + , mInUse(false) + { + AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD); + } public: NS_DECL_FRAMEARENA_HELPERS diff --git a/layout/svg/base/src/nsSVGPaintServerFrame.h b/layout/svg/base/src/nsSVGPaintServerFrame.h index 6a1070619243..20cf76bb5c0b 100644 --- a/layout/svg/base/src/nsSVGPaintServerFrame.h +++ b/layout/svg/base/src/nsSVGPaintServerFrame.h @@ -47,8 +47,11 @@ typedef nsSVGContainerFrame nsSVGPaintServerFrameBase; class nsSVGPaintServerFrame : public nsSVGPaintServerFrameBase { protected: - nsSVGPaintServerFrame(nsStyleContext* aContext) : - nsSVGPaintServerFrameBase(aContext) {} + nsSVGPaintServerFrame(nsStyleContext* aContext) + : nsSVGPaintServerFrameBase(aContext) + { + AddStateBits(NS_STATE_SVG_NONDISPLAY_CHILD); + } public: NS_DECL_FRAMEARENA_HELPERS diff --git a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp index 110cba877db4..c389a9853649 100644 --- a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp @@ -247,7 +247,14 @@ nsSVGPathGeometryFrame::InitialUpdate() void nsSVGPathGeometryFrame::NotifySVGChanged(PRUint32 aFlags) { - if (!(aFlags & SUPPRESS_INVALIDATION)) { + NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || + (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), + "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); + + NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); + + if (!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS)) { nsSVGUtils::UpdateGraphic(this); } } diff --git a/layout/svg/base/src/nsSVGPatternFrame.cpp b/layout/svg/base/src/nsSVGPatternFrame.cpp index 02028fd4eb76..b822451dccf3 100644 --- a/layout/svg/base/src/nsSVGPatternFrame.cpp +++ b/layout/svg/base/src/nsSVGPatternFrame.cpp @@ -327,8 +327,9 @@ nsSVGPatternFrame::PaintPattern(gfxASurface** surface, // The CTM of each frame referencing us can be different nsISVGChildFrame* SVGFrame = do_QueryFrame(kid); if (SVGFrame) { - SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION | - nsISVGChildFrame::TRANSFORM_CHANGED); + SVGFrame->NotifySVGChanged( + nsISVGChildFrame::DO_NOT_NOTIFY_RENDERING_OBSERVERS | + nsISVGChildFrame::TRANSFORM_CHANGED); } nsSVGUtils::PaintFrameWithEffects(&context, nsnull, kid); } diff --git a/layout/svg/base/src/nsSVGTextFrame.cpp b/layout/svg/base/src/nsSVGTextFrame.cpp index cbdae2d8d3cd..1c3e3c2dfca5 100644 --- a/layout/svg/base/src/nsSVGTextFrame.cpp +++ b/layout/svg/base/src/nsSVGTextFrame.cpp @@ -181,6 +181,13 @@ nsSVGTextFrame::GetRotationOfChar(PRUint32 charnum, float *_retval) void nsSVGTextFrame::NotifySVGChanged(PRUint32 aFlags) { + NS_ABORT_IF_FALSE(!(aFlags & DO_NOT_NOTIFY_RENDERING_OBSERVERS) || + (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD), + "Must be NS_STATE_SVG_NONDISPLAY_CHILD!"); + + NS_ABORT_IF_FALSE(aFlags & (TRANSFORM_CHANGED | COORD_CONTEXT_CHANGED), + "Invalidation logic may need adjusting"); + bool updateGlyphMetrics = false; if (aFlags & COORD_CONTEXT_CHANGED) { diff --git a/layout/tools/reftest/reftest.js b/layout/tools/reftest/reftest.js index daa73ccc1479..20fb074a1d28 100644 --- a/layout/tools/reftest/reftest.js +++ b/layout/tools/reftest/reftest.js @@ -397,6 +397,7 @@ function StartHTTPServer() function StartTests() { + var uri; #if BOOTSTRAP /* These prefs are optional, so we don't need to spit an error to the log */ try { diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp index 476a9cd08775..38db8793c26e 100644 --- a/layout/xul/base/src/nsBoxFrame.cpp +++ b/layout/xul/base/src/nsBoxFrame.cpp @@ -758,6 +758,8 @@ nsBoxFrame::Reflow(nsPresContext* aPresContext, } #endif + ReflowAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus); + NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; } @@ -934,6 +936,35 @@ nsBoxFrame::DoLayout(nsBoxLayoutState& aState) aState.SetLayoutFlags(oldFlags); + if (HasAbsolutelyPositionedChildren()) { + // Set up a |reflowState| to pass into ReflowAbsoluteFrames + nsHTMLReflowState reflowState(aState.PresContext(), this, + aState.GetRenderingContext(), + nsSize(mRect.width, NS_UNCONSTRAINEDSIZE)); + + // Set up a |desiredSize| to pass into ReflowAbsoluteFrames + nsHTMLReflowMetrics desiredSize; + desiredSize.width = mRect.width; + desiredSize.height = mRect.height; + + // get the ascent (cribbed from ::Reflow) + nscoord ascent = mRect.height; + + // getting the ascent could be a lot of work. Don't get it if + // we are the root. The viewport doesn't care about it. + if (!(mState & NS_STATE_IS_ROOT)) { + ascent = GetBoxAscent(aState); + } + desiredSize.ascent = ascent; + desiredSize.mOverflowAreas = GetOverflowAreas(); + + // Set up a |reflowStatus| to pass into ReflowAbsoluteFrames + // (just a dummy value; hopefully that's OK) + nsReflowStatus reflowStatus = NS_FRAME_COMPLETE; + ReflowAbsoluteFrames(aState.PresContext(), desiredSize, + reflowState, reflowStatus); + } + return rv; } @@ -946,6 +977,8 @@ nsBoxFrame::DestroyFrom(nsIFrame* aDestructRoot) // clean up the container box's layout manager and child boxes SetLayoutManager(nsnull); + DestroyAbsoluteFrames(aDestructRoot); + nsContainerFrame::DestroyFrom(aDestructRoot); } diff --git a/netwerk/base/public/security-prefs.js b/netwerk/base/public/security-prefs.js index 96a2cad3d851..9644196c5d84 100644 --- a/netwerk/base/public/security-prefs.js +++ b/netwerk/base/public/security-prefs.js @@ -1,6 +1,7 @@ pref("security.enable_ssl3", true); pref("security.enable_tls", true); pref("security.enable_tls_session_tickets", true); +pref("security.enable_md5_signatures", true); pref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", false); pref("security.ssl.renego_unrestricted_hosts", ""); diff --git a/parser/html/nsHtml5SpeculativeLoad.cpp b/parser/html/nsHtml5SpeculativeLoad.cpp index 1a627866b489..6a48700672c1 100644 --- a/parser/html/nsHtml5SpeculativeLoad.cpp +++ b/parser/html/nsHtml5SpeculativeLoad.cpp @@ -61,20 +61,21 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor) aExecutor->SetSpeculationBase(mUrl); break; case eSpeculativeLoadImage: - aExecutor->PreloadImage(mUrl, mCharsetOrCrossOrigin); + aExecutor->PreloadImage(mUrl, mCrossOrigin); break; case eSpeculativeLoadScript: - aExecutor->PreloadScript(mUrl, mCharsetOrCrossOrigin, mTypeOrCharsetSource); + aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSource, + mCrossOrigin); break; case eSpeculativeLoadStyle: - aExecutor->PreloadStyle(mUrl, mCharsetOrCrossOrigin); + aExecutor->PreloadStyle(mUrl, mCharset); break; case eSpeculativeLoadManifest: aExecutor->ProcessOfflineManifest(mUrl); break; case eSpeculativeLoadSetDocumentCharset: { nsCAutoString narrowName; - CopyUTF16toUTF8(mCharsetOrCrossOrigin, narrowName); + CopyUTF16toUTF8(mCharset, narrowName); NS_ASSERTION(mTypeOrCharsetSource.Length() == 1, "Unexpected charset source string"); PRInt32 intSource = (PRInt32)mTypeOrCharsetSource.First(); diff --git a/parser/html/nsHtml5SpeculativeLoad.h b/parser/html/nsHtml5SpeculativeLoad.h index 5e512d828a60..bf3720b90d3b 100644 --- a/parser/html/nsHtml5SpeculativeLoad.h +++ b/parser/html/nsHtml5SpeculativeLoad.h @@ -72,18 +72,20 @@ class nsHtml5SpeculativeLoad { "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadImage; mUrl.Assign(aUrl); - mCharsetOrCrossOrigin.Assign(aCrossOrigin); + mCrossOrigin.Assign(aCrossOrigin); } inline void InitScript(const nsAString& aUrl, - const nsAString& aCharset, - const nsAString& aType) { + const nsAString& aCharset, + const nsAString& aType, + const nsAString& aCrossOrigin) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadScript; mUrl.Assign(aUrl); - mCharsetOrCrossOrigin.Assign(aCharset); + mCharset.Assign(aCharset); mTypeOrCharsetSource.Assign(aType); + mCrossOrigin.Assign(aCrossOrigin); } inline void InitStyle(const nsAString& aUrl, const nsAString& aCharset) { @@ -91,7 +93,7 @@ class nsHtml5SpeculativeLoad { "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadStyle; mUrl.Assign(aUrl); - mCharsetOrCrossOrigin.Assign(aCharset); + mCharset.Assign(aCharset); } /** @@ -127,7 +129,7 @@ class nsHtml5SpeculativeLoad { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadSetDocumentCharset; - CopyUTF8toUTF16(aCharset, mCharsetOrCrossOrigin); + CopyUTF8toUTF16(aCharset, mCharset); mTypeOrCharsetSource.Assign((PRUnichar)aCharsetSource); } @@ -137,14 +139,12 @@ class nsHtml5SpeculativeLoad { eHtml5SpeculativeLoad mOpCode; nsString mUrl; /** - * If mOpCode is eSpeculativeLoadImage, this is the value of the - * "crossorigin" attribute. If mOpCode is eSpeculativeLoadStyle - * or eSpeculativeLoadScript then this is the value of the - * "charset" attribute. For eSpeculativeLoadSetDocumentCharset it is - * the charset that the document's charset is being set to. Otherwise - * it's empty. + * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript + * then this is the value of the "charset" attribute. For + * eSpeculativeLoadSetDocumentCharset it is the charset that the + * document's charset is being set to. Otherwise it's empty. */ - nsString mCharsetOrCrossOrigin; + nsString mCharset; /** * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a * one-character string whose single character's code point is to be @@ -152,6 +152,12 @@ class nsHtml5SpeculativeLoad { * the value of the type attribute. */ nsString mTypeOrCharsetSource; + /** + * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript, + * this is the value of the "crossorigin" attribute. If the + * attribute is not set, this will be a void string. + */ + nsString mCrossOrigin; }; #endif // nsHtml5SpeculativeLoad_h_ diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 2a5a81331131..1fc8d73ff570 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -108,11 +108,9 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm if (url) { nsString* crossOrigin = aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); - if (crossOrigin) { - mSpeculativeLoadQueue.AppendElement()->InitImage(*url, *crossOrigin); - } else { - mSpeculativeLoadQueue.AppendElement()->InitImage(*url, EmptyString()); - } + mSpeculativeLoadQueue.AppendElement()-> + InitImage(*url, + crossOrigin ? *crossOrigin : NullString()); } } else if (nsHtml5Atoms::script == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); @@ -123,9 +121,13 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm if (url) { nsString* charset = aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); nsString* type = aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); - mSpeculativeLoadQueue.AppendElement()->InitScript(*url, - (charset) ? *charset : EmptyString(), - (type) ? *type : EmptyString()); + nsString* crossOrigin = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); + mSpeculativeLoadQueue.AppendElement()-> + InitScript(*url, + (charset) ? *charset : EmptyString(), + (type) ? *type : EmptyString(), + (crossOrigin) ? *crossOrigin : NullString()); mCurrentHtmlScriptIsAsyncOrDefer = aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) || aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER); @@ -145,7 +147,7 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm } else if (nsHtml5Atoms::video == aName) { nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER); if (url) { - mSpeculativeLoadQueue.AppendElement()->InitImage(*url, EmptyString()); + mSpeculativeLoadQueue.AppendElement()->InitImage(*url, NullString()); } } else if (nsHtml5Atoms::style == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); @@ -170,7 +172,7 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm if (nsHtml5Atoms::image == aName) { nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); if (url) { - mSpeculativeLoadQueue.AppendElement()->InitImage(*url, EmptyString()); + mSpeculativeLoadQueue.AppendElement()->InitImage(*url, NullString()); } } else if (nsHtml5Atoms::script == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); @@ -180,9 +182,13 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); if (url) { nsString* type = aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); - mSpeculativeLoadQueue.AppendElement()->InitScript(*url, - EmptyString(), - (type) ? *type : EmptyString()); + nsString* crossOrigin = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); + mSpeculativeLoadQueue.AppendElement()-> + InitScript(*url, + EmptyString(), + (type) ? *type : EmptyString(), + (crossOrigin) ? *crossOrigin : NullString()); } } else if (nsHtml5Atoms::style == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index 593a829b926c..02b9be335408 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -930,13 +930,14 @@ nsHtml5TreeOpExecutor::ConvertIfNotPreloadedYet(const nsAString& aURL) void nsHtml5TreeOpExecutor::PreloadScript(const nsAString& aURL, const nsAString& aCharset, - const nsAString& aType) + const nsAString& aType, + const nsAString& aCrossOrigin) { nsCOMPtr uri = ConvertIfNotPreloadedYet(aURL); if (!uri) { return; } - mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType); + mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin); } void diff --git a/parser/html/nsHtml5TreeOpExecutor.h b/parser/html/nsHtml5TreeOpExecutor.h index f3fda582c73e..56a43ec70abe 100644 --- a/parser/html/nsHtml5TreeOpExecutor.h +++ b/parser/html/nsHtml5TreeOpExecutor.h @@ -425,7 +425,8 @@ class nsHtml5TreeOpExecutor : public nsContentSink, void PreloadScript(const nsAString& aURL, const nsAString& aCharset, - const nsAString& aType); + const nsAString& aType, + const nsAString& aCrossOrigin); void PreloadStyle(const nsAString& aURL, const nsAString& aCharset); diff --git a/security/manager/ssl/src/nsNSSComponent.cpp b/security/manager/ssl/src/nsNSSComponent.cpp index bf1d1cff6ec9..89ad70e9a22c 100644 --- a/security/manager/ssl/src/nsNSSComponent.cpp +++ b/security/manager/ssl/src/nsNSSComponent.cpp @@ -1597,6 +1597,26 @@ nsNSSComponent::TryCFM2MachOMigration(nsIFile *cfmPath, nsIFile *machoPath) } #endif +static void configureMD5(bool enabled) +{ + if (enabled) { // set flags + NSS_SetAlgorithmPolicy(SEC_OID_MD5, + NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0); + NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, + NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0); + NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC, + NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE, 0); + } + else { // clear flags + NSS_SetAlgorithmPolicy(SEC_OID_MD5, + 0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE); + NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, + 0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE); + NSS_SetAlgorithmPolicy(SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC, + 0, NSS_USE_ALG_IN_CERT_SIGNATURE | NSS_USE_ALG_IN_CMS_SIGNATURE); + } +} + nsresult nsNSSComponent::InitializeNSS(bool showWarningBox) { @@ -1788,6 +1808,8 @@ nsNSSComponent::InitializeNSS(bool showWarningBox) SSL_OptionSetDefault(SSL_ENABLE_SSL3, enabled); mPrefBranch->GetBoolPref("security.enable_tls", &enabled); SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled); + mPrefBranch->GetBoolPref("security.enable_md5_signatures", &enabled); + configureMD5(enabled); // Configure TLS session tickets mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled); @@ -2310,6 +2332,10 @@ nsNSSComponent::Observe(nsISupports *aSubject, const char *aTopic, mPrefBranch->GetBoolPref("security.enable_tls", &enabled); SSL_OptionSetDefault(SSL_ENABLE_TLS, enabled); clearSessionCache = true; + } else if (prefName.Equals("security.enable_md5_signatures")) { + mPrefBranch->GetBoolPref("security.enable_md5_signatures", &enabled); + configureMD5(enabled); + clearSessionCache = true; } else if (prefName.Equals("security.enable_tls_session_tickets")) { mPrefBranch->GetBoolPref("security.enable_tls_session_tickets", &enabled); SSL_OptionSetDefault(SSL_ENABLE_SESSION_TICKETS, enabled); diff --git a/toolkit/components/telemetry/Telemetry.cpp b/toolkit/components/telemetry/Telemetry.cpp index 2b0ab6331fe4..585a3d897f1a 100644 --- a/toolkit/components/telemetry/Telemetry.cpp +++ b/toolkit/components/telemetry/Telemetry.cpp @@ -1128,8 +1128,10 @@ TelemetrySessionData::LoadFromDisk(nsIFile *file, TelemetrySessionData **ptr) return NS_ERROR_FAILURE; } + // If there's not even enough data to read the header for the pickle, + // don't bother. Conveniently, this handles the error case as well. PRInt32 size = PR_Available(fd); - if (size == -1) { + if (size < static_cast(sizeof(Pickle::Header))) { return NS_ERROR_FAILURE; } @@ -1142,6 +1144,13 @@ TelemetrySessionData::LoadFromDisk(nsIFile *file, TelemetrySessionData **ptr) Pickle pickle(data, size); void *iter = NULL; + // Make sure that how much data the pickle thinks it has corresponds + // with how much data we actually read. + const Pickle::Header *header = pickle.headerT(); + if (header->payload_size != static_cast(amount) - sizeof(*header)) { + return NS_ERROR_FAILURE; + } + unsigned int storedVersion; if (!(pickle.ReadUInt32(&iter, &storedVersion) && storedVersion == sVersion)) { diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index 1c647ac1d3a5..c28c87abd201 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -253,16 +253,11 @@ public: void ToString(StringBuilder &profile) { - //XXX: this code is not thread safe and needs to be fixed - // can we just have a mutex that guards access to the circular buffer? - // no because the main thread can be stopped while it still has access. - // which will cause a deadlock - int oldReadPos = mReadPos; - while (mReadPos != mLastFlushPos) { - profile.Append(mEntries[mReadPos].TagToString(this).c_str()); - mReadPos = (mReadPos + 1) % mEntrySize; + int readPos = mReadPos; + while (readPos != mLastFlushPos) { + profile.Append(mEntries[readPos].TagToString(this).c_str()); + readPos = (readPos + 1) % mEntrySize; } - mReadPos = oldReadPos; } JSObject *ToJSObject(JSContext *aCx) @@ -306,14 +301,12 @@ public: void WriteProfile(FILE* stream) { - //XXX: this code is not thread safe and needs to be fixed - int oldReadPos = mReadPos; - while (mReadPos != mLastFlushPos) { - string tag = mEntries[mReadPos].TagToString(this); + int readPos = mReadPos; + while (readPos != mLastFlushPos) { + string tag = mEntries[readPos].TagToString(this); fwrite(tag.data(), 1, tag.length(), stream); - mReadPos = (mReadPos + 1) % mEntrySize; + readPos = (readPos + 1) % mEntrySize; } - mReadPos = oldReadPos; } private: // Circular buffer 'Keep One Slot Open' implementation diff --git a/xpcom/glue/nsTHashtable.cpp b/xpcom/glue/nsTHashtable.cpp index f762d8e70970..97ef330699b5 100644 --- a/xpcom/glue/nsTHashtable.cpp +++ b/xpcom/glue/nsTHashtable.cpp @@ -92,7 +92,6 @@ PRUint32 HashString(const char *str) { PRUint32 code = 0; - const char *origStr = str; while (*str) { code = AddToHash(code, *str); @@ -106,7 +105,6 @@ PRUint32 HashString(const PRUnichar *str) { PRUint32 code = 0; - const PRUnichar *origStr = str; while (*str) { code = AddToHash(code, *str); diff --git a/xpcom/tests/unit/xpcshell.ini b/xpcom/tests/unit/xpcshell.ini index 06c522844841..785e86fb4e26 100644 --- a/xpcom/tests/unit/xpcshell.ini +++ b/xpcom/tests/unit/xpcshell.ini @@ -29,6 +29,7 @@ fail-if = os == "android" [test_mac_bundle.js] [test_nsIMutableArray.js] [test_nsIProcess.js] +skip-if = os == "win" # bug 582821 [test_nsIProcess_stress.js] skip-if = os == "win" # See bug: 676412 [test_pipe.js]