author | David Anderson <danderson@mozilla.com> |
Mon, 12 Mar 2012 12:27:40 -0700 | |
changeset 112840 | 60fb46e7940cdbf645d2ac84b0ac3b7ec2bc4add |
parent 112839 | bf6acad353e0265602c9c5ce866cc9bef41a56eb (current diff) |
parent 92038 | c6f26a8dcd084c38f63c282ba77c713c7573e549 (diff) |
child 112841 | 79b5d9b66d9a68117abbda7f3a8ed87fb99d52ce |
push id | 239 |
push user | akeybl@mozilla.com |
push date | Thu, 03 Jan 2013 21:54:43 +0000 |
treeherder | mozilla-release@3a7b66445659 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 13.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/accessible/public/nsIAccessibleEvent.idl +++ b/accessible/public/nsIAccessibleEvent.idl @@ -566,8 +566,31 @@ interface nsIAccessibleTableChangeEvent: readonly attribute long rowOrColIndex; /** * Return the number of rows or cols */ readonly attribute long numRowsOrCols; }; + +/* + * An interface for virtual cursor changed events. + * Passes previous cursor position and text offsets. + */ +[scriptable, uuid(370e8b9b-2bbc-4bff-a9c7-16ddc54aea21)] +interface nsIAccessibleVirtualCursorChangeEvent : nsISupports +{ + /** + * Previous object pointed at by virtual cursor. null if none. + */ + readonly attribute nsIAccessible oldAccessible; + + /** + * Previous start offset of pivot. -1 if none. + */ + readonly attribute long oldStartOffset; + + /** + * Previous end offset of pivot. -1 if none. + */ + readonly attribute long oldEndOffset; +};
--- a/accessible/src/base/AccEvent.cpp +++ b/accessible/src/base/AccEvent.cpp @@ -375,8 +375,29 @@ AccTableChangeEvent:: already_AddRefed<nsAccEvent> AccTableChangeEvent::CreateXPCOMObject() { nsAccEvent* event = new nsAccTableChangeEvent(this); NS_IF_ADDREF(event); return event; } + +//////////////////////////////////////////////////////////////////////////////// +// AccVCChangeEvent +//////////////////////////////////////////////////////////////////////////////// + +AccVCChangeEvent:: + AccVCChangeEvent(nsAccessible* aAccessible, + nsIAccessible* aOldAccessible, + PRInt32 aOldStart, PRInt32 aOldEnd) : + AccEvent(::nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED, aAccessible), + mOldAccessible(aOldAccessible), mOldStart(aOldStart), mOldEnd(aOldEnd) +{ +} + +already_AddRefed<nsAccEvent> +AccVCChangeEvent::CreateXPCOMObject() +{ + nsAccEvent* event = new nsAccVirtualCursorChangeEvent(this); + NS_ADDREF(event); + return event; +}
--- a/accessible/src/base/AccEvent.h +++ b/accessible/src/base/AccEvent.h @@ -124,17 +124,18 @@ public: eGenericEvent, eStateChangeEvent, eTextChangeEvent, eMutationEvent, eHideEvent, eShowEvent, eCaretMoveEvent, eSelectionChangeEvent, - eTableChangeEvent + eTableChangeEvent, + eVirtualCursorChangeEvent }; static const EventGroup kEventGroup = eGenericEvent; virtual unsigned int GetEventGroups() const { return 1U << eGenericEvent; } @@ -394,16 +395,47 @@ public: PRUint32 GetIndex() const { return mRowOrColIndex; } PRUint32 GetCount() const { return mNumRowsOrCols; } private: PRUint32 mRowOrColIndex; // the start row/column after which the rows are inserted/deleted. PRUint32 mNumRowsOrCols; // the number of inserted/deleted rows/columns }; +/** + * Accessible virtual cursor change event. + */ +class AccVCChangeEvent : public AccEvent +{ +public: + AccVCChangeEvent(nsAccessible* aAccessible, + nsIAccessible* aOldAccessible, + PRInt32 aOldStart, PRInt32 aOldEnd); + + virtual ~AccVCChangeEvent() { } + + // AccEvent + virtual already_AddRefed<nsAccEvent> CreateXPCOMObject(); + + static const EventGroup kEventGroup = eVirtualCursorChangeEvent; + virtual unsigned int GetEventGroups() const + { + return AccEvent::GetEventGroups() | (1U << eVirtualCursorChangeEvent); + } + + // AccTableChangeEvent + nsIAccessible* OldAccessible() const { return mOldAccessible; } + PRInt32 OldStartOffset() const { return mOldStart; } + PRInt32 OldEndOffset() const { return mOldEnd; } + +private: + nsRefPtr<nsIAccessible> mOldAccessible; + PRInt32 mOldStart; + PRInt32 mOldEnd; +}; /** * Downcast the generic accessible event object to derived type. */ class downcast_accEvent { public: downcast_accEvent(AccEvent* e) : mRawPtr(e) { }
--- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -70,18 +70,18 @@ CPPSRCS = \ nsBaseWidgetAccessible.cpp \ nsEventShell.cpp \ nsFormControlAccessible.cpp \ nsRootAccessible.cpp \ nsApplicationAccessible.cpp \ nsCaretAccessible.cpp \ nsTextAccessible.cpp \ nsTextEquivUtils.cpp \ - nsTextAttrs.cpp \ StyleInfo.cpp \ + TextAttrs.cpp \ TextUpdater.cpp \ $(NULL) EXPORTS = \ a11yGeneric.h \ nsAccDocManager.h \ nsAccessibilityService.h \ nsAccessible.h \
--- a/accessible/src/base/StyleInfo.cpp +++ b/accessible/src/base/StyleInfo.cpp @@ -126,8 +126,17 @@ StyleInfo::FormatColor(const nscolor& aV void StyleInfo::FormatFontStyle(const nscoord& aValue, nsAString& aFormattedValue) { nsCSSKeyword keyword = 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); +}
--- a/accessible/src/base/StyleInfo.h +++ b/accessible/src/base/StyleInfo.h @@ -57,16 +57,17 @@ public: void TextIndent(nsAString& aValue); void MarginLeft(nsAString& aValue) { Margin(css::eSideLeft, aValue); } void MarginRight(nsAString& aValue) { Margin(css::eSideRight, aValue); } void MarginTop(nsAString& aValue) { Margin(css::eSideTop, aValue); } void MarginBottom(nsAString& aValue) { Margin(css::eSideBottom, aValue); } 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; StyleInfo(const StyleInfo&) MOZ_DELETE; StyleInfo& operator = (const StyleInfo&) MOZ_DELETE; void Margin(css::Side aSide, nsAString& aValue);
rename from accessible/src/base/nsTextAttrs.cpp rename to accessible/src/base/TextAttrs.cpp --- a/accessible/src/base/nsTextAttrs.cpp +++ b/accessible/src/base/TextAttrs.cpp @@ -31,17 +31,17 @@ * 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 "nsTextAttrs.h" +#include "TextAttrs.h" #include "nsAccUtils.h" #include "nsCoreUtils.h" #include "nsHyperTextAccessibleWrap.h" #include "StyleInfo.h" #include "gfxFont.h" #include "gfxUserFontSet.h" @@ -68,52 +68,42 @@ struct nsCSSTextAttrMapItem /** * The map of CSS properties to text attributes. */ const char* const kAnyValue = nsnull; 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 // the case of text attributes. // 3. Offset accessible and result hyper text offsets must not be specified // but include default text attributes flag and attributes list must be // specified in the case of default text attributes. NS_PRECONDITION(mHyperTextAcc && ((mOffsetAcc && mOffsetAccIdx != -1 && aStartHTOffset && aEndHTOffset) || (!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)) { for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) { nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx); if (!nsAccUtils::IsEmbeddedObject(currAcc)) break; @@ -125,120 +115,107 @@ nsTextAttrsMgr::GetAttributes(nsIPersist childIdx++) { nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx); if (!nsAccUtils::IsEmbeddedObject(currAcc)) break; (*aEndHTOffset)++; } - return NS_OK; + return; } // Get the content and frame of the accessible. In the case of document // accessible it's role content and root frame. nsIContent *hyperTextElm = mHyperTextAcc->GetContent(); 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; if (mOffsetAcc) { offsetNode = mOffsetAcc->GetContent(); offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode); frame = offsetElm->GetPrimaryFrame(); } - nsTArray<nsITextAttr*> textAttrArray(10); + nsTArray<TextAttr*> 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 ColorTextAttr colorTextAttr(rootFrame, frame); textAttrArray.AppendElement(&colorTextAttr); // "font-family" text attribute FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame); textAttrArray.AppendElement(&fontFamilyTextAttr); // "font-size" text attribute - nsFontSizeTextAttr fontSizeTextAttr(rootFrame, frame); + FontSizeTextAttr fontSizeTextAttr(rootFrame, frame); textAttrArray.AppendElement(&fontSizeTextAttr); // "font-style" text attribute FontStyleTextAttr fontStyleTextAttr(rootFrame, frame); 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<nsITextAttr*>& aTextAttrArray, - PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset) +void +TextAttrsMgr::GetRange(const nsTArray<TextAttr*>& aTextAttrArray, + PRInt32* aStartHTOffset, PRInt32* aEndHTOffset) { PRUint32 attrLen = aTextAttrArray.Length(); // Navigate backward from anchor accessible to find start offset. for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) { nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx); // Stop on embedded accessible since embedded accessibles are combined into // own range. 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; } } if (offsetFound) break; @@ -248,99 +225,99 @@ nsTextAttrsMgr::GetRange(const nsTArray< // Navigate forward from anchor accessible to find end offset. PRInt32 childLen = mHyperTextAcc->GetChildCount(); for (PRInt32 childIdx = mOffsetAccIdx + 1; childIdx < childLen; childIdx++) { nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx); 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. if (!textAttr->Equal(currElm)) { offsetFound = true; break; } } if (offsetFound) break; (*aEndHTOffset) += nsAccUtils::TextLength(currAcc); } +} - return NS_OK; -} //////////////////////////////////////////////////////////////////////////////// -// nsLangTextAttr +// LangTextAttr +//////////////////////////////////////////////////////////////////////////////// -nsLangTextAttr::nsLangTextAttr(nsHyperTextAccessible *aRootAcc, - nsIContent *aRootContent, nsIContent *aContent) : - nsTextAttr<nsAutoString>(aContent == nsnull), mRootContent(aRootContent) +TextAttrsMgr::LangTextAttr:: + LangTextAttr(nsHyperTextAccessible* aRoot, + nsIContent* aRootElm, nsIContent* aElm) : + TTextAttr<nsString>(!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<nsAutoString>(aContent == nsnull), mIndex(aIndex) +TextAttrsMgr::CSSTextAttr:: + CSSTextAttr(PRUint32 aIndex, nsIContent* aRootElm, nsIContent* aElm) : + TTextAttr<nsString>(!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<nsIDOMCSSStyleDeclaration> currStyleDecl = - nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aContent); + nsCoreUtils::GetComputedStyleDeclaration(EmptyString(), aElm); if (!currStyleDecl) return false; NS_ConvertASCIItoUTF16 cssName(gCSSTextAttrsMap[mIndex].mCSSName); nsresult rv = currStyleDecl->GetPropertyValue(cssName, *aValue); if (NS_FAILED(rv)) return true; @@ -348,60 +325,69 @@ nsCSSTextAttr::GetValueFor(nsIContent *a const char *cssValue = gCSSTextAttrsMap[mIndex].mCSSValue; if (cssValue != kAnyValue && !aValue->EqualsASCII(cssValue)) return false; return true; } 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<nscolor>(aFrame == nsnull), mRootFrame(aRootFrame) +TextAttrsMgr::BGColorTextAttr:: + BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr<nscolor>(!aFrame), mRootFrame(aRootFrame) { mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue); if (aFrame) mIsDefined = GetColor(aFrame, &mNativeValue); } 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; return true; } nsIFrame *parentFrame = aFrame->GetParent(); if (!parentFrame) { @@ -418,124 +404,131 @@ nsBGColorTextAttr::GetColor(nsIFrame *aF return GetColor(parentFrame, aColor); } //////////////////////////////////////////////////////////////////////////////// // ColorTextAttr //////////////////////////////////////////////////////////////////////////////// -ColorTextAttr::ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : - nsTextAttr<nscolor>(!aFrame) +TextAttrsMgr::ColorTextAttr:: + ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr<nscolor>(!aFrame) { mRootNativeValue = aRootFrame->GetStyleColor()->mColor; mIsRootDefined = true; if (aFrame) { mNativeValue = aFrame->GetStyleColor()->mColor; mIsDefined = true; } } 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; } return false; } 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); } //////////////////////////////////////////////////////////////////////////////// // FontFamilyTextAttr //////////////////////////////////////////////////////////////////////////////// -FontFamilyTextAttr::FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : - nsTextAttr<nsAutoString>(aFrame == nsnull) +TextAttrsMgr::FontFamilyTextAttr:: + FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr<nsString>(!aFrame) { mIsRootDefined = GetFontFamily(aRootFrame, mRootNativeValue); if (aFrame) mIsDefined = GetFontFamily(aFrame, mNativeValue); } 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<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm)); gfxFontGroup* fontGroup = fm->GetThebesFontGroup(); gfxFont* font = fontGroup->GetFontAt(0); gfxFontEntry* fontEntry = font->GetFontEntry(); aFamily = fontEntry->FamilyName(); return true; } //////////////////////////////////////////////////////////////////////////////// -// nsFontSizeTextAttr +// FontSizeTextAttr //////////////////////////////////////////////////////////////////////////////// -nsFontSizeTextAttr::nsFontSizeTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) : - nsTextAttr<nscoord>(aFrame == nsnull) +TextAttrsMgr::FontSizeTextAttr:: + FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr<nscoord>(!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. // // Note: according to IA2, "The conversion doesn't have to be exact. // The intent is to give the user a feel for the size of the text." // // ATK does not specify a unit and will likely follow IA2 here. // @@ -543,99 +536,105 @@ nsFontSizeTextAttr::Format(const nscoord float px = NSAppUnitsToFloatPixels(aValue, nsDeviceContext::AppUnitsPerCSSPixel()); // Each pt is 4/3 of a CSS pixel. int pts = NS_lround(px*3/4); 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); } //////////////////////////////////////////////////////////////////////////////// // FontStyleTextAttr //////////////////////////////////////////////////////////////////////////////// -FontStyleTextAttr::FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : - nsTextAttr<nscoord>(!aFrame) +TextAttrsMgr::FontStyleTextAttr:: + FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr<nscoord>(!aFrame) { mRootNativeValue = aRootFrame->GetStyleFont()->mFont.style; mIsRootDefined = true; if (aFrame) { mNativeValue = aFrame->GetStyleFont()->mFont.style; mIsDefined = true; } } bool -FontStyleTextAttr::GetValueFor(nsIContent* aContent, nscoord* aValue) +TextAttrsMgr::FontStyleTextAttr:: + GetValueFor(nsIContent* aContent, nscoord* aValue) { nsIFrame* frame = aContent->GetPrimaryFrame(); if (frame) { *aValue = frame->GetStyleFont()->mFont.style; return true; } return false; } 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<PRInt32>(aFrame == nsnull) +TextAttrsMgr::FontWeightTextAttr:: + FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) : + TTextAttr<PRInt32>(!aFrame) { mRootNativeValue = GetFontWeight(aRootFrame); mIsRootDefined = true; if (aFrame) { mNativeValue = GetFontWeight(aFrame); mIsDefined = true; } } 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). nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm)); gfxFontGroup *fontGroup = fm->GetThebesFontGroup(); gfxFont *font = fontGroup->GetFontAt(0); @@ -659,8 +658,87 @@ nsFontWeightTextAttr::GetFontWeight(nsIF // may not be the weight of the font face used to render the characters. // On Mac, font->GetStyle()->weight will just give the same number as // getComputedStyle(). fontEntry->Weight() will give the weight of the font // face used. gfxFontEntry *fontEntry = font->GetFontEntry(); 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<TextDecorValue>(!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); + } +}
rename from accessible/src/base/nsTextAttrs.h rename to accessible/src/base/TextAttrs.h --- a/accessible/src/base/nsTextAttrs.h +++ b/accessible/src/base/TextAttrs.h @@ -34,393 +34,410 @@ * 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" +#include "nsStyleConsts.h" -class nsITextAttr; +class nsHyperTextAccessible; + +namespace mozilla { +namespace a11y { /** * 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. + * nsHyperTextAccessible class). * - * @note "invalid: spelling" text attrbiute is implemented entirerly in + * @note "invalid: spelling" text attribute is implemented entirely in * nsHyperTextAccessible class. */ -class nsTextAttrsMgr +class TextAttrsMgr { public: /** - * Constructor. If instance of the class is intended to expose default text - * attributes then 'aIncludeDefAttrs' and 'aOffsetNode' argument must be - * skiped. + * 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 hyper text accessible text attributes are - * calculated for - * @param aHyperTextNode DOM node of the given hyper text accessbile + * @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 oOffsetNode [optional] DOM node represents hyper text offset - * inside hyper text accessible + * 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 */ - nsTextAttrsMgr(nsHyperTextAccessible *aHyperTextAcc, - bool aIncludeDefAttrs = true, - nsAccessible *aOffsetAcc = nsnull, - PRInt32 aOffsetAccIdx = -1); + 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 skiped. + * 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 */ - nsresult GetAttributes(nsIPersistentProperties *aAttributes, - PRInt32 *aStartHTOffset = nsnull, - PRInt32 *aEndHTOffset = nsnull); + 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 */ - nsresult GetRange(const nsTArray<nsITextAttr*>& aTextAttrArray, - PRInt32 *aStartHTOffset, PRInt32 *aEndHTOffset); + class TextAttr; + void GetRange(const nsTArray<TextAttr*>& aTextAttrArray, + PRInt32* aStartHTOffset, PRInt32* aEndHTOffset); private: - nsRefPtr<nsHyperTextAccessible> mHyperTextAcc; + nsHyperTextAccessible* mHyperTextAcc; bool mIncludeDefAttrs; - nsRefPtr<nsAccessible> mOffsetAcc; + nsAccessible* 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 T> -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<nsAutoString> -{ -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<nsIContent> mRootContent; -}; - + /** + * 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; -/** - * Class is used for the work with CSS based text attributes in nsTextAttrsMgr - * class. - */ -class nsCSSTextAttr : public nsTextAttr<nsAutoString> -{ -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; -}; + /** + * Return true if the text attribute value on the given element equals with + * predefined attribute value. + */ + virtual bool Equal(nsIContent* aElm) = 0; + }; -/** - * Class is used for the work with 'background-color' text attribute in - * nsTextAttrsMgr class. - */ -class nsBGColorTextAttr : public nsTextAttr<nscolor> -{ -public: - nsBGColorTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame); + /** + * Base class to work with text attributes. See derived classes below. + */ + template<class T> + 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); - // nsITextAttr - virtual nsIAtom *GetName() const { return nsGkAtoms::backgroundColor; } + 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; -protected: - // nsTextAttr - virtual bool GetValueFor(nsIContent *aContent, nscolor *aValue); - virtual void Format(const nscolor& aValue, nsAString& aFormattedValue); + // 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; -private: - bool GetColor(nsIFrame *aFrame, nscolor *aColor); - nsIFrame *mRootFrame; -}; + // 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 'color' text attribute in nsTextAttrsMgr - * class. - */ -class ColorTextAttr : public nsTextAttr<nscolor> -{ -public: - ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + /** + * Class is used for the work with 'language' text attribute. + */ + class LangTextAttr : public TTextAttr<nsString> + { + 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); - // nsITextAttr - virtual nsIAtom* GetName() const { return nsGkAtoms::color; } + private: + bool GetLang(nsIContent* aElm, nsAString& aLang); + nsCOMPtr<nsIContent> mRootContent; + }; + -protected: - // nsTextAttr - virtual bool GetValueFor(nsIContent* aContent, nscolor* aValue); - virtual void Format(const nscolor& aValue, nsAString& aFormattedValue); -}; + /** + * Class is used for the work with CSS based text attributes. + */ + class CSSTextAttr : public TTextAttr<nsString> + { + 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 "font-family" text attribute in - * nsTextAttrsMgr class. - */ -class FontFamilyTextAttr : public nsTextAttr<nsAutoString> -{ -public: - FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + /** + * Class is used for the work with 'background-color' text attribute. + */ + class BGColorTextAttr : public TTextAttr<nscolor> + { + 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); - // nsITextAttr - virtual nsIAtom* GetName() const { return nsGkAtoms::font_family; } + private: + bool GetColor(nsIFrame* aFrame, nscolor* aColor); + nsIFrame* mRootFrame; + }; -protected: - // nsTextAttr - virtual bool GetValueFor(nsIContent* aContent, nsAutoString* aValue); - virtual void Format(const nsAutoString& aValue, nsAString& aFormattedValue); + /** + * Class is used for the work with 'color' text attribute. + */ + class ColorTextAttr : public TTextAttr<nscolor> + { + public: + ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~ColorTextAttr() { } -private: + protected: - bool GetFontFamily(nsIFrame* aFrame, nsAutoString& aFamily); -}; + // TTextAttr + virtual bool GetValueFor(nsIContent* aElm, nscolor* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nscolor& aValue); + }; -/** - * Class is used for the work with "font-size" text attribute in nsTextAttrsMgr - * class. - */ -class nsFontSizeTextAttr : public nsTextAttr<nscoord> -{ -public: - nsFontSizeTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame); + /** + * Class is used for the work with "font-family" text attribute. + */ + class FontFamilyTextAttr : public TTextAttr<nsString> + { + 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); + }; - // nsITextAttr - virtual nsIAtom *GetName() const { return nsGkAtoms::font_size; } -protected: + /** + * Class is used for the work with "font-size" text attribute. + */ + class FontSizeTextAttr : public TTextAttr<nscoord> + { + public: + FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~FontSizeTextAttr() { } - // nsTextAttr - virtual bool GetValueFor(nsIContent *aContent, nscoord *aValue); - virtual void Format(const nscoord& aValue, nsAString& aFormattedValue); + protected: -private: + // TTextAttr + virtual bool GetValueFor(nsIContent* aElm, nscoord* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const nscoord& aValue); + + private: + nsDeviceContext* mDC; + }; + /** - * Return font size for the given frame. - * - * @param aFrame [in] the given frame to query font-size - * @return font size + * Class is used for the work with "font-style" text attribute. */ - nscoord GetFontSize(nsIFrame *aFrame); + class FontStyleTextAttr : public TTextAttr<nscoord> + { + public: + FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~FontStyleTextAttr() { } - nsDeviceContext *mDC; -}; + 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-style" text attribute in nsTextAttrsMgr - * class. - */ -class FontStyleTextAttr : public nsTextAttr<nscoord> -{ -public: - FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + /** + * Class is used for the work with "font-weight" text attribute. + */ + class FontWeightTextAttr : public TTextAttr<PRInt32> + { + public: + FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame); + virtual ~FontWeightTextAttr() { } - // nsITextAttr - virtual nsIAtom* GetName() const { return nsGkAtoms::font_style; } - -protected: + protected: - // nsTextAttr - virtual bool GetValueFor(nsIContent* aContent, nscoord* aValue); - virtual void Format(const nscoord &aValue, nsAString &aFormattedValue); -}; + // TTextAttr + virtual bool GetValueFor(nsIContent* aElm, PRInt32* aValue); + virtual void ExposeValue(nsIPersistentProperties* aAttributes, + const PRInt32& aValue); + + private: + PRInt32 GetFontWeight(nsIFrame* aFrame); + }; -/** - * Class is used for the work with "font-weight" text attribute in - * nsTextAttrsMgr class. - */ -class nsFontWeightTextAttr : public nsTextAttr<PRInt32> -{ -public: - nsFontWeightTextAttr(nsIFrame *aRootFrame, 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. + */ - // nsITextAttr - virtual nsIAtom *GetName() const { return nsGkAtoms::fontWeight; } + class TextDecorValue + { + public: + TextDecorValue() { } + TextDecorValue(nsIFrame* aFrame); -protected: + 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; } - // nsTextAttr - virtual bool GetValueFor(nsIContent *aElm, PRInt32 *aValue); - virtual void Format(const PRInt32& aValue, nsAString& aFormattedValue); + bool operator ==(const TextDecorValue& aValue) + { + return mColor == aValue.mColor && mLine == aValue.mLine && + mStyle == aValue.mStyle; + } + bool operator !=(const TextDecorValue& aValue) + { return !(*this == aValue); } -private: + private: + nscolor mColor; + PRUint8 mLine; + PRUint8 mStyle; + }; - /** - * Return font weight for the given frame. - * - * @param aFrame [in] the given frame to query font weight - * @return font weight - */ - PRInt32 GetFontWeight(nsIFrame *aFrame); -}; + class TextDecorTextAttr : public TTextAttr<TextDecorValue> + { + 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
--- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -1445,16 +1445,33 @@ nsAccessible::GetAttributesInternal(nsIP break; startContent = parentDoc->FindContentForSubDocument(doc); } if (!mContent->IsElement()) return NS_OK; + // Expose draggable object attribute? + nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mContent); + if (htmlElement) { + bool draggable = false; + htmlElement->GetDraggable(&draggable); + if (draggable) { + nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::draggable, + NS_LITERAL_STRING("true")); + } + } + + // Don't calculate CSS-based object attributes when no frame (i.e. + // the accessible is not unattached form three) or when the accessible is not + // primary for node (like list bullet or XUL tree items). + if (!mContent->GetPrimaryFrame() || !IsPrimaryForNode()) + return NS_OK; + // CSS style based object attributes. nsAutoString value; StyleInfo styleInfo(mContent->AsElement(), mDoc->PresShell()); // Expose 'display' attribute. styleInfo.Display(value); nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::display, value); @@ -1477,27 +1494,16 @@ nsAccessible::GetAttributesInternal(nsIP // Expose 'margin-top' attribute. styleInfo.MarginTop(value); nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginTop, value); // Expose 'margin-bottom' attribute. styleInfo.MarginBottom(value); nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginBottom, value); - // Expose draggable object attribute? - nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mContent); - if (htmlElement) { - bool draggable = false; - htmlElement->GetDraggable(&draggable); - if (draggable) { - nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::draggable, - NS_LITERAL_STRING("true")); - } - } - return NS_OK; } NS_IMETHODIMP nsAccessible::GroupPosition(PRInt32 *aGroupLevel, PRInt32 *aSimilarItemsInGroup, PRInt32 *aPositionInGroup) {
--- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -918,17 +918,18 @@ NS_IMETHODIMP nsDocAccessible::Observe(n //////////////////////////////////////////////////////////////////////////////// // nsIAccessiblePivotObserver NS_IMETHODIMP nsDocAccessible::OnPivotChanged(nsIAccessiblePivot* aPivot, nsIAccessible* aOldAccessible, PRInt32 aOldStart, PRInt32 aOldEnd) { - nsRefPtr<AccEvent> event = new AccEvent(nsIAccessibleEvent::EVENT_VIRTUALCURSOR_CHANGED, this); + nsRefPtr<AccEvent> event = new AccVCChangeEvent(this, aOldAccessible, + aOldStart, aOldEnd); nsEventShell::FireEvent(event); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsIDocumentObserver
--- a/accessible/src/html/nsHyperTextAccessible.cpp +++ b/accessible/src/html/nsHyperTextAccessible.cpp @@ -37,19 +37,19 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsHyperTextAccessible.h" #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" #include "nsFocusManager.h" #include "nsIDOMCharacterData.h" #include "nsIDOMDocument.h" #include "nsIDOMRange.h" #include "nsIDOMXULDocument.h" @@ -1125,34 +1125,32 @@ nsHyperTextAccessible::GetTextAttributes } nsAccessible* accAtOffset = GetChildAtOffset(aOffset); if (!accAtOffset) { // Offset 0 is correct offset when accessible has empty text. Include // 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; } return NS_ERROR_INVALID_ARG; } PRInt32 accAtOffsetIdx = accAtOffset->IndexInParent(); PRInt32 startOffset = GetChildOffset(accAtOffsetIdx); 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(); if (offsetFrame && offsetFrame->GetType() == nsGkAtoms::textFrame) { PRInt32 nodeOffset = 0; nsresult rv = RenderedToContentOffset(offsetFrame, offsetInAcc, &nodeOffset); NS_ENSURE_SUCCESS(rv, rv); @@ -1181,18 +1179,19 @@ nsHyperTextAccessible::GetDefaultTextAtt return NS_ERROR_FAILURE; nsCOMPtr<nsIPersistentProperties> attributes = do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID); NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*aAttributes = attributes); - nsTextAttrsMgr textAttrsMgr(this, true); - return textAttrsMgr.GetAttributes(*aAttributes); + TextAttrsMgr textAttrsMgr(this); + textAttrsMgr.GetAttributes(*aAttributes); + return NS_OK; } PRInt32 nsHyperTextAccessible::GetLevelInternal() { nsIAtom *tag = mContent->Tag(); if (tag == nsGkAtoms::h1) return 1;
--- a/accessible/src/xpcom/nsAccEvent.cpp +++ b/accessible/src/xpcom/nsAccEvent.cpp @@ -248,8 +248,45 @@ NS_IMETHODIMP nsAccTableChangeEvent::GetNumRowsOrCols(PRInt32* aNumRowsOrCols) { NS_ENSURE_ARG_POINTER(aNumRowsOrCols); *aNumRowsOrCols = static_cast<AccTableChangeEvent*>(mEvent.get())->GetCount(); return NS_OK; } +//////////////////////////////////////////////////////////////////////////////// +// nsAccVirtualCursorChangeEvent +//////////////////////////////////////////////////////////////////////////////// + +NS_IMPL_ISUPPORTS_INHERITED1(nsAccVirtualCursorChangeEvent, nsAccEvent, + nsIAccessibleVirtualCursorChangeEvent) + +NS_IMETHODIMP +nsAccVirtualCursorChangeEvent::GetOldAccessible(nsIAccessible** aOldAccessible) +{ + NS_ENSURE_ARG_POINTER(aOldAccessible); + + *aOldAccessible = + static_cast<AccVCChangeEvent*>(mEvent.get())->OldAccessible(); + NS_IF_ADDREF(*aOldAccessible); + return NS_OK; +} + +NS_IMETHODIMP +nsAccVirtualCursorChangeEvent::GetOldStartOffset(PRInt32* aOldStartOffset) +{ + NS_ENSURE_ARG_POINTER(aOldStartOffset); + + *aOldStartOffset = + static_cast<AccVCChangeEvent*>(mEvent.get())->OldStartOffset(); + return NS_OK; +} + +NS_IMETHODIMP +nsAccVirtualCursorChangeEvent::GetOldEndOffset(PRInt32* aOldEndOffset) +{ + NS_ENSURE_ARG_POINTER(aOldEndOffset); + + *aOldEndOffset = + static_cast<AccVCChangeEvent*>(mEvent.get())->OldEndOffset(); + return NS_OK; +}
--- a/accessible/src/xpcom/nsAccEvent.h +++ b/accessible/src/xpcom/nsAccEvent.h @@ -159,10 +159,30 @@ public: NS_DECL_NSIACCESSIBLETABLECHANGEEVENT private: nsAccTableChangeEvent(); nsAccTableChangeEvent(const nsAccTableChangeEvent&); nsAccTableChangeEvent& operator =(const nsAccTableChangeEvent&); }; +/** + * Accessible virtual cursor change event. + */ +class nsAccVirtualCursorChangeEvent : public nsAccEvent, + public nsIAccessibleVirtualCursorChangeEvent +{ +public: + nsAccVirtualCursorChangeEvent(AccVCChangeEvent* aEvent) : + nsAccEvent(aEvent) { } + virtual ~nsAccVirtualCursorChangeEvent() { } + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIACCESSIBLEVIRTUALCURSORCHANGEEVENT + +private: + nsAccVirtualCursorChangeEvent() MOZ_DELETE; + nsAccVirtualCursorChangeEvent(const nsAccVirtualCursorChangeEvent&) MOZ_DELETE; + nsAccVirtualCursorChangeEvent& operator =(const nsAccVirtualCursorChangeEvent&) MOZ_DELETE; +}; + #endif
--- a/accessible/tests/mochitest/attributes.js +++ b/accessible/tests/mochitest/attributes.js @@ -43,16 +43,33 @@ function testCSSAttrs(aID) "margin-right": computedStyle.marginRight, "margin-top": computedStyle.marginTop, "margin-bottom": computedStyle.marginBottom }; testAttrs(aID, attrs, true); } /** + * Test the accessible that it doesn't have CSS-based object attributes. + */ +function testAbsentCSSAttrs(aID) +{ + var attrs = { + "display": "", + "text-align": "", + "text-indent": "", + "margin-left": "", + "margin-right": "", + "margin-top": "", + "margin-bottom": "" + }; + testAbsentAttrs(aID, attrs); +} + +/** * Test group object attributes (posinset, setsize and level) and * nsIAccessible::groupPosition() method. * * @param aAccOrElmOrID [in] the ID, DOM node or accessible * @param aPosInSet [in] the value of 'posinset' attribute * @param aSetSize [in] the value of 'setsize' attribute * @param aLevel [in, optional] the value of 'level' attribute */
--- a/accessible/tests/mochitest/attributes/test_obj_css.html +++ b/accessible/tests/mochitest/attributes/test_obj_css.html @@ -77,16 +77,19 @@ https://bugzilla.mozilla.org/show_bug.cg testCSSAttrs("span"); testCSSAttrs("div"); testCSSAttrs("p"); testCSSAttrs("input"); testCSSAttrs("table"); testCSSAttrs("tr"); testCSSAttrs("td"); + // no CSS-based object attributes + testAbsentCSSAttrs(getAccessible("listitem").firstChild); + SimpleTest.finish(); } SimpleTest.waitForExplicitFinish(); addA11yLoadEvent(doTest); </script> </head> <body> @@ -106,16 +109,21 @@ https://bugzilla.mozilla.org/show_bug.cg title="Expose IA2 margin- object attributes"> Mozilla Bug 689540 </a> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=714579" title="Don't use GetComputedStyle for object attribute calculation"> Mozilla Bug 714579 </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=729831" + title="Don't expose CSS-based object attributes on not in tree accessible and accessible having no DOM element"> + Mozilla Bug 729831 + </a> <p id="display"></p> <div id="content" style="display: none"></div> <pre id="test"> </pre> <div id="display_block" role="img" style="display: block;">display: block</div> @@ -184,10 +192,14 @@ https://bugzilla.mozilla.org/show_bug.cg <div id="div">It's div</div> <p id="p">It's paragraph"</p> <input id="input"/> <table id="table" style="margin: 2px; text-align: center; text-indent: 10%;"> <tr id="tr" role="group"> <td id="td">td</td> </tr> </table> + + <ul> + <li id="listitem">item + </ul> </body> </html>
--- a/accessible/tests/mochitest/attributes/test_text.html +++ b/accessible/tests/mochitest/attributes/test_text.html @@ -264,23 +264,29 @@ tempElem = tempElem.nextSibling.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = { "font-family": kMonospaceFontFamily }; testTextAttrs(ID, 70, attrs, defAttrs, 69, 83); 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 = {}; testTextAttrs(ID, 123, attrs, defAttrs, 122, 130); ////////////////////////////////////////////////////////////////////////// // area10, different single style spans in non-styled paragraph ID = "area10"; @@ -318,23 +324,29 @@ tempElem = tempElem.nextSibling.nextSibling; gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); attrs = { "font-family": kMonospaceFontFamily }; testTextAttrs(ID, 71, attrs, defAttrs, 70, 84); 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 = {}; testTextAttrs(ID, 124, attrs, defAttrs, 123, 131); ////////////////////////////////////////////////////////////////////////// // area11, "font-weight" tests ID = "area11"; @@ -432,35 +444,82 @@ testTextAttrs(ID, 22, attrs, defAttrs, 22, 27); attrs = { "font-family": kCursiveFontFamily }; testTextAttrs(ID, 27, attrs, defAttrs, 27, 31); 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(); } SimpleTest.waitForExplicitFinish(); addA11yLoadEvent(doTest); </script> </head> <body style="font-size: 12pt"> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345759" title="Implement text attributes"> Mozilla Bug 345759 - </a><br> + </a> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=473576" title="font-family text attribute should expose actual font used"> Mozilla Bug 473576 </a> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=523304" + title="expose text-underline-color and text-line-through-color text attributes"> + Mozilla Bug 523304 + </a> <p id="display"></p> <div id="content" style="display: none"></div> <pre id="test"> </pre> <p id="area1" style="font-size: smaller">Normal <b>Bold</b> Normal</p> <p id="area2" style="font-size: 120%">Normal <b>Bold <i>Italic </i>Bold</b> Normal</p> <p id="area3" style="background-color: blue;"> @@ -541,10 +600,20 @@ <p id="area16" style="font-family: sans-serif;"> <span style="font-family: monospace;">text</span>text <span style="font-family: serif;">text</span>text <span style="font-family: BodoniThatDoesntExist;">text</span>text <span style="font-family: Comic Sans MS, cursive;">text</span>text <span style="font-family: sans-serif, fantasy;">text</span>text </p> + + <p id="area17"> + <span style="-moz-text-decoration-line: underline;">underline + </span><span style="text-decoration: underline; -moz-text-decoration-color: blue;">blue + </span><span style="text-decoration: underline; -moz-text-decoration-style: dotted;">dotted + </span><span style="-moz-text-decoration-line: line-through;">linethrough + </span><span style="text-decoration: line-through; -moz-text-decoration-color: blue;">blue + </span><span style="text-decoration: line-through; -moz-text-decoration-style: wavy;">wavy + </span> + </p> </body> </html>
--- a/accessible/tests/mochitest/common.js +++ b/accessible/tests/mochitest/common.js @@ -5,16 +5,18 @@ const nsIAccessibleRetrieval = Component const nsIAccessibleEvent = Components.interfaces.nsIAccessibleEvent; const nsIAccessibleStateChangeEvent = Components.interfaces.nsIAccessibleStateChangeEvent; const nsIAccessibleCaretMoveEvent = Components.interfaces.nsIAccessibleCaretMoveEvent; const nsIAccessibleTextChangeEvent = Components.interfaces.nsIAccessibleTextChangeEvent; +const nsIAccessibleVirtualCursorChangeEvent = + Components.interfaces.nsIAccessibleVirtualCursorChangeEvent; const nsIAccessibleStates = Components.interfaces.nsIAccessibleStates; const nsIAccessibleRole = Components.interfaces.nsIAccessibleRole; const nsIAccessibleScrollType = Components.interfaces.nsIAccessibleScrollType; const nsIAccessibleCoordinateType = Components.interfaces.nsIAccessibleCoordinateType; const nsIAccessibleRelation = Components.interfaces.nsIAccessibleRelation;
--- a/accessible/tests/mochitest/pivot.js +++ b/accessible/tests/mochitest/pivot.js @@ -69,47 +69,87 @@ var ObjectTraversalRule = * A checker for virtual cursor changed events. */ function virtualCursorChangedChecker(aDocAcc, aIdOrNameOrAcc, aTextOffsets) { this.__proto__ = new invokerChecker(EVENT_VIRTUALCURSOR_CHANGED, aDocAcc); this.check = function virtualCursorChangedChecker_check(aEvent) { + SimpleTest.info("virtualCursorChangedChecker_check"); + + var event = null; + try { + event = aEvent.QueryInterface(nsIAccessibleVirtualCursorChangeEvent); + } catch (e) { + SimpleTest.ok(false, "Does not support correct interface: " + e); + } + var position = aDocAcc.virtualCursor.position; var idMatches = position.DOMNode.id == aIdOrNameOrAcc; var nameMatches = position.name == aIdOrNameOrAcc; var accMatches = position == aIdOrNameOrAcc; SimpleTest.ok(idMatches || nameMatches || accMatches, "id or name matches", "expecting " + aIdOrNameOrAcc + ", got '" + prettyName(position)); if (aTextOffsets) { SimpleTest.is(aDocAcc.virtualCursor.startOffset, aTextOffsets[0], "wrong start offset"); SimpleTest.is(aDocAcc.virtualCursor.endOffset, aTextOffsets[1], "wrong end offset"); } + + var prevPosAndOffset = virtualCursorChangedChecker. + getPreviousPosAndOffset(aDocAcc.virtualCursor); + + if (prevPosAndOffset) { + SimpleTest.is(event.oldAccessible, prevPosAndOffset.position, + "previous position does not match"); + SimpleTest.is(event.oldStartOffset, prevPosAndOffset.startOffset, + "previous start offset does not match"); + SimpleTest.is(event.oldEndOffset, prevPosAndOffset.endOffset, + "previous end offset does not match"); + } }; } +virtualCursorChangedChecker.prevPosAndOffset = {}; + +virtualCursorChangedChecker.storePreviousPosAndOffset = + function storePreviousPosAndOffset(aPivot) +{ + virtualCursorChangedChecker.prevPosAndOffset[aPivot] = + {position: aPivot.position, + startOffset: aPivot.startOffset, + endOffset: aPivot.endOffset}; +}; + +virtualCursorChangedChecker.getPreviousPosAndOffset = + function getPreviousPosAndOffset(aPivot) +{ + return virtualCursorChangedChecker.prevPosAndOffset[aPivot]; +}; + /** * Set a text range in the pivot and wait for virtual cursor change event. * * @param aDocAcc document that manages the virtual cursor * @param aTextAccessible accessible to set to virtual cursor's position * @param aTextOffsets start and end offsets of text range to set in virtual * cursor */ function setVirtualCursorRangeInvoker(aDocAcc, aTextAccessible, aTextOffsets) { this.invoke = function virtualCursorChangedInvoker_invoke() { + virtualCursorChangedChecker. + storePreviousPosAndOffset(aDocAcc.virtualCursor); SimpleTest.info(prettyName(aTextAccessible) + " " + aTextOffsets); aDocAcc.virtualCursor.setTextRange(aTextAccessible, aTextOffsets[0], aTextOffsets[1]); }; this.getID = function setVirtualCursorRangeInvoker_getID() { @@ -131,16 +171,18 @@ function setVirtualCursorRangeInvoker(aD * @param aIdOrNameOrAcc id, accessivle or accessible name to expect virtual * cursor to land on after performing move method. */ function setVirtualCursorPosInvoker(aDocAcc, aPivotMoveMethod, aRule, aIdOrNameOrAcc) { this.invoke = function virtualCursorChangedInvoker_invoke() { + virtualCursorChangedChecker. + storePreviousPosAndOffset(aDocAcc.virtualCursor); var moved = aDocAcc.virtualCursor[aPivotMoveMethod](aRule); SimpleTest.ok((aIdOrNameOrAcc && moved) || (!aIdOrNameOrAcc && !moved), "moved pivot"); }; this.getID = function setVirtualCursorPosInvoker_getID() { return "Do " + (aIdOrNameOrAcc ? "" : "no-op ") + aPivotMoveMethod;
--- a/browser/app/blocklist.xml +++ b/browser/app/blocklist.xml @@ -1,10 +1,10 @@ <?xml version="1.0"?> -<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1330367012000"> +<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1331241604000"> <emItems> <emItem blockID="i58" id="webmaster@buzzzzvideos.info"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i41" id="{99079a25-328f-4bd4-be04-00955acaa0a7}"> <versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1"> </versionRange> @@ -14,28 +14,16 @@ </versionRange> </emItem> <emItem blockID="i8" id="{B13721C7-F507-4982-B2E5-502A71474FED}"> <versionRange minVersion=" " severity="1"> </versionRange> </emItem> <emItem blockID="i43" id="supportaccessplugin@gmail.com"> </emItem> - <emItem blockID="i38" id="{B7082FAA-CB62-4872-9106-E42DD88EDE45}"> - <versionRange minVersion="0.1" maxVersion="3.3.0.*"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.7a1" maxVersion="*" /> - </targetApplication> - </versionRange> - <versionRange minVersion="3.3.1" maxVersion="*"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="5.0a1" maxVersion="*" /> - </targetApplication> - </versionRange> - </emItem> <emItem blockID="i65" id="activity@facebook.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i66" id="youtubeer@youtuber.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> @@ -58,54 +46,32 @@ <emItem blockID="i61" id="youtube@youtube3.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i10" id="{8CE11043-9A15-4207-A565-0C94C42D590D}"> </emItem> - <emItem blockID="i1" id="mozilla_cc@internetdownloadmanager.com"> - <versionRange minVersion="2.1" maxVersion="3.3"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.0a1" maxVersion="*" /> - </targetApplication> - </versionRange> - <versionRange minVersion=" " maxVersion="6.9.8"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.7a1pre" maxVersion="*" /> - </targetApplication> - </versionRange> - </emItem> <emItem blockID="i63" id="youtube@youtuber.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i18" id="msntoolbar@msn.com"> <versionRange minVersion=" " maxVersion="6.*"> </versionRange> </emItem> <emItem blockID="i13" id="{E8E88AB0-7182-11DF-904E-6045E0D72085}"> </emItem> <emItem blockID="i64" id="royal@facebook.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> - <emItem blockID="i4" id="{4B3803EA-5230-4DC3-A7FC-33638F3D3542}"> - <versionRange minVersion="1.2" maxVersion="1.2"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.0a1" maxVersion="*" /> - </targetApplication> - </versionRange> - </emItem> - <emItem blockID="i50" id="firebug@software.joehewitt.com"> - <versionRange minVersion="0" maxVersion="0"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="9.0a1" maxVersion="9.*" /> - </targetApplication> + <emItem blockID="i72" id="{4ED1F68A-5463-4931-9384-8FFF5ED91D92}"> + <versionRange minVersion="0" maxVersion="3.4.1.194" severity="1"> </versionRange> </emItem> <emItem blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}"> <versionRange minVersion="0.1" maxVersion="4.3.1.00" severity="1"> </versionRange> </emItem> <emItem blockID="i53" id="{a3a5c777-f583-4fef-9380-ab4add1bc2a8}"> <versionRange minVersion="2.0.3" maxVersion="2.0.3"> @@ -116,60 +82,36 @@ </versionRange> </emItem> <emItem blockID="i70" id="psid-vhvxQHMZBOzUZA@jetpack"> <versionRange minVersion="0" maxVersion="*" severity="1"> </versionRange> </emItem> <emItem blockID="i7" id="{2224e955-00e9-4613-a844-ce69fccaae91}"> </emItem> - <emItem blockID="i46" id="{841468a1-d7f4-4bd3-84e6-bb0f13a06c64}"> - <versionRange minVersion="0.1" maxVersion="*"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="9.0a1" maxVersion="9.0" /> - </targetApplication> - </versionRange> - </emItem> <emItem blockID="i67" id="youtube2@youtube2.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i60" id="youtb3@youtb3.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> - <emItem blockID="i23" id="firefox@bandoo.com"> - <versionRange minVersion="5.0" maxVersion="5.0" severity="1"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.7a1pre" maxVersion="*" /> - </targetApplication> + <emItem blockID="i56" id="flash@adobe.com"> + <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i55" id="youtube@youtube7.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> - <emItem blockID="i11" id="yslow@yahoo-inc.com"> - <versionRange minVersion="2.0.5" maxVersion="2.0.5"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.5.7" maxVersion="*" /> - </targetApplication> - </versionRange> - </emItem> <emItem blockID="i22" id="ShopperReports@ShopperReports.com"> <versionRange minVersion="3.1.22.0" maxVersion="3.1.22.0"> </versionRange> </emItem> - <emItem blockID="i2" id="fdm_ffext@freedownloadmanager.org"> - <versionRange minVersion="1.0" maxVersion="1.3.1"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.0a1" maxVersion="*" /> - </targetApplication> - </versionRange> - </emItem> <emItem blockID="i44" id="sigma@labs.mozilla"> </emItem> <emItem blockID="i5" id="support@daemon-tools.cc"> <versionRange minVersion=" " maxVersion="1.0.0.5"> </versionRange> </emItem> <emItem blockID="i69" id="{977f3b97-5461-4346-92c8-a14c749b77c9}"> <versionRange minVersion="0" maxVersion="*" severity="1"> @@ -198,102 +140,49 @@ <emItem blockID="i62" id="jid0-EcdqvFOgWLKHNJPuqAnawlykCGZ@jetpack"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i17" id="{3252b9ae-c69a-4eaf-9502-dc9c1f6c009e}"> <versionRange minVersion="2.2" maxVersion="2.2"> </versionRange> </emItem> - <emItem blockID="i56" id="flash@adobe.com"> - <versionRange minVersion="0" maxVersion="*"> - </versionRange> - </emItem> - <emItem blockID="i45" id="{22119944-ED35-4ab1-910B-E619EA06A115}"> - <versionRange minVersion="0.1" maxVersion="7.6.1"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="8.0a1" maxVersion="*" /> - </targetApplication> - </versionRange> - </emItem> <emItem blockID="i19" id="{46551EC9-40F0-4e47-8E18-8E5CF550CFB8}"> <versionRange minVersion="1.1b1" maxVersion="1.1b1"> </versionRange> </emItem> <emItem blockID="i3" id="langpack-vi-VN@firefox.mozilla.org"> <versionRange minVersion="2.0" maxVersion="2.0"> </versionRange> </emItem> <emItem blockID="i51" id="admin@youtubeplayer.com"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> <emItem blockID="i52" id="ff-ext@youtube"> <versionRange minVersion="0" maxVersion="*"> </versionRange> </emItem> - <emItem blockID="i24" id="{6E19037A-12E3-4295-8915-ED48BC341614}"> - <versionRange minVersion="0.1" maxVersion="1.3.328.4" severity="1"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.7a1pre" maxVersion="*" /> - </targetApplication> - </versionRange> - </emItem> - <emItem blockID="i15" id="personas@christopher.beard"> - <versionRange minVersion="1.6" maxVersion="1.6"> - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.6" maxVersion="3.6.*" /> - </targetApplication> - </versionRange> - </emItem> <emItem blockID="i21" id="support@update-firefox.com"> </emItem> </emItems> <pluginItems> - <pluginItem blockID="p26"> - <match name="name" exp="^Yahoo Application State Plugin$" /> <match name="description" exp="^Yahoo Application State Plugin$" /> <match name="filename" exp="npYState.dll" /> <versionRange > - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.0a1" maxVersion="3.*" /> - </targetApplication> - </versionRange> - </pluginItem> - <pluginItem blockID="p27"> - <match name="name" exp="QuickTime Plug-in 7[.]1[.]" /> <match name="filename" exp="npqtplugin.?[.]dll" /> <versionRange > - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.0a1" maxVersion="3.*" /> - </targetApplication> - </versionRange> - </pluginItem> <pluginItem blockID="p28"> <match name="filename" exp="NPFFAddOn.dll" /> <versionRange > </versionRange> </pluginItem> <pluginItem blockID="p31"> <match name="filename" exp="NPMySrch.dll" /> <versionRange > </versionRange> </pluginItem> - <pluginItem blockID="p32"> - <match name="filename" exp="npViewpoint.dll" /> <versionRange > - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.0" maxVersion="*" /> - </targetApplication> - </versionRange> - </pluginItem> <pluginItem blockID="p33"> <match name="name" exp="[0-6]\.0\.[01]\d{2}\.\d+" /> <match name="filename" exp="npdeploytk.dll" /> <versionRange severity="1"> </versionRange> </pluginItem> - <pluginItem blockID="p34"> - <match name="filename" exp="[Nn][Pp][Jj][Pp][Ii]1[56]0_[0-9]+\.[Dd][Ll][Ll]" /> <versionRange > - <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"> - <versionRange minVersion="3.6a1pre" maxVersion="*" /> - </targetApplication> - </versionRange> - </pluginItem> </pluginItems> <gfxItems> <gfxBlacklistEntry blockID="g35"> <os>WINNT 6.1</os> <vendor>0x10de</vendor> <devices> <device>0x0a6c</device>
--- a/browser/base/content/browser-menubar.inc +++ b/browser/base/content/browser-menubar.inc @@ -286,22 +286,22 @@ accesskey="&fullZoomToggleCmd.accesskey;" type="checkbox" command="cmd_fullZoomToggle" checked="false"/> </menupopup> </menu> <menu id="pageStyleMenu" label="&pageStyleMenu.label;" accesskey="&pageStyleMenu.accesskey;" observes="isImage"> - <menupopup onpopupshowing="stylesheetFillPopup(this);" - oncommand="stylesheetSwitchAll(window.content, event.target.getAttribute('data')); setStyleDisabled(false);"> + <menupopup onpopupshowing="gPageStyleMenu.fillPopup(this);" + oncommand="gPageStyleMenu.switchStyleSheet(event.target.getAttribute('data'));"> <menuitem id="menu_pageStyleNoStyle" label="&pageStyleNoStyle.label;" accesskey="&pageStyleNoStyle.accesskey;" - oncommand="setStyleDisabled(true); event.stopPropagation();" + oncommand="gPageStyleMenu.disableStyle(); event.stopPropagation();" type="radio"/> <menuitem id="menu_pageStylePersistentOnly" label="&pageStylePersistentOnly.label;" accesskey="&pageStylePersistentOnly.accesskey;" type="radio" checked="true"/> <menuseparator/> </menupopup>
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -5326,33 +5326,28 @@ function setToolbarVisibility(toolbar, i #ifdef MENUBAR_CAN_AUTOHIDE updateAppButtonDisplay(); #endif } var TabsOnTop = { init: function TabsOnTop_init() { - this._initialized = true; - this.syncUI(); Services.prefs.addObserver(this._prefName, this, false); }, uninit: function TabsOnTop_uninit() { Services.prefs.removeObserver(this._prefName, this); }, toggle: function () { this.enabled = !Services.prefs.getBoolPref(this._prefName); }, syncUI: function () { - if (!this._initialized) - return; - let userEnabled = Services.prefs.getBoolPref(this._prefName); let enabled = userEnabled && gBrowser.tabContainer.visible; document.getElementById("cmd_ToggleTabsOnTop") .setAttribute("checked", userEnabled); document.documentElement.setAttribute("tabsontop", enabled); document.getElementById("navigator-toolbox").setAttribute("tabsontop", enabled); @@ -6092,33 +6087,33 @@ function charsetLoadListener(event) { gPrevCharset = gLastBrowserCharset; gLastBrowserCharset = charset; } } var gPageStyleMenu = { - getAllStyleSheets: function (frameset) { + _getAllStyleSheets: function (frameset) { var styleSheetsArray = Array.slice(frameset.document.styleSheets); for (let i = 0; i < frameset.frames.length; i++) { - let frameSheets = this.getAllStyleSheets(frameset.frames[i]); + let frameSheets = this._getAllStyleSheets(frameset.frames[i]); styleSheetsArray = styleSheetsArray.concat(frameSheets); } return styleSheetsArray; }, - stylesheetFillPopup: function (menuPopup) { + fillPopup: function (menuPopup) { var noStyle = menuPopup.firstChild; var persistentOnly = noStyle.nextSibling; var sep = persistentOnly.nextSibling; while (sep.nextSibling) menuPopup.removeChild(sep.nextSibling); - var styleSheets = this.getAllStyleSheets(window.content); + var styleSheets = this._getAllStyleSheets(window.content); var currentStyleSheets = {}; var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled; var haveAltSheets = false; var altStyleSelected = false; for (let i = 0; i < styleSheets.length; ++i) { let currentStyleSheet = styleSheets[i]; @@ -6156,56 +6151,64 @@ var gPageStyleMenu = { noStyle.setAttribute("checked", styleDisabled); persistentOnly.setAttribute("checked", !altStyleSelected && !styleDisabled); persistentOnly.hidden = (window.content.document.preferredStyleSheetSet) ? haveAltSheets : false; sep.hidden = (noStyle.hidden && persistentOnly.hidden) || !haveAltSheets; return true; }, - stylesheetInFrame: function (frame, title) { + _stylesheetInFrame: function (frame, title) { return Array.some(frame.document.styleSheets, function (stylesheet) stylesheet.title == title); }, - stylesheetSwitchFrame: function (frame, title) { + _stylesheetSwitchFrame: function (frame, title) { var docStyleSheets = frame.document.styleSheets; for (let i = 0; i < docStyleSheets.length; ++i) { let docStyleSheet = docStyleSheets[i]; if (title == "_nostyle") docStyleSheet.disabled = true; else if (docStyleSheet.title) docStyleSheet.disabled = (docStyleSheet.title != title); else if (docStyleSheet.disabled) docStyleSheet.disabled = false; } }, - stylesheetSwitchAll: function (frameset, title) { - if (!title || title == "_nostyle" || this.stylesheetInFrame(frameset, title)) - this.stylesheetSwitchFrame(frameset, title); + _stylesheetSwitchAll: function (frameset, title) { + if (!title || title == "_nostyle" || this._stylesheetInFrame(frameset, title)) + this._stylesheetSwitchFrame(frameset, title); for (let i = 0; i < frameset.frames.length; i++) - this.stylesheetSwitchAll(frameset.frames[i], title); - }, - - setStyleDisabled: function (disabled) { - getMarkupDocumentViewer().authorStyleDisabled = disabled; + this._stylesheetSwitchAll(frameset.frames[i], title); + }, + + switchStyleSheet: function (title, contentWindow) { + getMarkupDocumentViewer().authorStyleDisabled = false; + this._stylesheetSwitchAll(contentWindow || content, title); + }, + + disableStyle: function () { + getMarkupDocumentViewer().authorStyleDisabled = true; }, }; /* Legacy global page-style functions */ -var getAllStyleSheets = gPageStyleMenu.getAllStyleSheets; -var stylesheetFillPopup = gPageStyleMenu.stylesheetFillPopup; -var stylesheetInFrame = gPageStyleMenu.stylesheetInFrame; -var stylesheetSwitchFrame = gPageStyleMenu.stylesheetSwitchFrame; -var stylesheetSwitchAll = gPageStyleMenu.stylesheetSwitchAll; -var setStyleDisabled = gPageStyleMenu.setStyleDisabled; +var getAllStyleSheets = gPageStyleMenu._getAllStyleSheets.bind(gPageStyleMenu); +var stylesheetFillPopup = gPageStyleMenu.fillPopup.bind(gPageStyleMenu); +function stylesheetSwitchAll(contentWindow, title) { + gPageStyleMenu.switchStyleSheet(title, contentWindow); +} +function setStyleDisabled(disabled) { + if (disabled) + gPageStyleMenu.disableStyle(); +} var BrowserOffline = { _inited: false, ///////////////////////////////////////////////////////////////////////////// // BrowserOffline Public Methods init: function ()
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -2774,19 +2774,17 @@ this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle")); tab.setAttribute("crop", "end"); tab.setAttribute("validate", "never"); tab.setAttribute("onerror", "this.removeAttribute('image');"); this.adjustTabstrip(); Services.prefs.addObserver("browser.tabs.", this._prefObserver, false); window.addEventListener("resize", this, false); - - this.updateVisibility(); - this._propagateVisibility(); + window.addEventListener("load", this, false); ]]> </constructor> <destructor> <![CDATA[ Services.prefs.removeObserver("browser.tabs.", this._prefObserver); ]]> </destructor> @@ -2836,25 +2834,29 @@ <field name="_dragOverDelay">350</field> <field name="_dragTime">0</field> <field name="_container" readonly="true"><![CDATA[ this.parentNode && this.parentNode.localName == "toolbar" ? this.parentNode : this; ]]></field> + <field name="_propagatedVisibilityOnce">false</field> + <property name="visible" onget="return !this._container.collapsed;"> <setter><![CDATA[ - if (val == this.visible) + if (val == this.visible && + this._propagatedVisibilityOnce) return val; this._container.collapsed = !val; this._propagateVisibility(); + this._propagatedVisibilityOnce = true; return val; ]]></setter> </property> <method name="_propagateVisibility"> <body><![CDATA[ let visible = this.visible; @@ -3075,16 +3077,19 @@ this.mTabstrip.ensureElementIsVisible(this.selectedItem, false); ]]></body> </method> <method name="handleEvent"> <parameter name="aEvent"/> <body><![CDATA[ switch (aEvent.type) { + case "load": + this.updateVisibility(); + break; case "resize": if (aEvent.target != window) break; var width = this.mTabstrip.boxObject.width; if (width != this.mTabstripWidth) { this.adjustTabstrip(); this._fillTrailingGap(); this._handleTabSelect();
--- a/browser/base/content/test/browser_page_style_menu.js +++ b/browser/base/content/test/browser_page_style_menu.js @@ -9,17 +9,17 @@ function test() { }, true); let rootDir = getRootDirectory(gTestPath); content.location = rootDir + "page_style_sample.html"; } function checkPageStyleMenu() { var menupopup = document.getElementById("pageStyleMenu") .getElementsByTagName("menupopup")[0]; - stylesheetFillPopup(menupopup); + gPageStyleMenu.fillPopup(menupopup); var items = []; var current = menupopup.getElementsByTagName("menuseparator")[0]; while (current.nextSibling) { current = current.nextSibling; items.push(current); }
--- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -59,16 +59,19 @@ XPCOMUtils.defineLazyGetter(this, "NetUt return NetUtil; }); XPCOMUtils.defineLazyGetter(this, "PlacesUtils", function() { Cu.import("resource://gre/modules/PlacesUtils.jsm"); return PlacesUtils; }); +XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter", + "resource:///modules/KeywordURLResetPrompter.jsm"); + const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser"; const PREF_PLUGINS_UPDATEURL = "plugins.update.url"; // We try to backup bookmarks at idle times, to avoid doing that at shutdown. // Number of idle seconds before trying to backup bookmarks. 15 minutes. const BOOKMARKS_BACKUP_IDLE_TIME = 15 * 60; // Minimum interval in milliseconds between backups. const BOOKMARKS_BACKUP_INTERVAL = 86400 * 1000; @@ -272,16 +275,23 @@ BrowserGlue.prototype = { this._distributionCustomizer.applyPrefDefaults(); this._distributionCustomizer.applyCustomizations(); // To apply distribution bookmarks use "places-init-complete". } else if (data == "force-places-init") { this._initPlaces(); } break; + case "defaultURIFixup-using-keyword-pref": + if (KeywordURLResetPrompter.shouldPrompt) { + let keywordURI = subject.QueryInterface(Ci.nsIURI); + KeywordURLResetPrompter.prompt(this.getMostRecentBrowserWindow(), + keywordURI); + } + break; } }, // initialization (called on application startup) _init: function BG__init() { let os = Services.obs; os.addObserver(this, "xpcom-shutdown", false); os.addObserver(this, "prefservice:after-app-defaults", false); @@ -301,16 +311,17 @@ BrowserGlue.prototype = { os.addObserver(this, "session-save", false); os.addObserver(this, "places-init-complete", false); this._isPlacesInitObserver = true; os.addObserver(this, "places-database-locked", false); this._isPlacesLockedObserver = true; os.addObserver(this, "distribution-customization-complete", false); os.addObserver(this, "places-shutdown", false); this._isPlacesShutdownObserver = true; + os.addObserver(this, "defaultURIFixup-using-keyword-pref", false); }, // cleanup (called on application shutdown) _dispose: function BG__dispose() { let os = Services.obs; os.removeObserver(this, "xpcom-shutdown"); os.removeObserver(this, "prefservice:after-app-defaults"); os.removeObserver(this, "final-ui-startup"); @@ -329,16 +340,17 @@ BrowserGlue.prototype = { if (this._isIdleObserver) this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME); if (this._isPlacesInitObserver) os.removeObserver(this, "places-init-complete"); if (this._isPlacesLockedObserver) os.removeObserver(this, "places-database-locked"); if (this._isPlacesShutdownObserver) os.removeObserver(this, "places-shutdown"); + os.removeObserver(this, "defaultURIFixup-using-keyword-pref"); }, _onAppDefaults: function BG__onAppDefaults() { // apply distribution customizations (prefs) // other customizations are applied in _onProfileStartup() this._distributionCustomizer.applyPrefDefaults(); },
--- a/browser/components/sessionstore/test/browser_408470.js +++ b/browser/components/sessionstore/test/browser_408470.js @@ -45,18 +45,18 @@ function test() { let tab = gBrowser.addTab(testUrl); tab.linkedBrowser.addEventListener("load", function(aEvent) { tab.linkedBrowser.removeEventListener("load", arguments.callee, true); // enable all stylesheets and verify that they're correctly persisted Array.forEach(tab.linkedBrowser.contentDocument.styleSheets, function(aSS, aIx) { pendingCount++; let ssTitle = aSS.title; - stylesheetSwitchAll(tab.linkedBrowser.contentWindow, ssTitle); - + gPageStyleMenu.switchStyleSheet(ssTitle, tab.linkedBrowser.contentWindow); + let newTab = gBrowser.duplicateTab(tab); newTab.linkedBrowser.addEventListener("load", function(aEvent) { newTab.linkedBrowser.removeEventListener("load", arguments.callee, true); let states = Array.map(newTab.linkedBrowser.contentDocument.styleSheets, function(aSS) !aSS.disabled); let correct = states.indexOf(true) == aIx && states.indexOf(true, aIx + 1) == -1; if (/^fail_/.test(ssTitle))
--- a/browser/devtools/debugger/DebuggerUI.jsm +++ b/browser/devtools/debugger/DebuggerUI.jsm @@ -563,16 +563,17 @@ DebuggerUI.prototype = { * The content type of the source script. */ _onSourceLoaded: function DebuggerUI__onSourceLoaded(aSourceUrl, aSourceText, aContentType) { let dbg = this.getDebugger(this.aWindow.gBrowser.selectedTab); dbg.debuggerWindow.SourceScripts.setEditorMode(aSourceUrl, aContentType); dbg.editor.setText(aSourceText); + dbg.editor.resetUndo(); let doc = dbg.frame.contentDocument; let scripts = doc.getElementById("scripts"); let elt = scripts.getElementsByAttribute("value", aSourceUrl)[0]; let script = elt.getUserData("sourceScript"); script.loaded = true; script.text = aSourceText; script.contentType = aContentType; elt.setUserData("sourceScript", script, null);
--- a/browser/devtools/debugger/debugger.js +++ b/browser/devtools/debugger/debugger.js @@ -610,16 +610,17 @@ var SourceScripts = { var evt = document.createEvent("CustomEvent"); evt.initCustomEvent("Debugger:LoadSource", true, false, aScript.url); document.documentElement.dispatchEvent(evt); window.editor.setText(DebuggerView.getStr("loadingText")); } else { window.editor.setText(aScript.text); window.updateEditorBreakpoints(); } + window.editor.resetUndo(); } }; SourceScripts.onPaused = SourceScripts.onPaused.bind(SourceScripts); SourceScripts.onScripts = SourceScripts.onScripts.bind(SourceScripts); SourceScripts.onNewScript = SourceScripts.onNewScript.bind(SourceScripts); SourceScripts.onScriptsCleared = SourceScripts.onScriptsCleared.bind(SourceScripts); SourceScripts.onChange = SourceScripts.onChange.bind(SourceScripts);
--- a/browser/devtools/debugger/debugger.xul +++ b/browser/devtools/debugger/debugger.xul @@ -40,20 +40,39 @@ <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?> <?xml-stylesheet href="chrome://browser/content/orion.css" type="text/css"?> <?xml-stylesheet href="chrome://browser/content/debugger.css" type="text/css"?> <?xml-stylesheet href="chrome://browser/skin/devtools/debugger.css" type="text/css"?> <!DOCTYPE window [ <!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/debugger.dtd" > %debuggerDTD; ]> +<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?> +<?xul-overlay href="chrome://browser/content/source-editor-overlay.xul"?> <xul:window xmlns="http://www.w3.org/1999/xhtml" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + <xul:script type="text/javascript" src="chrome://global/content/globalOverlay.js"/> <xul:script type="text/javascript" src="debugger.js"/> <xul:script type="text/javascript" src="debugger-view.js"/> + <xul:popupset id="debugger-popups"> + <xul:menupopup id="sourceEditorContextMenu" + onpopupshowing="goUpdateSourceEditorMenuItems()"> + <xul:menuitem id="se-cMenu-copy"/> + <xul:menuseparator/> + <xul:menuitem id="se-cMenu-selectAll"/> + <xul:menuseparator/> + <xul:menuitem id="se-cMenu-find"/> + <xul:menuitem id="se-cMenu-findAgain"/> + <xul:menuseparator/> + <xul:menuitem id="se-cMenu-gotoLine"/> + </xul:menupopup> + </xul:popupset> + <xul:commandset id="editMenuCommands"/> + <xul:commandset id="sourceEditorCommands"/> + <xul:keyset id="sourceEditorKeys"/> <div id="body" class="vbox flex"> <xul:toolbar id="dbg-toolbar"> <xul:button id="close">&debuggerUI.closeButton;</xul:button> <xul:button id="resume"/> <xul:menulist id="scripts"/> </xul:toolbar> <div id="dbg-content" class="hbox flex">
--- a/browser/devtools/debugger/test/Makefile.in +++ b/browser/devtools/debugger/test/Makefile.in @@ -69,16 +69,17 @@ include $(topsrcdir)/config/rules.mk browser_dbg_stack-04.js \ browser_dbg_location-changes.js \ browser_dbg_script-switching.js \ browser_dbg_pause-resume.js \ browser_dbg_update-editor-mode.js \ 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) _BROWSER_TEST_PAGES = \ browser_dbg_tab1.html \ browser_dbg_tab2.html \ browser_dbg_debuggerstatement.html \ browser_dbg_stack.html \
new file mode 100644 --- /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; + }); +}
--- a/browser/devtools/jar.mn +++ b/browser/devtools/jar.mn @@ -5,14 +5,14 @@ browser.jar: content/browser/scratchpad.js (scratchpad/scratchpad.js) content/browser/splitview.css (shared/splitview.css) * content/browser/styleeditor.xul (styleeditor/styleeditor.xul) content/browser/styleeditor.css (styleeditor/styleeditor.css) content/browser/devtools/csshtmltree.xul (styleinspector/csshtmltree.xul) 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) content/browser/debugger-view.js (debugger/debugger-view.js)
--- a/browser/devtools/scratchpad/scratchpad.xul +++ b/browser/devtools/scratchpad/scratchpad.xul @@ -106,31 +106,16 @@ <!-- TODO: bug 650340 - implement printFile <key id="sp-key-printFile" key="&printCmd.commandkey;" command="sp-cmd-printFile" modifiers="accel"/> --> - <key id="key_cut" - key="&cutCmd.key;" - modifiers="accel"/> - - <key id="key_copy" - key="©Cmd.key;" - modifiers="accel"/> - <key id="key_paste" - key="&pasteCmd.key;" - modifiers="accel"/> - <key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/> - <key id="key_undo" key="&undoCmd.key;" modifiers="accel" - command="se-cmd-undo"/> - <key id="key_redo" key="&undoCmd.key;" modifiers="accel,shift" - command="se-cmd-redo"/> <key id="sp-key-run" key="&run.key;" command="sp-cmd-run" modifiers="accel"/> <key id="sp-key-inspect" key="&inspect.key;" command="sp-cmd-inspect" modifiers="accel"/> @@ -141,38 +126,16 @@ <key id="sp-key-errorConsole" key="&errorConsoleCmd.commandkey;" command="sp-cmd-errorConsole" modifiers="accel,shift"/> <key id="sp-key-webConsole" key="&webConsoleCmd.commandkey;" command="sp-cmd-webConsole" modifiers="accel,shift"/> - <key id="key_find" - key="&findCmd.key;" - command="cmd_find" - modifiers="accel"/> -#ifdef XP_MACOSX - <key id="key_findAgain" - key="&findAgainCmd.key;" - command="cmd_findAgain" - modifiers="accel"/> - <key id="key_findPrevious" - key="&findPreviousCmd.key;" - command="cmd_findPrevious" - modifiers="accel,shift"/> -#else - <key id="key_findAgain" - keycode="VK_F3" - command="cmd_findAgain"/> - <key id="key_findPrevious" - keycode="VK_F3" - command="cmd_findPrevious" - modifiers="shift"/> -#endif <key id="key_openHelp" keycode="VK_F1" command="sp-cmd-documentationLink"/> </keyset> <menubar id="sp-menubar"> <menu id="sp-file-menu" label="&fileMenu.label;" @@ -214,66 +177,30 @@ accesskey="&closeCmd.accesskey;" command="sp-cmd-close"/> </menupopup> </menu> <menu id="sp-edit-menu" label="&editMenu.label;" accesskey="&editMenu.accesskey;"> <menupopup id="sp-menu_editpopup" - onpopupshowing="goUpdateGlobalEditMenuItems()"> - <menuitem id="sp-menu-undo" - label="&undoCmd.label;" - key="key_undo" - accesskey="&undoCmd.accesskey;" - command="se-cmd-undo"/> - <menuitem id="sp-menu-redo" - label="&redoCmd.label;" - key="key_redo" - accesskey="&redoCmd.accesskey;" - command="se-cmd-redo"/> + onpopupshowing="goUpdateSourceEditorMenuItems()"> + <menuitem id="se-menu-undo"/> + <menuitem id="se-menu-redo"/> <menuseparator/> - <menuitem id="sp-menu-cut" - label="&cutCmd.label;" - key="key_cut" - accesskey="&cutCmd.accesskey;" - command="cmd_cut"/> - <menuitem id="sp-menu-copy" - label="©Cmd.label;" - key="key_copy" - accesskey="©Cmd.accesskey;" - command="cmd_copy"/> - <menuitem id="sp-menu-paste" - label="&pasteCmd.label;" - key="key_paste" - accesskey="&pasteCmd.accesskey;" - command="cmd_paste"/> + <menuitem id="se-menu-cut"/> + <menuitem id="se-menu-copy"/> + <menuitem id="se-menu-paste"/> <menuseparator/> - <menuitem id="sp-menu-selectAll" - label="&selectAllCmd.label;" - key="key_selectAll" - accesskey="&selectAllCmd.accesskey;" - command="cmd_selectAll"/> + <menuitem id="se-menu-selectAll"/> <menuseparator/> - <menuitem id="sp-menu-find" - label="&findCmd.label;" - accesskey="&findCmd.accesskey;" - key="key_find" - command="cmd_find"/> - <menuitem id="sp-menu-findAgain" - label="&findAgainCmd.label;" - accesskey="&findAgainCmd.accesskey;" - key="key_findAgain" - command="cmd_findAgain"/> + <menuitem id="se-menu-find"/> + <menuitem id="se-menu-findAgain"/> <menuseparator/> - <menuitem id="sp-menu-gotoLine" - label="&gotoLineCmd.label;" - accesskey="&gotoLineCmd.accesskey;" - key="key_gotoLine" - command="cmd_gotoLine"/> + <menuitem id="se-menu-gotoLine"/> </menupopup> </menu> <menu id="sp-execute-menu" label="&executeMenu.label;" accesskey="&executeMenu.accesskey;"> <menupopup id="sp-menu_executepopup"> <menuitem id="sp-text-run" label="&run.label;" @@ -333,23 +260,23 @@ command="sp-cmd-documentationLink" key="key_openHelp"/> </menupopup> </menu> </menubar> <popupset id="scratchpad-popups"> <menupopup id="scratchpad-text-popup" - onpopupshowing="goUpdateGlobalEditMenuItems()"> - <menuitem id="menu_cut"/> - <menuitem id="menu_copy"/> - <menuitem id="menu_paste"/> - <menuitem id="menu_delete"/> + onpopupshowing="goUpdateSourceEditorMenuItems()"> + <menuitem id="se-cMenu-cut"/> + <menuitem id="se-cMenu-copy"/> + <menuitem id="se-cMenu-paste"/> + <menuitem id="se-cMenu-delete"/> <menuseparator/> - <menuitem id="menu_selectAll"/> + <menuitem id="se-cMenu-selectAll"/> <menuseparator/> <menuitem id="sp-text-run" label="&run.label;" accesskey="&run.accesskey;" key="sp-key-run" command="sp-cmd-run"/> <menuitem id="sp-text-inspect" label="&inspect.label;" @@ -365,12 +292,12 @@ <menuitem id="sp-text-resetContext" label="&resetContext2.label;" accesskey="&resetContext2.accesskey;" command="sp-cmd-resetContext"/> </menupopup> </popupset> <notificationbox id="scratchpad-notificationbox" flex="1"> - <hbox id="scratchpad-editor" flex="1" context="scratchpad-text-popup" /> + <hbox id="scratchpad-editor" flex="1"/> </notificationbox> </window>
--- 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 @@ -22,17 +22,17 @@ function test() } function runTests() { let sp = gScratchpadWindow.Scratchpad; 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"); let pass = 0; sp.setText("bug 699130: hello world! (edit menu)"); let editMenu = doc.getElementById("sp-edit-menu"); @@ -46,19 +46,19 @@ function runTests() editMenuIndex = i; break; } } isnot(editMenuIndex, -1, "Edit menu index is correct"); 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; let isContextMenu = false; let openMenu = function(aX, aY, aCallback) { if (!editMenu || OS != "Darwin") { menuPopup.addEventListener("popupshown", function onPopupShown() { @@ -169,19 +169,19 @@ function runTests() let testContextMenu = function() { info("will test the context menu"); editMenu = null; isContextMenu = true; 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)"); openMenu(10, 10, firstShow); }; openMenu(10, 10, firstShow); }
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm +++ b/browser/devtools/sourceeditor/source-editor-orion.jsm @@ -19,16 +19,17 @@ * Portions created by the Initial Developer are Copyright (C) 2011 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Mihai Sucan <mihai.sucan@gmail.com> (original author) * Kenny Heaton <kennyheaton@gmail.com> * Spyros Livathinos <livathinos.spyros@gmail.com> * Allen Eubank <adeubank@gmail.com> + * Girish Sharma <scrapmachines@gmail.com> * * 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 @@ -59,16 +60,24 @@ const ORION_IFRAME = "data:text/html;cha " href='chrome://browser/skin/devtools/orion-container.css'></head>" + "<body style='height:100%;margin:0;overflow:hidden'>" + "<div id='editor' style='height:100%'></div>" + "</body></html>"; 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. * * @type number */ const PRIMARY_SELECTION_DELAY = 100; /** @@ -105,16 +114,20 @@ const ORION_ANNOTATION_TYPES = { currentLine: "orion.annotation.currentLine", }; /** * 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, accel: true, }, { action: "redo", code: Ci.nsIDOMKeyEvent.DOM_VK_Z, accel: true, @@ -460,16 +473,20 @@ SourceEditor.prototype = { /** * The "tab" editor action implementation. This adds support for expanded tabs * to spaces, and support for the indentation of multiple lines at once. * @private */ _doTab: function SE__doTab() { + if (this.readOnly) { + return false; + } + let indent = "\t"; let selection = this.getSelection(); let model = this._model; let firstLine = model.getLineAtOffset(selection.start); let firstLineStart = model.getLineStart(firstLine); let lastLineOffset = selection.end > selection.start ? selection.end - 1 : selection.end; let lastLine = model.getLineAtOffset(lastLineOffset); @@ -510,16 +527,20 @@ SourceEditor.prototype = { /** * The "Unindent lines" editor action implementation. This method is invoked * when the user presses Shift-Tab. * @private */ _doUnindentLines: function SE__doUnindentLines() { + if (this.readOnly) { + return true; + } + let indent = "\t"; let selection = this.getSelection(); let model = this._model; let firstLine = model.getLineAtOffset(selection.start); let lastLineOffset = selection.end > selection.start ? selection.end - 1 : selection.end; let lastLine = model.getLineAtOffset(lastLineOffset); @@ -564,16 +585,20 @@ SourceEditor.prototype = { /** * The editor Enter action implementation, which adds simple automatic * indentation based on the previous line when the user presses the Enter key. * @private */ _doEnter: function SE__doEnter() { + if (this.readOnly) { + return false; + } + let selection = this.getSelection(); if (selection.start != selection.end) { return false; } let model = this._model; let lineIndex = model.getLineAtOffset(selection.start); let lineText = model.getLine(lineIndex, true); @@ -1304,20 +1329,66 @@ SourceEditor.prototype = { /** * Set the caret position: line and column. * * @param number aLine * 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); }, /** * Get the line count. * * @return number * The number of lines in the document being edited. */
--- a/browser/devtools/sourceeditor/source-editor-overlay.xul +++ b/browser/devtools/sourceeditor/source-editor-overlay.xul @@ -30,85 +30,208 @@ - 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 ***** --> -<!DOCTYPE overlay SYSTEM "chrome://browser/locale/devtools/sourceeditor.dtd"> +<!DOCTYPE overlay [ + <!ENTITY % editMenuStrings SYSTEM "chrome://global/locale/editMenuOverlay.dtd"> + %editMenuStrings; + <!ENTITY % sourceEditorStrings SYSTEM "chrome://browser/locale/devtools/sourceeditor.dtd"> + %sourceEditorStrings; +]> <overlay id="sourceEditorOverlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <!-- This Source Editor overlay requires the editMenuOverlay.xul to be loaded. The globalOverlay.js script is also required in the XUL document where - the source-editor-overlay.xul is loaded. --> + the source-editor-overlay.xul is loaded. Do not use #editMenuKeys to + avoid conflicts! --> + + <script type="application/javascript"> + function goUpdateSourceEditorMenuItems() + { + goUpdateGlobalEditMenuItems(); + let commands = ['se-cmd-undo', 'se-cmd-redo', 'se-cmd-cut', 'se-cmd-paste', + 'se-cmd-delete']; + commands.forEach(goUpdateCommand); + } + </script> <commandset id="sourceEditorCommands"> <command id="cmd_find" oncommand="goDoCommand('cmd_find')"/> <command id="cmd_findAgain" oncommand="goDoCommand('cmd_findAgain')" disabled="true"/> <command id="cmd_findPrevious" oncommand="goDoCommand('cmd_findPrevious')" disabled="true"/> <command id="cmd_gotoLine" oncommand="goDoCommand('cmd_gotoLine')"/> + <command id="se-cmd-selectAll" oncommand="goDoCommand('se-cmd-selectAll')"/> + <command id="se-cmd-cut" oncommand="goDoCommand('se-cmd-cut')" disabled="true"/> + <command id="se-cmd-paste" oncommand="goDoCommand('se-cmd-paste')" disabled="true"/> + <command id="se-cmd-delete" oncommand="goDoCommand('se-cmd-delete')" disabled="true"/> <command id="se-cmd-undo" oncommand="goDoCommand('se-cmd-undo')" disabled="true"/> <command id="se-cmd-redo" oncommand="goDoCommand('se-cmd-redo')" disabled="true"/> </commandset> <keyset id="sourceEditorKeys"> + <!-- Do not use both #sourceEditorKeys and #editMenuKeys in the same + document to avoid conflicts! --> + <key id="key_undo" + key="&undoCmd.key;" + modifiers="accel" + command="se-cmd-undo"/> +#ifdef XP_UNIX + <key id="key_redo" + key="&undoCmd.key;" + modifiers="accel,shift" + command="se-cmd-redo"/> +#else + <key id="key_redo" + key="&redoCmd.key;" + modifiers="accel" + command="se-cmd-redo"/> +#endif + <key id="key_cut" + key="&cutCmd.key;" + modifiers="accel" + command="se-cmd-cut"/> + <key id="key_copy" + key="©Cmd.key;" + modifiers="accel" + command="cmd_copy"/> + <key id="key_paste" + key="&pasteCmd.key;" + modifiers="accel" + command="se-cmd-paste"/> <key id="key_gotoLine" key="&gotoLineCmd.key;" command="cmd_gotoLine" modifiers="accel"/> + <key id="key_delete" + keycode="VK_DELETE" + command="se-cmd-delete"/> + <key id="key_selectAll" + key="&selectAllCmd.key;" + modifiers="accel" + command="se-cmd-selectAll"/> + <key id="key_find" + key="&findCmd.key;" + modifiers="accel" + command="cmd_find"/> + <key id="key_findAgain" + key="&findAgainCmd.key;" + modifiers="accel" + command="cmd_findAgain"/> + <key id="key_findPrevious" + key="&findAgainCmd.key;" + modifiers="shift,accel" + command="cmd_findPrevious"/> + <key id="key_findAgain2" + keycode="&findAgainCmd.key2;" + command="cmd_findAgain"/> + <key id="key_findPrevious2" + keycode="&findAgainCmd.key2;" + modifiers="shift" + command="cmd_findPrevious"/> </keyset> - <menupopup id="sourceEditorContextMenu" - onpopupshowing="goUpdateGlobalEditMenuItems()"> - <menuitem id="se-menu-undo" - label="&undoCmd.label;" - key="key_undo" - accesskey="&undoCmd.accesskey;" - command="se-cmd-undo"/> - <menuseparator/> - <menuitem id="se-menu-cut" - label="&cutCmd.label;" - key="key_cut" - accesskey="&cutCmd.accesskey;" - command="cmd_cut"/> - <menuitem id="se-menu-copy" - label="©Cmd.label;" - key="key_copy" - accesskey="©Cmd.accesskey;" - command="cmd_copy"/> - <menuitem id="se-menu-paste" - label="&pasteCmd.label;" - key="key_paste" - accesskey="&pasteCmd.accesskey;" - command="cmd_paste"/> - <menuitem id="se-menu-delete" - label="&deleteCmd.label;" - key="key_delete" - accesskey="&deleteCmd.accesskey;" - command="cmd_delete"/> - <menuseparator/> - <menuitem id="se-menu-selectAll" - label="&selectAllCmd.label;" - key="key_selectAll" - accesskey="&selectAllCmd.accesskey;" - command="cmd_selectAll"/> - <menuseparator/> - <menuitem id="se-menu-find" - label="&findCmd.label;" - accesskey="&findCmd.accesskey;" - key="key_find" - command="cmd_find"/> - <menuitem id="se-menu-findAgain" - label="&findAgainCmd.label;" - accesskey="&findAgainCmd.accesskey;" - key="key_findAgain" - command="cmd_findAgain"/> - <menuseparator/> - <menuitem id="se-menu-gotoLine" - label="&gotoLineCmd.label;" - accesskey="&gotoLineCmd.accesskey;" - key="key_gotoLine" - command="cmd_gotoLine"/> - </menupopup> + <!-- Items for the Edit menu --> + + <menuitem id="se-menu-undo" + label="&undoCmd.label;" + key="key_undo" + accesskey="&undoCmd.accesskey;" + command="se-cmd-undo"/> + <menuitem id="se-menu-redo" + label="&redoCmd.label;" + key="key_redo" + accesskey="&redoCmd.accesskey;" + command="se-cmd-redo"/> + <menuitem id="se-menu-cut" + label="&cutCmd.label;" + key="key_cut" + accesskey="&cutCmd.accesskey;" + command="se-cmd-cut"/> + <menuitem id="se-menu-copy" + label="©Cmd.label;" + key="key_copy" + accesskey="©Cmd.accesskey;" + command="cmd_copy"/> + <menuitem id="se-menu-paste" + label="&pasteCmd.label;" + key="key_paste" + accesskey="&pasteCmd.accesskey;" + command="se-cmd-paste"/> + <menuitem id="se-menu-delete" + label="&deleteCmd.label;" + key="key_delete" + accesskey="&deleteCmd.accesskey;" + command="se-cmd-delete"/> + <menuitem id="se-menu-selectAll" + label="&selectAllCmd.label;" + key="key_selectAll" + accesskey="&selectAllCmd.accesskey;" + command="se-cmd-selectAll"/> + <menuitem id="se-menu-find" + label="&findCmd.label;" + accesskey="&findCmd.accesskey;" + key="key_find" + command="cmd_find"/> + <menuitem id="se-menu-findAgain" + label="&findAgainCmd.label;" + accesskey="&findAgainCmd.accesskey;" + key="key_findAgain" + command="cmd_findAgain"/> + <menuitem id="se-menu-gotoLine" + label="&gotoLineCmd.label;" + accesskey="&gotoLineCmd.accesskey;" + key="key_gotoLine" + command="cmd_gotoLine"/> + + <!-- Items for context menus --> + + <menuitem id="se-cMenu-undo" + label="&undoCmd.label;" + key="key_undo" + accesskey="&undoCmd.accesskey;" + command="se-cmd-undo"/> + <menuitem id="se-cMenu-cut" + label="&cutCmd.label;" + key="key_cut" + accesskey="&cutCmd.accesskey;" + command="se-cmd-cut"/> + <menuitem id="se-cMenu-copy" + label="©Cmd.label;" + key="key_copy" + accesskey="©Cmd.accesskey;" + command="cmd_copy"/> + <menuitem id="se-cMenu-paste" + label="&pasteCmd.label;" + key="key_paste" + accesskey="&pasteCmd.accesskey;" + command="se-cmd-paste"/> + <menuitem id="se-cMenu-delete" + label="&deleteCmd.label;" + key="key_delete" + accesskey="&deleteCmd.accesskey;" + command="se-cmd-delete"/> + <menuitem id="se-cMenu-selectAll" + label="&selectAllCmd.label;" + key="key_selectAll" + accesskey="&selectAllCmd.accesskey;" + command="se-cmd-selectAll"/> + <menuitem id="se-cMenu-find" + label="&findCmd.label;" + accesskey="&findCmd.accesskey;" + key="key_find" + command="cmd_find"/> + <menuitem id="se-cMenu-findAgain" + label="&findAgainCmd.label;" + accesskey="&findAgainCmd.accesskey;" + key="key_findAgain" + command="cmd_findAgain"/> + <menuitem id="se-cMenu-gotoLine" + label="&gotoLineCmd.label;" + accesskey="&gotoLineCmd.accesskey;" + key="key_gotoLine" + command="cmd_gotoLine"/> </overlay>
--- a/browser/devtools/sourceeditor/source-editor-ui.jsm +++ b/browser/devtools/sourceeditor/source-editor-ui.jsm @@ -248,16 +248,20 @@ SourceEditorController.prototype = { switch (aCommand) { case "cmd_find": case "cmd_findAgain": case "cmd_findPrevious": 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: result = false; break; } return result; @@ -273,28 +277,42 @@ SourceEditorController.prototype = { */ isCommandEnabled: function SEC_isCommandEnabled(aCommand) { let result; switch (aCommand) { case "cmd_find": case "cmd_gotoLine": + case "se-cmd-selectAll": result = true; break; case "cmd_findAgain": case "cmd_findPrevious": result = this._editor.lastFind && this._editor.lastFind.lastFound != -1; break; case "se-cmd-undo": result = this._editor.canUndo(); break; 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; } return result; }, @@ -315,19 +333,33 @@ SourceEditorController.prototype = { this._editor.ui.findNext(); break; case "cmd_findPrevious": this._editor.ui.findPrevious(); break; 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; + } } }, onEvent: function() { } };
--- a/browser/devtools/sourceeditor/source-editor.jsm +++ b/browser/devtools/sourceeditor/source-editor.jsm @@ -308,16 +308,26 @@ SourceEditor.EVENTS = { * have not been saved yet. Event object properties: oldValue and newValue. * Both are booleans telling the old dirty state and the new state, * respectively. */ 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. * * @param object aDestination * @param object aSource */ function extend(aDestination, aSource) { for (let name in aSource) { @@ -331,16 +341,17 @@ function extend(aDestination, aSource) * Add methods common to all components. */ extend(SourceEditor.prototype, { // Expose the static constants on the SourceEditor instances. EVENTS: SourceEditor.EVENTS, MODES: SourceEditor.MODES, THEMES: SourceEditor.THEMES, DEFAULTS: SourceEditor.DEFAULTS, + VERTICAL_ALIGN: SourceEditor.VERTICAL_ALIGN, _lastFind: null, /** * Find a string in the editor. * * @param string aString * The string you want to search for. If |aString| is not given the
--- a/browser/devtools/sourceeditor/test/Makefile.in +++ b/browser/devtools/sourceeditor/test/Makefile.in @@ -55,12 +55,13 @@ include $(topsrcdir)/config/rules.mk browser_bug687160_line_api.js \ browser_bug650345_find.js \ browser_bug703692_focus_blur.js \ browser_bug725388_mouse_events.js \ browser_bug707987_debugger_breakpoints.js \ 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) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644 --- /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,<?xml version='1.0'?>" + + "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" + + " title='test for bug 729480 - allow setCaretPosition align the target line" + + " vertically in view according to a third argument'" + + " width='300' height='300'><box flex='1'/></window>"; + 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); +}
--- a/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js +++ b/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js @@ -196,21 +196,31 @@ function editorLoaded() editor.readOnly = true; EventUtils.synthesizeKey("b", {}, testWin); is(editor.getText(), "foofoo", "editor is now read-only (keyboard)"); 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. editor.setText("foobarbaz"); editor.setSelection(1, 4); let event = null;
--- a/browser/devtools/styleeditor/styleeditor.xul +++ b/browser/devtools/styleeditor/styleeditor.xul @@ -52,26 +52,40 @@ id="style-editor-chrome-window" title="&window.title;" windowtype="Tools:StyleEditor" width="800" height="280" persist="screenX screenY width height sizemode"> <xul:script type="application/javascript" src="chrome://global/content/globalOverlay.js"/> <xul:popupset id="style-editor-popups"> - <xul:menupopup id="sourceEditorContextMenu"/> + <xul:menupopup id="sourceEditorContextMenu" + onpopupshowing="goUpdateSourceEditorMenuItems()"> + <xul:menuitem id="se-cMenu-undo"/> + <xul:menuseparator/> + <xul:menuitem id="se-cMenu-cut"/> + <xul:menuitem id="se-cMenu-copy"/> + <xul:menuitem id="se-cMenu-paste"/> + <xul:menuitem id="se-cMenu-delete"/> + <xul:menuseparator/> + <xul:menuitem id="se-cMenu-selectAll"/> + <xul:menuseparator/> + <xul:menuitem id="se-cMenu-find"/> + <xul:menuitem id="se-cMenu-findAgain"/> + <xul:menuseparator/> + <xul:menuitem id="se-cMenu-gotoLine"/> + </xul:menupopup> </xul:popupset> <xul:commandset id="editMenuCommands"/> <xul:commandset id="sourceEditorCommands"/> <xul:commandset id="style-editor-commandset"> <xul:command id="style-editor-cmd-close" oncommand="window.close();"/> </xul:commandset> -<xul:keyset id="editMenuKeys"/> <xul:keyset id="sourceEditorKeys"/> <xul:keyset id="style-editor-keyset"> <xul:key id="style-editor-key-close" key="&closeCmd.key;" command="style-editor-cmd-close" modifiers="accel"/> </xul:keyset>
--- a/browser/locales/en-US/chrome/browser/browser.properties +++ b/browser/locales/en-US/chrome/browser/browser.properties @@ -328,12 +328,28 @@ syncPromoNotification.learnMoreLinkText= # LOCALIZATION NOTE (telemetryPrompt): %1$S will be replaced by brandFullName, # and %2$S by the value of the toolkit.telemetry.server_owner preference. telemetryPrompt = Will you help improve %1$S by sending anonymous information about performance, hardware characteristics, feature usage, and browser customizations to %2$S? telemetryLinkLabel = Learn More telemetryYesButtonLabel2 = Yes, I want to help telemetryYesButtonAccessKey = Y telemetryNoButtonLabel = No telemetryNoButtonAccessKey = N + +# Keyword.URL reset prompt +# LOCALIZATION NOTE (keywordPrompt.message): +# - %1$S is brandShortName +# - %2$S is a host name (e.g. "somewebsearch.com") from the current value of keyword.URL +# - %3$S is the name of the default search engine (e.g. "Google") +keywordPrompt.message = %1$S is using '%2$S' for searches from the location bar. Would you like to restore the default search (%3$S)? + +# LOCALIZATION NOTE (keywordPrompt.yesButton): %1$S is the name of the default search engine +keywordPrompt.yesButton = Yes, use %1$S +keywordPrompt.yesButton.accessKey = Y + +# LOCALIZATION NOTE (keywordPrompt.noButton): %1$S is a host name (e.g. "somewebsearch.com") from the current value of keyword.URL +keywordPrompt.noButton = No, continue using '%1$S' +keywordPrompt.noButton.accessKey = N + # Telemetry opt-out prompt for Aurora and Nightly # LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by # brandFullName, and %2$S by the value of the toolkit.telemetry.server_owner preference. telemetryOptOutPrompt = %1$S sends information about performance, hardware, usage and customizations back to %2$S to help improve %3$S.
--- a/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd +++ b/browser/locales/en-US/chrome/browser/devtools/scratchpad.dtd @@ -38,60 +38,16 @@ <!ENTITY closeCmd.label "Close"> <!ENTITY closeCmd.key "W"> <!ENTITY closeCmd.accesskey "C"> <!ENTITY editMenu.label "Edit"> <!ENTITY editMenu.accesskey "E"> -<!ENTITY undoCmd.label "Undo"> -<!ENTITY undoCmd.key "Z"> -<!ENTITY undoCmd.accesskey "U"> - -<!ENTITY redoCmd.label "Redo"> -<!ENTITY redoCmd.key "Y"> -<!ENTITY redoCmd.accesskey "R"> - -<!ENTITY cutCmd.label "Cut"> -<!ENTITY cutCmd.key "X"> -<!ENTITY cutCmd.accesskey "t"> - -<!ENTITY copyCmd.label "Copy"> -<!ENTITY copyCmd.key "C"> -<!ENTITY copyCmd.accesskey "C"> - -<!ENTITY pasteCmd.label "Paste"> -<!ENTITY pasteCmd.key "V"> -<!ENTITY pasteCmd.accesskey "P"> - -<!ENTITY selectAllCmd.label "Select All"> -<!ENTITY selectAllCmd.key "A"> -<!ENTITY selectAllCmd.accesskey "A"> - -<!ENTITY findCmd.label "Find…"> -<!ENTITY findCmd.key "F"> -<!ENTITY findCmd.accesskey "F"> - -<!ENTITY findAgainCmd.label "Find Again…"> -<!-- LOCALIZATION NOTE (findAgainCmd.key): This key is used only on Macs. - - Windows and Linux builds use the F3 key which is not localizable on purpose. - --> -<!ENTITY findAgainCmd.key "G"> -<!ENTITY findAgainCmd.accesskey "g"> -<!-- LOCALIZATION NOTE (findPreviousCmd.key): This key is used only on Macs. - - Windows and Linux builds use the Shift-F3 key which is not localizable on - - purpose. - --> -<!ENTITY findPreviousCmd.key "G"> - -<!ENTITY gotoLineCmd.label "Jump to line…"> -<!ENTITY gotoLineCmd.key "J"> -<!ENTITY gotoLineCmd.accesskey "J"> - <!ENTITY run.label "Run"> <!ENTITY run.accesskey "R"> <!ENTITY run.key "r"> <!ENTITY inspect.label "Inspect"> <!ENTITY inspect.accesskey "I"> <!ENTITY inspect.key "i">
--- a/browser/locales/en-US/chrome/browser/devtools/sourceeditor.dtd +++ b/browser/locales/en-US/chrome/browser/devtools/sourceeditor.dtd @@ -5,28 +5,11 @@ <!-- LOCALIZATION NOTE : FILE Do not translate commandkeys --> <!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to - keep it in English, or another language commonly spoken among web developers. - You want to make that choice consistent across the developer tools. - A good criteria is the language in which you'd find the best - documentation on web development on the web. --> -<!ENTITY undoCmd.label "Undo"> -<!ENTITY undoCmd.accesskey "U"> -<!ENTITY cutCmd.label "Cut"> -<!ENTITY cutCmd.accesskey "t"> -<!ENTITY copyCmd.label "Copy"> -<!ENTITY copyCmd.accesskey "C"> -<!ENTITY pasteCmd.label "Paste"> -<!ENTITY pasteCmd.accesskey "P"> -<!ENTITY deleteCmd.label "Delete"> -<!ENTITY deleteCmd.accesskey "D"> -<!ENTITY selectAllCmd.label "Select All"> -<!ENTITY selectAllCmd.accesskey "A"> -<!ENTITY findCmd.label "Find…"> -<!ENTITY findCmd.accesskey "F"> -<!ENTITY findAgainCmd.label "Find Again…"> -<!ENTITY findAgainCmd.accesskey "g"> <!ENTITY gotoLineCmd.label "Jump to line…"> <!ENTITY gotoLineCmd.key "J"> <!ENTITY gotoLineCmd.accesskey "J"> -
new file mode 100644 --- /dev/null +++ b/browser/modules/KeywordURLResetPrompter.jsm @@ -0,0 +1,105 @@ +/* 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/. */ + +let EXPORTED_SYMBOLS = [ "KeywordURLResetPrompter" ]; + +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); + +const KEYWORD_PROMPT_REV = 1; + +let KeywordURLResetPrompter = { + get shouldPrompt() { + let keywordURLUserSet = Services.prefs.prefHasUserValue("keyword.URL"); + let declinedRev; + try { + declinedRev = Services.prefs.getIntPref("browser.keywordURLPromptDeclined"); + } catch (ex) {} + + return keywordURLUserSet && declinedRev != KEYWORD_PROMPT_REV; + }, + + prompt: function KeywordURLResetPrompter_prompt(win, keywordURI) { + let tabbrowser = win.gBrowser; + let notifyBox = tabbrowser.getNotificationBox(); + + let existingNotification = notifyBox.getNotificationWithValue("keywordURL-reset"); + if (existingNotification) + return; + + // Find the name/URI of this build's original default engine. + // XXX: Can't use originalDefaultEngine getter here, because that doesn't + // use the default pref branch. + let defaultURI; + let defaultEngine; + try { + let defaultPB = Services.prefs.getDefaultBranch(null); + let defaultName = defaultPB.getComplexValue("browser.search.defaultenginename", + Ci.nsIPrefLocalizedString).data; + defaultEngine = Services.search.getEngineByName(defaultName); + defaultURI = defaultEngine.getSubmission("foo").uri; + } catch (ex) { + // Something went horribly wrong! bail out + return; + } + + // If the user-set value has the same base domain as the default, don't + // prompt. + let keywordBaseDomain; + try { + keywordBaseDomain = Services.eTLD.getBaseDomain(keywordURI); + if (keywordBaseDomain == Services.eTLD.getBaseDomain(defaultURI)) + return; + } catch (ex) {} + + if (!keywordBaseDomain) + return; + + let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties"); + let brandShortName = brandBundle.GetStringFromName("brandShortName"); + + let browserBundle = win.gNavigatorBundle; + let msg = browserBundle.getFormattedString("keywordPrompt.message", + [brandShortName, keywordBaseDomain, + defaultEngine.name]); + let buttons = [ + { + label: browserBundle.getFormattedString("keywordPrompt.yesButton", + [defaultEngine.name]), + accessKey: browserBundle.getString("keywordPrompt.yesButton.accessKey"), + popup: null, + callback: function(aNotificationBar, aButton) { + Services.prefs.clearUserPref("keyword.URL"); + try { + // If the currently loaded URI still has the same base domain as the + // keyword URI (this is used as a rough approximation of whether the + // user is still seeing search results as opposed to having clicked + // on a result link), load the default engine's searchForm URL so + // that they can re-do their search. + let currentBaseDomain = Services.eTLD.getBaseDomain(tabbrowser.currentURI); + if (currentBaseDomain == keywordBaseDomain) + tabbrowser.loadURI(defaultEngine.searchForm); + } catch (ex) {} + } + }, + { + label: browserBundle.getFormattedString("keywordPrompt.noButton", + [keywordBaseDomain]), + accessKey: browserBundle.getString("keywordPrompt.noButton.accessKey"), + popup: null, + callback: function(aNotificationBar, aButton) { + Services.prefs.setIntPref("browser.keywordURLPromptDeclined", KEYWORD_PROMPT_REV); + } + } + ]; + + let notification = notifyBox.appendNotification(msg, "keywordURL-reset", null, notifyBox.PRIORITY_WARNING_HIGH, buttons); + notification.setAttribute("hideclose", true); + // stick around for a few page loads in case there are redirects involved + notification.persistence = 3; + } +}
--- a/browser/modules/Makefile.in +++ b/browser/modules/Makefile.in @@ -47,16 +47,17 @@ include $(topsrcdir)/config/config.mk TEST_DIRS += test EXTRA_JS_MODULES = \ openLocationLastURL.jsm \ NetworkPrioritizer.jsm \ NewTabUtils.jsm \ offlineAppCache.jsm \ TelemetryTimestamps.jsm \ + KeywordURLResetPrompter.jsm \ $(NULL) ifeq ($(MOZ_WIDGET_TOOLKIT),windows) EXTRA_JS_MODULES += \ WindowsPreviewPerTab.jsm \ WindowsJumpLists.jsm \ $(NULL) endif
--- a/browser/themes/gnomestripe/devtools/csshtmltree.css +++ b/browser/themes/gnomestripe/devtools/csshtmltree.css @@ -200,17 +200,17 @@ */ .ruleview { background-color: #FFF; } .ruleview-rule-source { background-color: -moz-dialog; - color: #0091ff; + color: -moz-dialogText; padding: 2px 5px; cursor: pointer; } .ruleview-rule-source:hover { text-decoration: underline; }
index 8ef1ba4a5cd268f4549fa2b511d6d47f8b46333e..9184b95187e8b951069a209a9051a9eceba6e461 GIT binary patch literal 863 zc$@)W1EBngP)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^0009fNkl<Zc-pO1 zTS!z<6b(rP5kVx2TOx!RN`X?J5<=il^cO@Q{RGxe^;ut0R9a-Iqo#?^G#}+7(-2A! z60-**q=Z2bzEYbzPtUyWj5@2e2Z?GXHS}Y#&)#>fIcx88II{zTM|Kjsh{HrKk+%WJ zAy+h_1$Jx&Vju+r2d|+o^($UzYEvLrG@{)O13Bp3yBM15T3%i8U^5V|Xhgdm29BXy zQ$a(AVfYZRkHZKquM6RdMzp{GSVdEJERpfQ2J+CUDZ{sjfMpcu*TPsGJ&oW@5B!D! ze_;6!2v;<s{mVc$VP3;SBA<xa*g%J-eBK54+&Y4j#aQ`xo+b_eJv8zv7k=vmyhiXB zgiB2{1BpZdQB>a8HC*1%X*M-<b~C20Z=h9EUiUma9uIuhFYx#R@G2XEW4C~I4WXVa z_$(7r4@0=rL^BXeq{+Ih?rB14ZO6ru+IBPJ5cBkZ8)(*)+x;Eh`H^tfq34GX_;3U6 zB?tTy^}u6JqUUHhS6&0cr6%eTnAmk`UB}>qnzqZukDkOASGSyEG&6t6dVF*Pjha$w z4ol8O_&?pp%D@Srft$AHvZf<2cqyFw$E)G;_#s?sA`EcsiR|<oH*2_8)oi|7+0=cf zqA`K-y5y{%iEf}yQ!dvm9Lfi$(*cKT37*fLK!pb5^;NhmGYHk~$4c+<Fh{u5L>Lfo z+;QwUmYe1mn(EEB%WAJMCNqD_dRue@HJWldXW`VR5bDapYDW$nb{hhH1qfAS!R~S+ z(0^9CCT9l1r6$4v$DhJ8AL7^t*m*oRFS=P$GsGCfyo7Z#zb8i;sM3_(F$24mqkWc! zP-{AD)*o<>wE!j!j=4#AM~cFC!8P>;!lfp{0B?H|C-9D)4zuF~c7BqZn;BD?UtnD> zWOn33RH-SeeHs?02Ug20tonR-t?P@he|rzzW@CLG_Gzv;8R1eB@er-u{v@7tqO8RP zJI`c{;~hw3J(J(#BA?>QeG9Jf)@9u`h0Q>?qS>yecsE)z3Sr{gUaF~0fn3pub~_Bj p5__Z@8R^D<$K;SJ8qsdmz)uUW$2a}EvC#kk002ovPDHLkV1k%7iwOV#
--- a/browser/themes/pinstripe/devtools/csshtmltree.css +++ b/browser/themes/pinstripe/devtools/csshtmltree.css @@ -202,17 +202,17 @@ */ .ruleview { background-color: #FFF; } .ruleview-rule-source { background-color: -moz-dialog; - color: #0091ff; + color: -moz-dialogText; padding: 2px 5px; cursor: pointer; } .ruleview-rule-source:hover { text-decoration: underline; }
index 8ef1ba4a5cd268f4549fa2b511d6d47f8b46333e..9184b95187e8b951069a209a9051a9eceba6e461 GIT binary patch literal 863 zc$@)W1EBngP)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^0009fNkl<Zc-pO1 zTS!z<6b(rP5kVx2TOx!RN`X?J5<=il^cO@Q{RGxe^;ut0R9a-Iqo#?^G#}+7(-2A! z60-**q=Z2bzEYbzPtUyWj5@2e2Z?GXHS}Y#&)#>fIcx88II{zTM|Kjsh{HrKk+%WJ zAy+h_1$Jx&Vju+r2d|+o^($UzYEvLrG@{)O13Bp3yBM15T3%i8U^5V|Xhgdm29BXy zQ$a(AVfYZRkHZKquM6RdMzp{GSVdEJERpfQ2J+CUDZ{sjfMpcu*TPsGJ&oW@5B!D! ze_;6!2v;<s{mVc$VP3;SBA<xa*g%J-eBK54+&Y4j#aQ`xo+b_eJv8zv7k=vmyhiXB zgiB2{1BpZdQB>a8HC*1%X*M-<b~C20Z=h9EUiUma9uIuhFYx#R@G2XEW4C~I4WXVa z_$(7r4@0=rL^BXeq{+Ih?rB14ZO6ru+IBPJ5cBkZ8)(*)+x;Eh`H^tfq34GX_;3U6 zB?tTy^}u6JqUUHhS6&0cr6%eTnAmk`UB}>qnzqZukDkOASGSyEG&6t6dVF*Pjha$w z4ol8O_&?pp%D@Srft$AHvZf<2cqyFw$E)G;_#s?sA`EcsiR|<oH*2_8)oi|7+0=cf zqA`K-y5y{%iEf}yQ!dvm9Lfi$(*cKT37*fLK!pb5^;NhmGYHk~$4c+<Fh{u5L>Lfo z+;QwUmYe1mn(EEB%WAJMCNqD_dRue@HJWldXW`VR5bDapYDW$nb{hhH1qfAS!R~S+ z(0^9CCT9l1r6$4v$DhJ8AL7^t*m*oRFS=P$GsGCfyo7Z#zb8i;sM3_(F$24mqkWc! zP-{AD)*o<>wE!j!j=4#AM~cFC!8P>;!lfp{0B?H|C-9D)4zuF~c7BqZn;BD?UtnD> zWOn33RH-SeeHs?02Ug20tonR-t?P@he|rzzW@CLG_Gzv;8R1eB@er-u{v@7tqO8RP zJI`c{;~hw3J(J(#BA?>QeG9Jf)@9u`h0Q>?qS>yecsE)z3Sr{gUaF~0fn3pub~_Bj p5__Z@8R^D<$K;SJ8qsdmz)uUW$2a}EvC#kk002ovPDHLkV1k%7iwOV#
--- a/browser/themes/winstripe/devtools/csshtmltree.css +++ b/browser/themes/winstripe/devtools/csshtmltree.css @@ -200,17 +200,17 @@ */ .ruleview { background-color: #FFF; } .ruleview-rule-source { background-color: -moz-dialog; - color: #0091ff; + color: -moz-dialogText; padding: 2px 5px; cursor: pointer; } .ruleview-rule-source:hover { text-decoration: underline; }
index 8ef1ba4a5cd268f4549fa2b511d6d47f8b46333e..9184b95187e8b951069a209a9051a9eceba6e461 GIT binary patch literal 863 zc$@)W1EBngP)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^0009fNkl<Zc-pO1 zTS!z<6b(rP5kVx2TOx!RN`X?J5<=il^cO@Q{RGxe^;ut0R9a-Iqo#?^G#}+7(-2A! z60-**q=Z2bzEYbzPtUyWj5@2e2Z?GXHS}Y#&)#>fIcx88II{zTM|Kjsh{HrKk+%WJ zAy+h_1$Jx&Vju+r2d|+o^($UzYEvLrG@{)O13Bp3yBM15T3%i8U^5V|Xhgdm29BXy zQ$a(AVfYZRkHZKquM6RdMzp{GSVdEJERpfQ2J+CUDZ{sjfMpcu*TPsGJ&oW@5B!D! ze_;6!2v;<s{mVc$VP3;SBA<xa*g%J-eBK54+&Y4j#aQ`xo+b_eJv8zv7k=vmyhiXB zgiB2{1BpZdQB>a8HC*1%X*M-<b~C20Z=h9EUiUma9uIuhFYx#R@G2XEW4C~I4WXVa z_$(7r4@0=rL^BXeq{+Ih?rB14ZO6ru+IBPJ5cBkZ8)(*)+x;Eh`H^tfq34GX_;3U6 zB?tTy^}u6JqUUHhS6&0cr6%eTnAmk`UB}>qnzqZukDkOASGSyEG&6t6dVF*Pjha$w z4ol8O_&?pp%D@Srft$AHvZf<2cqyFw$E)G;_#s?sA`EcsiR|<oH*2_8)oi|7+0=cf zqA`K-y5y{%iEf}yQ!dvm9Lfi$(*cKT37*fLK!pb5^;NhmGYHk~$4c+<Fh{u5L>Lfo z+;QwUmYe1mn(EEB%WAJMCNqD_dRue@HJWldXW`VR5bDapYDW$nb{hhH1qfAS!R~S+ z(0^9CCT9l1r6$4v$DhJ8AL7^t*m*oRFS=P$GsGCfyo7Z#zb8i;sM3_(F$24mqkWc! zP-{AD)*o<>wE!j!j=4#AM~cFC!8P>;!lfp{0B?H|C-9D)4zuF~c7BqZn;BD?UtnD> zWOn33RH-SeeHs?02Ug20tonR-t?P@he|rzzW@CLG_Gzv;8R1eB@er-u{v@7tqO8RP zJI`c{;~hw3J(J(#BA?>QeG9Jf)@9u`h0Q>?qS>yecsE)z3Sr{gUaF~0fn3pub~_Bj p5__Z@8R^D<$K;SJ8qsdmz)uUW$2a}EvC#kk002ovPDHLkV1k%7iwOV#
--- a/config/rules.mk +++ b/config/rules.mk @@ -955,20 +955,20 @@ ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH)) ifdef MSMANIFEST_TOOL @if test -f $@.manifest; then \ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ rm -f $@.manifest; \ fi endif # MSVC with manifest tool else ifeq ($(CPP_PROG_LINK),1) - $(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) + $(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) @$(call CHECK_STDCXX,$@) else - $(EXPAND_CC) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) + $(EXPAND_CC) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(LIBS_DIR) $(LIBS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) endif # CPP_PROG_LINK endif # WINNT && !GNU_CC ifdef ENABLE_STRIP $(STRIP) $@ endif ifdef MOZ_POST_PROGRAM_COMMAND $(MOZ_POST_PROGRAM_COMMAND) $@
--- a/configure.in +++ b/configure.in @@ -4926,16 +4926,20 @@ MOZ_ARG_HEADER(Toolkit Options) then dnl nglayout only supports building with one toolkit, dnl so ignore everything after the first comma (","). MOZ_WIDGET_TOOLKIT=`echo "$_DEFAULT_TOOLKIT" | sed -e "s/,.*$//"` else 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 ======================================================== case "$MOZ_WIDGET_TOOLKIT" in cairo-windows) MOZ_WIDGET_TOOLKIT=windows @@ -4960,26 +4964,27 @@ cairo-gtk2|cairo-gtk2-x11) AC_DEFINE(MOZ_WIDGET_GTK2) MOZ_PDF_PRINTING=1 MOZ_INSTRUMENT_EVENT_LOOP=1 ;; 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) MOZ_PDF_PRINTING=1 ;; cairo-os2) MOZ_WIDGET_TOOLKIT=os2 @@ -8838,16 +8843,19 @@ if test "$ac_cv___posix_fallocate" = tru AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) 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 ==================================================== _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $XCFLAGS" AC_TRY_COMPILE([ #include <stdio.h> #include <stdlib.h>
new file mode 100644 --- /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_ */
--- a/content/base/public/Makefile.in +++ b/content/base/public/Makefile.in @@ -74,35 +74,38 @@ nsContentCreatorFunctions.h \ nsDOMFile.h \ nsLineBreaker.h \ nsReferencedElement.h \ nsTreeSanitizer.h \ 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) XPIDLSRCS = \ nsIContentPolicy.idl \ nsIDocumentEncoder.idl \ nsIDOMFile.idl \ nsIDOMFileReader.idl \ nsIDOMFileList.idl \ nsIDOMFileException.idl \ - nsIDOMFileError.idl \ nsIDOMFormData.idl \ nsIDOMParser.idl \ nsIDOMSerializer.idl \ nsISelectionController.idl \ nsISelectionDisplay.idl \ nsISelectionListener.idl \ nsISelectionPrivate.idl \ nsIScriptLoaderObserver.idl \
--- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1614,17 +1614,53 @@ public: static JSContext *GetCurrentJSContext(); /** * Case insensitive comparison between two strings. However it only ignores * 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<int N> + static inline bool + EqualsLiteralIgnoreASCIICase(const nsAString& aStr1, + const char (&aStr2)[N]) + { + return EqualsLiteralIgnoreASCIICase(aStr1, aStr2, N-1); + } + template<int N> + 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. */ static void ASCIIToLower(nsAString& aStr); static void ASCIIToLower(const nsAString& aSource, nsAString& aDest); /**
--- a/content/base/public/nsDOMFile.h +++ b/content/base/public/nsDOMFile.h @@ -38,33 +38,33 @@ #ifndef nsDOMFile_h__ #define nsDOMFile_h__ #include "nsICharsetDetectionObserver.h" #include "nsIFile.h" #include "nsIDOMFile.h" #include "nsIDOMFileList.h" -#include "nsIDOMFileError.h" #include "nsIInputStream.h" #include "nsIJSNativeInitializer.h" #include "nsIMutable.h" #include "nsCOMArray.h" #include "nsCOMPtr.h" #include "nsString.h" #include "nsIXMLHttpRequest.h" #include "prmem.h" #include "nsAutoPtr.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" -#include "mozilla/GuardObjects.h" -#include "mozilla/StandardInteger.h" - class nsIFile; class nsIInputStream; class nsIClassInfo; class nsIBlobBuilder; nsresult NS_NewBlobBuilder(nsISupports* *aSupports); class nsDOMFileBase : public nsIDOMFile, @@ -358,28 +358,16 @@ public: return static_cast<nsDOMFileList*>(aSupports); } private: nsCOMArray<nsIDOMFile> 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 MOZ_GUARD_OBJECT_NOTIFIER_PARAM); ~nsDOMFileInternalUrlHolder(); nsAutoString mUrl; private: MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
deleted file mode 100644 --- 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; -};
--- a/content/base/public/nsIDOMFileReader.idl +++ b/content/base/public/nsIDOMFileReader.idl @@ -34,19 +34,19 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsIDOMEventTarget.idl" 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] void readAsArrayBuffer(in nsIDOMBlob filedata); void readAsBinaryString(in nsIDOMBlob filedata); void readAsText(in nsIDOMBlob filedata, [optional] in DOMString encoding); void readAsDataURL(in nsIDOMBlob file); @@ -54,17 +54,17 @@ interface nsIDOMFileReader : nsIDOMEvent const unsigned short EMPTY = 0; const unsigned short LOADING = 1; const unsigned short DONE = 2; readonly attribute unsigned short readyState; [implicit_jscontext] readonly attribute jsval result; - readonly attribute nsIDOMFileError error; + readonly attribute nsIDOMDOMError error; attribute nsIDOMEventListener onloadstart; attribute nsIDOMEventListener onprogress; attribute nsIDOMEventListener onload; attribute nsIDOMEventListener onabort; attribute nsIDOMEventListener onerror; attribute nsIDOMEventListener onloadend; };
--- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -1419,17 +1419,18 @@ public: * If this document is a static clone, this returns the original * document. */ nsIDocument* GetOriginalDocument() { return mOriginalDocument; } /** * 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; /** * Called by nsParser to preload style sheets. Can also be merged into * the parser if and when the parser is merged with libgklayout. */
--- a/content/base/public/nsIScriptElement.h +++ b/content/base/public/nsIScriptElement.h @@ -42,16 +42,17 @@ #include "nsISupports.h" #include "nsIURI.h" #include "nsCOMPtr.h" #include "nsIScriptLoaderObserver.h" #include "nsWeakPtr.h" #include "nsIParser.h" #include "nsContentCreatorFunctions.h" #include "nsIDOMHTMLScriptElement.h" +#include "mozilla/CORSMode.h" #define NS_ISCRIPTELEMENT_IID \ { 0x24ab3ff2, 0xd75e, 0x4be4, \ { 0x8d, 0x50, 0xd6, 0x75, 0x31, 0x29, 0xab, 0x65 } } /** * Internal interface implemented by script elements */ @@ -253,16 +254,25 @@ public: if (!mAlreadyStarted) { // Need to lose parser-insertedness here to allow another script to cause // execution later. LoseParserInsertedness(); } 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 * contains a script. Once it has been evaluated there is no way to make it * reevaluate the script, you'll have to create a new element. This also means * that when adding a src attribute to an element that already contains an * inline script, the script referenced by the src attribute will not be * loaded.
--- a/content/base/src/FileIOObject.cpp +++ b/content/base/src/FileIOObject.cpp @@ -114,23 +114,23 @@ FileIOObject::ClearProgressEventTimer() } void 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; } // Dispatch error event to signify load failure DispatchProgressEvent(NS_LITERAL_STRING(ERROR_STR)); DispatchProgressEvent(finalEvent); } @@ -253,24 +253,27 @@ FileIOObject::OnStopRequest(nsIRequest* DispatchProgressEvent(termEvent); return NS_OK; } 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); // Dispatch the events DispatchProgressEvent(NS_LITERAL_STRING(ABORT_STR)); DispatchProgressEvent(finalEvent); @@ -280,16 +283,16 @@ FileIOObject::Abort() NS_IMETHODIMP FileIOObject::GetReadyState(PRUint16 *aReadyState) { *aReadyState = mReadyState; return NS_OK; } NS_IMETHODIMP -FileIOObject::GetError(nsIDOMFileError** aError) +FileIOObject::GetError(nsIDOMDOMError** aError) { NS_IF_ADDREF(*aError = mError); return NS_OK; } } // namespace dom } // namespace mozilla
--- a/content/base/src/FileIOObject.h +++ b/content/base/src/FileIOObject.h @@ -40,18 +40,19 @@ #include "nsIDOMEventTarget.h" #include "nsDOMEventTargetHelper.h" #include "nsIChannel.h" #include "nsIFile.h" #include "nsIDOMFile.h" #include "nsIStreamListener.h" #include "nsITimer.h" +#include "nsCOMPtr.h" -#include "nsCOMPtr.h" +#include "mozilla/dom/DOMError.h" #define NS_PROGRESS_EVENT_INTERVAL 50 namespace mozilla { namespace dom { extern const PRUint64 kUnknownSize; @@ -64,17 +65,17 @@ class FileIOObject : public nsDOMEventTa public: FileIOObject(); NS_DECL_ISUPPORTS_INHERITED // 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); NS_DECL_AND_IMPL_EVENT_HANDLER(progress); NS_DECL_NSITIMERCALLBACK NS_DECL_NSISTREAMLISTENER @@ -103,17 +104,17 @@ protected: void ClearProgressEventTimer(); void DispatchError(nsresult rv, nsAString& finalEvent); nsresult DispatchProgressEvent(const nsAString& aType); nsCOMPtr<nsITimer> mProgressNotifier; bool mProgressEventWasDelayed; bool mTimerIsActive; - nsCOMPtr<nsIDOMFileError> mError; + nsCOMPtr<nsIDOMDOMError> mError; nsCOMPtr<nsIChannel> mChannel; PRUint16 mReadyState; PRUint64 mTotal; PRUint64 mTransferred; };
--- a/content/base/src/nsAttrValue.cpp +++ b/content/base/src/nsAttrValue.cpp @@ -709,17 +709,17 @@ nsAttrValue::GetEnumString(nsAString& aR PRInt16 val = allEnumBits >> NS_ATTRVALUE_ENUMTABLEINDEX_BITS; const EnumTable* table = sEnumTableArray-> ElementAt(allEnumBits & NS_ATTRVALUE_ENUMTABLEINDEX_MASK); while (table->tag) { if (table->value == val) { aResult.AssignASCII(table->tag); if (!aRealTag && allEnumBits & NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER) { - ToUpperCase(aResult); + nsContentUtils::ASCIIToUpper(aResult); } return; } table++; } NS_NOTREACHED("couldn't find value in EnumTable"); } @@ -1311,17 +1311,17 @@ nsAttrValue::ParseEnumValue(const nsAStr if (aCaseSensitive ? aValue.EqualsASCII(tableEntry->tag) : aValue.LowerCaseEqualsASCII(tableEntry->tag)) { PRInt32 value = EnumTableEntryToValue(aTable, tableEntry); bool equals = aCaseSensitive || aValue.EqualsASCII(tableEntry->tag); 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; } } SetIntValueAndType(value, eEnum, equals ? nsnull : &aValue); NS_ASSERTION(GetEnumValue() == tableEntry->value, "failed to store enum properly");
--- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -612,18 +612,19 @@ nsContentSink::ProcessLinkHeader(nsICont if (type.IsEmpty()) { type = value; type.StripWhitespace(); } } else if (attr.LowerCaseEqualsLiteral("media")) { 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()) { anchor = value; anchor.StripWhitespace(); } } } @@ -752,29 +753,29 @@ nsContentSink::ProcessMETATag(nsIContent // set any HTTP-EQUIV data into document's header data as well as url nsAutoString header; aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, header); if (!header.IsEmpty()) { nsAutoString result; aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result); if (!result.IsEmpty()) { - ToLowerCase(header); + nsContentUtils::ASCIIToLower(header); nsCOMPtr<nsIAtom> fieldAtom(do_GetAtom(header)); rv = ProcessHeaderData(fieldAtom, result, aContent); } } NS_ENSURE_SUCCESS(rv, rv); if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, nsGkAtoms::handheldFriendly, eIgnoreCase)) { nsAutoString result; aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result); if (!result.IsEmpty()) { - ToLowerCase(result); + nsContentUtils::ASCIIToLower(result); mDocument->SetHeaderData(nsGkAtoms::handheldFriendly, result); } } return rv; }
--- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -5388,16 +5388,17 @@ nsContentUtils::ASCIIToUpper(const nsASt *dest = (c >= 'a' && c <= 'z') ? c + ('A' - 'a') : c; ++iter; ++dest; } } } +/* static */ bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, const nsAString& aStr2) { PRUint32 len = aStr1.Length(); if (len != aStr2.Length()) { return false; } @@ -5410,32 +5411,70 @@ nsContentUtils::EqualsIgnoreASCIICase(co 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 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 // the same ascii char, but just differing in case PRUnichar c1Upper = c1 & 0xffdf; if (!('A' <= c1Upper && c1Upper <= 'Z')) { return false; } } } 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() { if (!sSameOriginChecker) { sSameOriginChecker = new nsSameOriginChecker(); NS_IF_ADDREF(sSameOriginChecker); } return sSameOriginChecker;
--- a/content/base/src/nsDOMAttribute.cpp +++ b/content/base/src/nsDOMAttribute.cpp @@ -205,21 +205,21 @@ nsDOMAttribute::GetName(nsAString& aName already_AddRefed<nsIAtom> nsDOMAttribute::GetNameAtom(nsIContent* aContent) { nsIAtom* result = nsnull; if (!mNsAware && mNodeInfo->NamespaceID() == kNameSpaceID_None && aContent->IsInHTMLDocument() && aContent->IsHTML()) { - nsAutoString name; - mNodeInfo->NameAtom()->ToString(name); - nsAutoString lower; - ToLowerCase(name, lower); - nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(lower); + nsString name; + mNodeInfo->GetName(name); + nsAutoString lowercaseName; + nsContentUtils::ASCIIToLower(name, lowercaseName); + nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(lowercaseName); nameAtom.swap(result); } else { nsCOMPtr<nsIAtom> nameAtom = mNodeInfo->NameAtom(); nameAtom.swap(result); } return result; }
--- a/content/base/src/nsDOMAttributeMap.cpp +++ b/content/base/src/nsDOMAttributeMap.cpp @@ -330,19 +330,17 @@ nsDOMAttributeMap::SetNamedItemInternal( ni = mContent->GetExistingAttrNameFromQName(name); if (ni) { rv = RemoveAttribute(ni, getter_AddRefs(tmpReturn)); NS_ENSURE_SUCCESS(rv, rv); } else { if (mContent->IsInHTMLDocument() && mContent->IsHTML()) { - nsAutoString lower; - ToLowerCase(name, lower); - name = lower; + nsContentUtils::ASCIIToLower(name); } rv = mContent->NodeInfo()->NodeInfoManager()-> GetNodeInfo(name, nsnull, kNameSpaceID_None, nsIDOMNode::ATTRIBUTE_NODE, getter_AddRefs(ni)); NS_ENSURE_SUCCESS(rv, rv); // value is already empty }
--- a/content/base/src/nsDOMFile.cpp +++ b/content/base/src/nsDOMFile.cpp @@ -628,37 +628,16 @@ NS_IMETHODIMP nsDOMFileList::Item(PRUint32 aIndex, nsIDOMFile **aFile) { NS_IF_ADDREF(*aFile = GetItemAt(aIndex)); 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 nsDOMFileInternalUrlHolder::nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; aFile->GetInternalUrl(aPrincipal, mUrl); }
--- a/content/base/src/nsDOMFileReader.cpp +++ b/content/base/src/nsDOMFileReader.cpp @@ -250,17 +250,17 @@ nsDOMFileReader::GetResult(JSContext* aC nsString tmpResult = mResult; if (!xpc::StringToJsval(aCx, tmpResult, aResult)) { return NS_ERROR_FAILURE; } return NS_OK; } NS_IMETHODIMP -nsDOMFileReader::GetError(nsIDOMFileError** aError) +nsDOMFileReader::GetError(nsIDOMDOMError** aError) { return FileIOObject::GetError(aError); } NS_IMETHODIMP nsDOMFileReader::ReadAsArrayBuffer(nsIDOMBlob* aFile, JSContext* aCx) { return ReadFileContent(aCx, aFile, EmptyString(), FILE_AS_ARRAYBUFFER);
--- a/content/base/src/nsDOMFileReader.h +++ b/content/base/src/nsDOMFileReader.h @@ -49,17 +49,16 @@ #include "prtime.h" #include "nsITimer.h" #include "nsICharsetDetector.h" #include "nsICharsetDetectionObserver.h" #include "nsIDOMFile.h" #include "nsIDOMFileReader.h" #include "nsIDOMFileList.h" -#include "nsIDOMFileError.h" #include "nsIInputStream.h" #include "nsCOMPtr.h" #include "nsIStreamLoader.h" #include "nsIChannel.h" #include "prmem.h" #include "FileIOObject.h"
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3242,24 +3242,37 @@ nsDocument::MaybeRescheduleAnimationFram void nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks) { aCallbacks.AppendElements(mFrameRequestCallbacks); mFrameRequestCallbacks.Clear(); } +PLDHashOperator RequestDiscardEnumerator(imgIRequest* aKey, + PRUint32 aData, + void* userArg) +{ + aKey->RequestDiscard(); + return PL_DHASH_NEXT; +} + void nsDocument::DeleteShell() { mExternalResourceMap.HideViewers(); if (IsEventHandlingEnabled()) { 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; } void nsDocument::RevokeAnimationFrameNotifications() { if (!mFrameRequestCallbacks.IsEmpty()) { mPresShell->GetPresContext()->RefreshDriver()-> @@ -4409,17 +4422,17 @@ nsDocument::CreateElement(const nsAStrin *aReturn = nsnull; nsresult rv = nsContentUtils::CheckQName(aTagName, false); NS_ENSURE_SUCCESS(rv, rv); bool needsLowercase = IsHTML() && !IsLowercaseASCII(aTagName); nsAutoString lcTagName; if (needsLowercase) { - ToLowerCase(aTagName, lcTagName); + nsContentUtils::ASCIIToLower(aTagName, lcTagName); } rv = CreateElem(needsLowercase ? lcTagName : aTagName, nsnull, mDefaultElementType, aReturn); return rv; } NS_IMETHODIMP @@ -7719,24 +7732,30 @@ nsDocument::MaybePreLoadImage(nsIURI* ur PRInt16 blockingStatus; if (nsContentUtils::IsImageInCache(uri) || !nsContentUtils::CanLoadImage(uri, static_cast<nsIDocument *>(this), this, NodePrincipal(), &blockingStatus)) { return; } 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; - } - // 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. + break; + default: + /* should never happen */ + MOZ_NOT_REACHED("Unknown CORS mode!"); + } // Image not in cache - trigger preload nsCOMPtr<imgIRequest> request; nsresult rv = nsContentUtils::LoadImage(uri, this, NodePrincipal(), mDocumentURI, // uri of document used as referrer @@ -8304,36 +8323,42 @@ nsDocument::RemoveImage(imgIRequest* aIm NS_ABORT_IF_FALSE(found, "Removing image that wasn't in the tracker!"); NS_ABORT_IF_FALSE(count > 0, "Entry in the cache tracker with count 0!"); // We're removing, so decrement the count. count--; // 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; } PLDHashOperator LockEnumerator(imgIRequest* aKey, PRUint32 aData, void* userArg) { aKey->LockImage();
--- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -154,16 +154,18 @@ #include "nsSVGFeatures.h" #include "nsWrapperCacheInlines.h" #include "nsCycleCollector.h" #include "xpcpublic.h" #include "xpcprivate.h" #include "nsLayoutStatics.h" #include "mozilla/Telemetry.h" +#include "mozilla/CORSMode.h" + using namespace mozilla; using namespace mozilla::dom; NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID); PRInt32 nsIContent::sTabFocusModel = eTabFocus_any; bool nsIContent::sTabFocusModelAppliesToXUL = false; PRUint32 nsMutationGuard::sMutationCount = 0; @@ -2848,25 +2850,26 @@ nsresult nsGenericElement::GetAttributeNS(const nsAString& aNamespaceURI, const nsAString& aLocalName, nsAString& aReturn) { PRInt32 nsid = 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<nsIAtom> name = do_GetAtom(aLocalName); - GetAttr(nsid, name, aReturn); + bool hasAttr = GetAttr(nsid, name, aReturn); + if (!hasAttr) { + SetDOMStringToNull(aReturn); + } return NS_OK; } nsresult nsGenericElement::SetAttributeNS(const nsAString& aNamespaceURI, const nsAString& aQualifiedName, const nsAString& aValue) @@ -6230,16 +6233,58 @@ nsINode::SizeOfExcludingThis(nsMallocSiz size_t nsGenericElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const { return Element::SizeOfExcludingThis(aMallocSizeOf) + 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<bool> 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); \ if (elm) { \ elm->GetJSEventListener(nsGkAtoms::on##name_, vp); \ } else { \ *vp = JSVAL_NULL; \ } \
--- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -60,16 +60,17 @@ #include "nsIDOMNodeSelector.h" #include "nsIDOMXPathNSResolver.h" #include "nsPresContext.h" #include "nsIDOMDOMStringMap.h" #include "nsContentList.h" #include "nsDOMClassInfoID.h" // DOMCI_DATA #include "nsIDOMTouchEvent.h" #include "nsIInlineEventHandlers.h" +#include "mozilla/CORSMode.h" #include "nsISMILAttr.h" class nsIDOMAttr; class nsIDOMEventListener; class nsIFrame; class nsIDOMNamedNodeMap; class nsICSSDeclaration; @@ -635,16 +636,35 @@ public: static bool CanSkipInCC(nsINode* aNode); static bool CanSkipThis(nsINode* aNode); static void MarkNodeChildren(nsINode* aNode); static void InitCCCallbacks(); static void MarkUserData(void* aObject, nsIAtom* aKey, void* aChild, 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 * read. */ static const bool kFireMutationEvent = true; static const bool kDontFireMutationEvent = false; static const bool kNotifyDocumentObservers = true;
--- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -1999,18 +1999,20 @@ GK_ATOM(mixed, "mixed") GK_ATOM(multiline, "multiline") GK_ATOM(password, "password") GK_ATOM(posinset, "posinset") GK_ATOM(select1, "select1") 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") GK_ATOM(toolbarspacer, "toolbarspacer") GK_ATOM(toolbarspring, "toolbarspring") GK_ATOM(_undefined, "undefined") GK_ATOM(xmlroles, "xml-roles") #endif
--- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -55,17 +55,17 @@ #include "nsContentPolicyUtils.h" #include "nsIURI.h" #include "nsILoadGroup.h" #include "imgIContainer.h" #include "imgILoader.h" #include "nsThreadUtils.h" #include "nsNetUtil.h" #include "nsAsyncDOMEvent.h" -#include "nsGenericHTMLElement.h" +#include "nsGenericElement.h" #include "nsIPresShell.h" #include "nsEventStates.h" #include "nsGUIEvent.h" #include "nsIChannel.h" #include "nsIStreamListener.h" @@ -77,16 +77,18 @@ #include "nsIContentPolicy.h" #include "nsContentPolicyUtils.h" #include "nsEventDispatcher.h" #include "nsSVGEffects.h" #include "mozAutoDocUpdate.h" #include "mozilla/dom/Element.h" +using namespace mozilla; + #ifdef DEBUG_chb static void PrintReqURL(imgIRequest* req) { if (!req) { printf("(null req)\n"); return; } nsCOMPtr<nsIURI> uri; @@ -770,19 +772,19 @@ nsImageLoadingContent::LoadImage(nsIURI* if (!NS_CP_ACCEPTED(cpDecision)) { FireEvent(NS_LITERAL_STRING("error")); SetBlockedRequest(aNewURI, cpDecision); return NS_OK; } 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; } // Not blocked. Do the load. nsCOMPtr<imgIRequest>& req = PrepareNextRequest(); nsresult rv; rv = nsContentUtils::LoadImage(aNewURI, aDocument, aDocument->NodePrincipal(), @@ -1182,13 +1184,13 @@ nsImageLoadingContent::CreateStaticImage aDest->mStateChangerDepth = mStateChangerDepth; aDest->mIsImageStateForced = mIsImageStateForced; aDest->mLoading = mLoading; aDest->mBroken = mBroken; aDest->mUserDisabled = mUserDisabled; aDest->mSuppressed = mSuppressed; } -nsGenericHTMLElement::CORSMode +CORSMode nsImageLoadingContent::GetCORSMode() { - return nsGenericHTMLElement::CORS_NONE; + return CORS_NONE; }
--- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -49,16 +49,17 @@ #include "nsINode.h" #include "imgIRequest.h" #include "prtypes.h" #include "nsCOMPtr.h" #include "nsContentUtils.h" // NS_CONTENT_DELETE_LIST_MEMBER #include "nsString.h" #include "nsEventStates.h" #include "nsGenericHTMLElement.h" +#include "mozilla/CORSMode.h" class nsIURI; class nsIDocument; class imgILoader; class nsIIOService; class nsImageLoadingContent : public nsIImageLoadingContent { @@ -178,17 +179,17 @@ protected: // Sets blocking state only if the desired state is different from the // current one. See the comment for mBlockingOnload for more information. void SetBlockingOnload(bool aBlocking); /** * 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: /** * Struct used to manage the image observers. */ struct ImageObserver { ImageObserver(imgIDecoderObserver* aObserver) : mObserver(aObserver),
--- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -69,37 +69,44 @@ #include "nsThreadUtils.h" #include "nsDocShellCID.h" #include "nsIContentSecurityPolicy.h" #include "prlog.h" #include "nsIChannelPolicy.h" #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; ////////////////////////////////////////////////////////////// // Per-request data structure ////////////////////////////////////////////////////////////// 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) { } NS_DECL_ISUPPORTS void FireScriptAvailable(nsresult aResult) { mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo); @@ -117,16 +124,17 @@ public: nsCOMPtr<nsIScriptElement> mElement; bool mLoading; // Are we still waiting for a load to complete? bool mIsInline; // Is the script inline or loaded? nsString mScriptText; // Holds script for loaded scripts PRUint32 mJSVersion; nsCOMPtr<nsIURI> mURI; nsCOMPtr<nsIPrincipal> mOriginPrincipal; PRInt32 mLineNo; + const CORSMode mCORSMode; }; // The nsScriptLoadRequest is passed as the context to necko, and thus // it needs to be threadsafe. Necko won't do anything with this // context, but it will AddRef and Release it on other threads. NS_IMPL_THREADSAFE_ISUPPORTS0(nsScriptLoadRequest) ////////////////////////////////////////////////////////////// @@ -288,17 +296,16 @@ nsScriptLoader::StartLoad(nsScriptLoadRe ? static_cast<nsISupports *>(aRequest->mElement.get()) : static_cast<nsISupports *>(mDocument); nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType); if (NS_FAILED(rv)) { return rv; } nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup(); - nsCOMPtr<nsIStreamLoader> loader; nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->GetScriptGlobalObject())); if (!window) { return NS_ERROR_NULL_POINTER; } nsIDocShell *docshell = window->GetDocShell(); @@ -327,20 +334,31 @@ nsScriptLoader::StartLoad(nsScriptLoadRe if (httpChannel) { // HTTP content negotation has little value in this context. httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), NS_LITERAL_CSTRING("*/*"), false); httpChannel->SetReferrer(mDocument->GetDocumentURI()); } + nsCOMPtr<nsIStreamLoader> loader; rv = NS_NewStreamLoader(getter_AddRefs(loader), this); NS_ENSURE_SUCCESS(rv, rv); - rv = channel->AsyncOpen(loader, aRequest); + nsCOMPtr<nsIStreamListener> 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; } bool nsScriptLoader::PreloadURIComparator::Equals(const PreloadInfo &aPi, nsIURI * const &aURI) const @@ -546,42 +564,44 @@ nsScriptLoader::ProcessScriptElement(nsI nsRefPtr<nsScriptLoadRequest> request; if (aElement->GetScriptExternal()) { // external script nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI(); if (!scriptURI) { return false; } + CORSMode ourCORSMode = aElement->GetCORSMode(); nsTArray<PreloadInfo>::index_type i = mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator()); if (i != nsTArray<PreloadInfo>::NoIndex) { // preloaded // note that a script-inserted script can steal a preload! request = mPreloads[i].mRequest; request->mElement = aElement; nsString preloadCharset(mPreloads[i].mCharset); mPreloads.RemoveElementAt(i); // Double-check that the charset the preload used is the same as // 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 { // Drop the preload request = nsnull; } } 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; rv = StartLoad(request, type); NS_ENSURE_SUCCESS(rv, false); } request->mJSVersion = version; @@ -692,17 +712,18 @@ nsScriptLoader::ProcessScriptElement(nsI csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_INLINE_SCRIPT, NS_ConvertUTF8toUTF16(asciiSpec), scriptText, aElement->GetScriptLineNumber()); return false; } } - 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; request->mURI = mDocument->GetDocumentURI(); request->mLineNo = aElement->GetScriptLineNumber(); if (aElement->GetParserCreated() == FROM_PARSER_XSLT && (!ReadyToExecuteScripts() || !mXSLTRequests.IsEmpty())) { @@ -1223,19 +1244,24 @@ nsScriptLoader::PrepareLoadedRequest(nsS bool requestSucceeded; rv = httpChannel->GetRequestSucceeded(&requestSucceeded); if (NS_SUCCEEDED(rv) && !requestSucceeded) { return NS_ERROR_NOT_AVAILABLE; } } nsCOMPtr<nsIChannel> 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. nsAutoString hintCharset; if (!aRequest->IsPreload()) { aRequest->mElement->GetScriptCharset(hintCharset); } else { nsTArray<PreloadInfo>::index_type i = @@ -1320,24 +1346,27 @@ nsScriptLoader::ParsingComplete(bool aTe // Have to call this even if aTerminated so we'll correctly unblock // onload and all. ProcessPendingRequests(); } 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<nsScriptLoadRequest> request = new nsScriptLoadRequest(nsnull, 0); + nsRefPtr<nsScriptLoadRequest> request = + new nsScriptLoadRequest(nsnull, 0, + nsGenericElement::StringToCORSMode(aCrossOrigin)); request->mURI = aURI; request->mIsInline = false; request->mLoading = true; nsresult rv = StartLoad(request, aType); if (NS_FAILED(rv)) { return; }
--- a/content/base/src/nsScriptLoader.h +++ b/content/base/src/nsScriptLoader.h @@ -233,19 +233,22 @@ public: } /** * Adds aURI to the preload list and starts loading it. * * @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: /** * Unblocks the creator parser of the parser-blocking scripts. */ void UnblockParser(nsScriptLoadRequest* aParserBlockingRequest); /**
--- a/content/base/src/nsStyleLinkElement.cpp +++ b/content/base/src/nsStyleLinkElement.cpp @@ -180,32 +180,32 @@ PRUint32 nsStyleLinkElement::ParseLinkTy nsAString::const_iterator current(start); bool inString = !nsContentUtils::IsHTMLWhitespace(*current); nsAutoString subString; 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; } } else { if (!inString) { start = current; inString = true; } } ++current; } if (inString) { - ToLowerCase(Substring(start, current), subString); - linkMask |= ToLinkMask(subString); + nsContentUtils::ASCIIToLower(Substring(start, current), subString); + linkMask |= ToLinkMask(subString); } return linkMask; } NS_IMETHODIMP nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver, bool* aWillNotify, bool* aIsAlternate)
--- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -557,16 +557,21 @@ include $(topsrcdir)/config/rules.mk test_bug717511.html \ file_bug717511.html \ file_bug717511.html^headers^ \ file_bug717511_2.html \ file_bug717511_2.html^headers^ \ 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 = \ test_bug357450.js \ $(NULL) # This test fails on the Mac for some reason ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
copy from content/base/test/bug461735-post-redirect.js copy to content/base/test/bug696301-script-1.js --- a/content/base/test/bug461735-post-redirect.js +++ b/content/base/test/bug696301-script-1.js @@ -1,3 +1,3 @@ var a = 0; -var b = 0; +var global = "ran"; c(); \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/content/base/test/bug696301-script-1.js^headers^ @@ -0,0 +1,1 @@ +Access-Control-Allow-Origin: *
copy from content/base/test/bug461735-post-redirect.js copy to content/base/test/bug696301-script-2.js --- a/content/base/test/bug461735-post-redirect.js +++ b/content/base/test/bug696301-script-2.js @@ -1,3 +1,3 @@ var a = 0; -var b = 0; +var global = "ran"; c(); \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/content/base/test/test_bug696301-1.html @@ -0,0 +1,78 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=696301 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 696301</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696301">Mozilla Bug 696301</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> +var errorFired = false; +var global = ""; +window.onerror = function(message, uri, line) { + is(message, "Script error.", "Should have empty error message"); + is(uri, + "http://example.com/tests/content/base/test/bug696301-script-1.js", + "Should have correct script URI"); + is(line, 0, "Shouldn't have a line here"); + errorFired = true; +} +</script> +<script src="http://example.com/tests/content/base/test/bug696301-script-1.js"></script> +<script> + is(errorFired, true, "Should have error in different origin script"); + is(global, "ran", "Different origin script should have run"); +</script> + +<script type="application/javascript"> +errorFired = false; +global = ""; +window.onerror = function(message, uri, line) { + is(message, "c is not defined", "Should have correct error message"); + is(uri, + "http://example.com/tests/content/base/test/bug696301-script-1.js", + "Should also have correct script URI"); + is(line, 3, "Should have a line here"); + errorFired = true; +} +</script> +<script src="http://example.com/tests/content/base/test/bug696301-script-1.js" + crossorigin></script> +<script> + is(errorFired, true, "Should have error in different origin script with CORS"); + is(global, "ran", "Different origin script with CORS should have run"); +</script> + +<script type="application/javascript"> +errorFired = false; +global = ""; +window.onerror = function(message, uri, line) { + is(message, "Error loading script", "Should have correct error message"); + is(uri, + "http://example.com/tests/content/base/test/bug696301-script-2.js", + "Should still have correct script URI even when failing CORS"); + is(line, 1, "Load failures seem to count as line 1"); + errorFired = true; +} +</script> +<script src="http://example.com/tests/content/base/test/bug696301-script-2.js" + crossorigin></script> +<script> + is(errorFired, true, + "Should have error when different origin script fails CORS check"); + is(global, "", "Different origin script that fails CORS should not have run"); +</script> + +</pre> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/content/base/test/test_bug696301-2.html @@ -0,0 +1,80 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=696301 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 696301</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696301">Mozilla Bug 696301</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<!-- Test SVG script here --> +<svg> +<script type="application/javascript"> +var errorFired = false; +var global = ""; +window.onerror = function(message, uri, line) { + is(message, "Script error.", "Should have empty error message"); + is(uri, + "http://example.com/tests/content/base/test/bug696301-script-1.js", + "Should have correct script URI"); + is(line, 0, "Shouldn't have a line here"); + errorFired = true; +} +</script> +<script xlink:href="http://example.com/tests/content/base/test/bug696301-script-1.js"></script> +<script> + is(errorFired, true, "Should have error in different origin script"); + is(global, "ran", "Different origin script should have run"); +</script> + +<script type="application/javascript"> +errorFired = false; +global = ""; +window.onerror = function(message, uri, line) { + is(message, "c is not defined", "Should have correct error message"); + is(uri, + "http://example.com/tests/content/base/test/bug696301-script-1.js", + "Should also have correct script URI"); + is(line, 3, "Should have a line here"); + errorFired = true; +} +</script> +<script xlink:href="http://example.com/tests/content/base/test/bug696301-script-1.js" + crossorigin></script> +<script> + is(errorFired, true, "Should have error in different origin script with CORS"); + is(global, "ran", "Different origin script with CORS should have run"); +</script> + +<script type="application/javascript"> +errorFired = false; +global = ""; +window.onerror = function(message, uri, line) { + is(message, "Error loading script", "Should have correct error message"); + is(uri, + "http://example.com/tests/content/base/test/bug696301-script-2.js", + "Should still have correct script URI even when failing CORS"); + is(line, 1, "Load failures seem to count as line 1"); + errorFired = true; +} +</script> +<script xlink:href="http://example.com/tests/content/base/test/bug696301-script-2.js" + crossorigin></script> +<script> + is(errorFired, true, + "Should have error when different origin script fails CORS check"); + is(global, "", "Different origin script that fails CORS should not have run"); +</script> +</svg> +</pre> +</body> +</html>
--- a/content/canvas/crashtests/crashtests.list +++ b/content/canvas/crashtests/crashtests.list @@ -1,6 +1,7 @@ load 360293-1.html load 421715-1.html load 553938-1.html load 647480.html load 0px-size-font-667225.html +load texImage2D.html load 729116.html
new file mode 100644 --- /dev/null +++ b/content/canvas/crashtests/texImage2D.html @@ -0,0 +1,8 @@ +<!doctype html> +<canvas></canvas> +<script> +var canvas = document.body.firstChild, + gl = canvas.getContext("experimental-webgl"); +gl.texImage2D(0, 0, 0, 0, 0, { get width() { throw 7 }, get height() { throw 7 }, data: new Uint8ClampedArray(10) }); +gl.texSubImage2D(0, 0, 0, 0, 0, 0, { get width() { throw 7 }, get height() { throw 7 }, data: new Uint8ClampedArray(10) }); +</script>
--- a/content/canvas/src/CustomQS_WebGL.h +++ b/content/canvas/src/CustomQS_WebGL.h @@ -377,16 +377,143 @@ nsIDOMWebGLRenderingContext_ReadPixels(J if (NS_FAILED(rv)) return xpc_qsThrowMethodFailed(cx, rv, vp); *vp = JSVAL_VOID; return JS_TRUE; } +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<class T> +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<nsGenericElement>( + 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) * TexImage2D(uint, int, uint, uint, uint, nsIDOMElement) * TexImage2D(uint, int, uint, uint, uint, ImageData) */ static JSBool nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, unsigned argc, jsval *vp) @@ -407,75 +534,31 @@ nsIDOMWebGLRenderingContext_TexImage2D(J if (argc < 6 || argc == 7 || argc == 8) return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); jsval *argv = JS_ARGV(cx, 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<nsIDOMElement>(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); GET_UINT32_ARG(argv6, 6); GET_UINT32_ARG(argv7, 7); JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]); @@ -531,71 +614,27 @@ nsIDOMWebGLRenderingContext_TexSubImage2 jsval *argv = JS_ARGV(cx, vp); // arguments common to all cases GET_UINT32_ARG(argv0, 0); GET_INT32_ARG(argv1, 1); 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<nsIDOMElement>(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); GET_UINT32_ARG(argv6, 6); GET_UINT32_ARG(argv7, 7); JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]); // try to grab a js::TypedArray
--- a/content/canvas/src/WebGLContext.h +++ b/content/canvas/src/WebGLContext.h @@ -810,17 +810,17 @@ protected: WebGLint *intParamPtr, WebGLfloat *floatParamPtr); void ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride, const PRUint8*src, PRUint8 *dst, int srcFormat, bool srcPremultiplied, int dstFormat, bool dstPremultiplied, size_t dstTexelSize); - nsresult DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, + nsresult DOMElementToImageSurface(dom::Element* imageOrCanvas, gfxImageSurface **imageOut, int *format); nsresult CopyTexSubImage2D_base(WebGLenum target, WebGLint level, WebGLenum internalformat, WebGLint xoffset, WebGLint yoffset,
--- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -65,16 +65,17 @@ #include "WebGLValidateStrings.h" // needed to check if current OS is lower than 10.7 #if defined(MOZ_WIDGET_COCOA) #include "nsCocoaFeatures.h" #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); /* Helper macros for when we're just wrapping a gl method, so that * we can avoid having to type this 500 times. Note that these MUST * NOT BE USED if we need to check any of the parameters. */ @@ -3961,35 +3962,34 @@ WebGLContext::ConvertImage(size_t width, HANDLE_FLOAT_SRCFORMAT(A32F, 4, unpackA32FToRGBA32F) default: NS_ASSERTION(false, "Coding error?! Should never reach this point."); return; } } nsresult -WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas, +WebGLContext::DOMElementToImageSurface(Element* imageOrCanvas, gfxImageSurface **imageOut, int *format) { - nsCOMPtr<nsIContent> content = do_QueryInterface(imageOrCanvas); - if (!content) { + if (!imageOrCanvas) { return NS_ERROR_FAILURE; } PRUint32 flags = nsLayoutUtils::SFE_WANT_NEW_SURFACE | nsLayoutUtils::SFE_WANT_IMAGE_SURFACE; if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE) flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION; if (!mPixelStorePremultiplyAlpha) 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) { // SurfaceFromElement lied! return NS_ERROR_FAILURE; } // We disallow loading cross-domain images and videos that have not been validated @@ -4011,17 +4011,17 @@ WebGLContext::DOMElementToImageSurface(n "See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures"); return NS_ERROR_DOM_SECURITY_ERR; } } // 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 " "when a cross-domain image is drawn on it. " "See https://developer.mozilla.org/en/WebGL/Cross-Domain_Textures"); return NS_ERROR_DOM_SECURITY_ERR; } } @@ -5077,17 +5077,17 @@ WebGLContext::TexImage2D_imageData(WebGL pixels ? JS_GetTypedArrayData(pixels) : 0, pixels ? JS_GetTypedArrayByteLength(pixels) : 0, -1, WebGLTexelFormat::RGBA8, false); } 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; nsRefPtr<gfxImageSurface> isurf; int srcFormat; nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), &srcFormat); @@ -5267,17 +5267,17 @@ WebGLContext::TexSubImage2D_imageData(We -1, WebGLTexelFormat::RGBA8, false); } 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; nsRefPtr<gfxImageSurface> isurf; int srcFormat; nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf), &srcFormat);
--- a/content/canvas/test/test_canvas.html +++ b/content/canvas/test/test_canvas.html @@ -7586,67 +7586,67 @@ ok(!_thrown_outer, ctx.canvas.id + ' sho } </script> <!-- [[[ test_2d.imageData.create.type.html ]]] --> <p>Canvas test: 2d.imageData.create.type - bug 433004</p> -<!-- Testing: createImageData() returns an ImageData object containing a CanvasPixelArray object --> +<!-- Testing: createImageData() returns an ImageData object containing a Uint8ClampedArray object --> <canvas id="c261" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas> <script> function test_2d_imageData_create_type() { var canvas = document.getElementById('c261'); var ctx = canvas.getContext('2d'); var _thrown_outer = false; try { todo(window.ImageData !== undefined, "window.ImageData !== undefined"); -todo(window.CanvasPixelArray !== undefined, "window.CanvasPixelArray !== undefined"); +ok(window.Uint8ClampedArray !== undefined, "window.Uint8ClampedArray !== undefined"); window.ImageData.prototype.thisImplementsImageData = true; -window.CanvasPixelArray.prototype.thisImplementsCanvasPixelArray = true; +window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true; var imgdata = ctx.createImageData(1, 1); ok(imgdata.thisImplementsImageData, "imgdata.thisImplementsImageData"); -ok(imgdata.data.thisImplementsCanvasPixelArray, "imgdata.data.thisImplementsCanvasPixelArray"); +ok(imgdata.data.thisImplementsUint8ClampedArray, "imgdata.data.thisImplementsUint8ClampedArray"); } catch (e) { _thrown_outer = true; } todo(!_thrown_outer, ctx.canvas.id + ' should not throw exception'); } </script> <!-- [[[ test_2d.imageData.create1.type.html ]]] --> <p>Canvas test: 2d.imageData.create1.type - bug 630040</p> -<!-- Testing: createImageData(imgdata) returns an ImageData object containing a CanvasPixelArray object --> +<!-- Testing: createImageData(imgdata) returns an ImageData object containing a Uint8ClampedArray object --> <canvas id="c261a" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas> <script> function test_2d_imageData_create1_type() { var canvas = document.getElementById('c261a'); var ctx = canvas.getContext('2d'); var _thrown_outer = false; try { todo(window.ImageData !== undefined, "window.ImageData !== undefined"); -todo(window.CanvasPixelArray !== undefined, "window.CanvasPixelArray !== undefined"); +ok(window.Uint8ClampedArray !== undefined, "window.Uint8ClampedArray !== undefined"); window.ImageData.prototype.thisImplementsImageData = true; -window.CanvasPixelArray.prototype.thisImplementsCanvasPixelArray = true; +window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true; var imgdata = ctx.createImageData(ctx.createImageData(1, 1)); todo(imgdata.thisImplementsImageData, "imgdata.thisImplementsImageData"); -todo(imgdata.data.thisImplementsCanvasPixelArray, "imgdata.data.thisImplementsCanvasPixelArray"); +ok(imgdata.data.thisImplementsUint8ClampedArray, "imgdata.data.thisImplementsUint8ClampedArray"); } catch (e) { _thrown_outer = true; } todo(!_thrown_outer, ctx.canvas.id + ' should not throw exception'); } @@ -8224,35 +8224,35 @@ ok(!_thrown_outer, ctx.canvas.id + ' sho } </script> <!-- [[[ test_2d.imageData.get.type.html ]]] --> <p>Canvas test: 2d.imageData.get.type</p> -<!-- Testing: getImageData() returns an ImageData object containing a CanvasPixelArray object --> +<!-- Testing: getImageData() returns an ImageData object containing a Uint8ClampedArray object --> <canvas id="c276" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas> <script> function test_2d_imageData_get_type() { var canvas = document.getElementById('c276'); var ctx = canvas.getContext('2d'); var _thrown_outer = false; try { todo(window.ImageData !== undefined, "window.ImageData !== undefined"); -todo(window.CanvasPixelArray !== undefined, "window.CanvasPixelArray !== undefined"); +ok(window.Uint8ClampedArray !== undefined, "window.Uint8ClampedArray !== undefined"); window.ImageData.prototype.thisImplementsImageData = true; -window.CanvasPixelArray.prototype.thisImplementsCanvasPixelArray = true; +window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true; var imgdata = ctx.getImageData(0, 0, 1, 1); ok(imgdata.thisImplementsImageData, "imgdata.thisImplementsImageData"); -ok(imgdata.data.thisImplementsCanvasPixelArray, "imgdata.data.thisImplementsCanvasPixelArray"); +ok(imgdata.data.thisImplementsUint8ClampedArray, "imgdata.data.thisImplementsUint8ClampedArray"); } catch (e) { _thrown_outer = true; } todo(!_thrown_outer, ctx.canvas.id + ' should not throw exception'); }
--- a/content/events/crashtests/crashtests.list +++ b/content/events/crashtests/crashtests.list @@ -1,10 +1,11 @@ load 104310-1.html load 116206-1.html load 135345-1.html load 422009-1.xhtml load 457776-1.html load 496308-1.html load 682637-1.html load eventctor-nulldictionary.html +load eventctor-nullstorage.html load recursive-onload.html load recursive-DOMNodeInserted.html
new file mode 100644 --- /dev/null +++ b/content/events/crashtests/eventctor-nullstorage.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<script> +new StorageEvent("").storageArea; +</script>
--- a/content/html/content/public/nsHTMLMediaElement.h +++ b/content/html/content/public/nsHTMLMediaElement.h @@ -45,16 +45,17 @@ #include "nsIHttpChannel.h" #include "nsThreadUtils.h" #include "nsIDOMRange.h" #include "nsCycleCollectionParticipant.h" #include "nsILoadGroup.h" #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 */ typedef PRUint16 nsMediaNetworkState; typedef PRUint16 nsMediaReadyState; class nsHTMLMediaElement : public nsGenericHTMLElement, @@ -66,17 +67,17 @@ public: typedef mozilla::VideoFrameContainer VideoFrameContainer; enum CanPlayStatus { CANPLAY_NO, CANPLAY_MAYBE, CANPLAY_YES }; - CORSMode GetCORSMode() { + mozilla::CORSMode GetCORSMode() { return mCORSMode; } nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo); virtual ~nsHTMLMediaElement(); /** * This is used when the browser is constructing a video element to play @@ -776,12 +777,12 @@ protected: // load when the user initiates either playback or an explicit load is // stored in mPreloadURI. bool mLoadIsSuspended; // True if a same-origin check has been done for the media element and resource. bool mMediaSecurityVerified; // The CORS mode when loading the media element - CORSMode mCORSMode; + mozilla::CORSMode mCORSMode; }; #endif
--- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -2483,34 +2483,35 @@ nsGenericHTMLElement::GetContentEditable } return NS_OK; } 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; } - - SetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, contentEditable, - true); - - return NS_OK; + + if (nsContentUtils::EqualsLiteralIgnoreASCIICase(aContentEditable, "false")) { + SetAttr(kNameSpaceID_None, nsGkAtoms::contenteditable, NS_LITERAL_STRING("false"), true); + + return NS_OK; + } + + return NS_ERROR_DOM_SYNTAX_ERR; } nsresult nsGenericHTMLElement::GetIsContentEditable(bool* aContentEditable) { NS_ENSURE_ARG_POINTER(aContentEditable); for (nsIContent* node = this; node; node = node->GetParent()) { @@ -2881,24 +2882,16 @@ nsGenericHTMLFormElement::PreHandleEvent break; } } } 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 { return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled) || (mFieldSet && mFieldSet->IsDisabled()); }
--- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -525,50 +525,24 @@ public: * @param aResult result value [out] */ NS_HIDDEN_(nsresult) GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& aResult); /** * Returns the current disabled state of the element. */ virtual bool IsDisabled() const { - return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled); + return false; } bool IsHidden() const { 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 */ void AddToNameTable(nsIAtom* aName) { NS_ASSERTION(HasName(), "Node doesn't have name?"); nsIDocument* doc = GetCurrentDoc(); if (doc && !IsInAnonymousSubtree()) {
--- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -358,20 +358,18 @@ nsHTMLImageElement::ParseAttribute(PRInt const nsAString& aValue, nsAttrValue& aResult) { if (aNamespaceID == kNameSpaceID_None) { if (aAttribute == nsGkAtoms::align) { 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; } } return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, aResult); @@ -657,22 +655,13 @@ nsresult nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const { if (aDest->OwnerDoc()->IsStaticDocument()) { CreateStaticImageClone(static_cast<nsHTMLImageElement*>(aDest)); } 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)); }
--- a/content/html/content/src/nsHTMLLinkElement.cpp +++ b/content/html/content/src/nsHTMLLinkElement.cpp @@ -431,17 +431,19 @@ nsHTMLLinkElement::GetStyleSheetInfo(nsA if (aTitle.IsEmpty()) { // alternates must have title return; } else { *aIsAlternate = true; } } 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; GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType); nsContentUtils::SplitMimeType(aType, mimeType, notUsed); if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) { return; }
--- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -946,24 +946,17 @@ nsresult nsHTMLMediaElement::LoadResourc } if (mChannel) { mChannel->Cancel(NS_BINDING_ABORTED); mChannel = nsnull; } // 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) { // Clone it. nsresult rv = InitializeDecoderAsClone(other->mDecoder); if (NS_SUCCEEDED(rv)) return rv; } @@ -1599,20 +1592,18 @@ bool nsHTMLMediaElement::ParseAttribute( { 0 } }; if (aNamespaceID == kNameSpaceID_None) { if (ParseImageAttribute(aAttribute, aValue, aResult)) { 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); } } return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, aResult);
--- a/content/html/content/src/nsHTMLOptGroupElement.cpp +++ b/content/html/content/src/nsHTMLOptGroupElement.cpp @@ -80,16 +80,20 @@ public: // nsIContent virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor); virtual nsEventStates IntrinsicState() const; virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; virtual nsXPCClassInfo* GetClassInfo(); + + virtual bool IsDisabled() const { + return HasAttr(kNameSpaceID_None, nsGkAtoms::disabled); + } protected: /** * Get the select content element that contains this option * @param aSelectElement the select element [OUT] */ nsIContent* GetSelect(); };
--- a/content/html/content/src/nsHTMLOptionElement.h +++ b/content/html/content/src/nsHTMLOptionElement.h @@ -99,16 +99,20 @@ public: // nsIContent virtual nsEventStates IntrinsicState() const; virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const; 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 * intentionally does not return nsresult, all we care about is if * there's a select associated with this option or not. */ nsHTMLSelectElement* GetSelect();
--- a/content/html/content/src/nsHTMLScriptElement.cpp +++ b/content/html/content/src/nsHTMLScriptElement.cpp @@ -52,16 +52,17 @@ #include "nsIXPConnect.h" #include "nsServiceManagerUtils.h" #include "nsIDOMDocument.h" #include "nsContentErrors.h" #include "nsIArray.h" #include "nsTArray.h" #include "nsDOMJSUtils.h" +using namespace mozilla; using namespace mozilla::dom; class nsHTMLScriptElement : public nsGenericHTMLElement, public nsIDOMHTMLScriptElement, public nsScriptElement { public: using nsGenericElement::GetText; @@ -103,21 +104,26 @@ public: // nsIDOMHTMLScriptElement NS_DECL_NSIDOMHTMLSCRIPTELEMENT // nsIScriptElement virtual void GetScriptType(nsAString& type); 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; // nsGenericElement virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify); virtual nsXPCClassInfo* GetClassInfo(); @@ -173,16 +179,32 @@ nsHTMLScriptElement::BindToTree(nsIDocum if (aDocument) { MaybeProcessScript(); } 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 { *aResult = nsnull; nsCOMPtr<nsINodeInfo> ni = aNodeInfo; nsHTMLScriptElement* it = new nsHTMLScriptElement(ni.forget(), NOT_FROM_PARSER); @@ -306,14 +328,20 @@ nsHTMLScriptElement::FreezeUriAsyncDefer mDefer = !async && defer; mAsync = async; } mFrozen = true; } +CORSMode +nsHTMLScriptElement::GetCORSMode() const +{ + return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); +} + bool nsHTMLScriptElement::HasScriptContent() { return (mFrozen ? mExternal : HasAttr(kNameSpaceID_None, nsGkAtoms::src)) || nsContentUtils::HasNonEmptyTextContent(this); }
--- a/content/html/content/src/nsHTMLStyleElement.cpp +++ b/content/html/content/src/nsHTMLStyleElement.cpp @@ -335,17 +335,19 @@ nsHTMLStyleElement::GetStyleSheetInfo(ns *aIsAlternate = false; nsAutoString title; GetAttr(kNameSpaceID_None, nsGkAtoms::title, title); title.CompressWhitespace(); 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); nsAutoString mimeType; nsAutoString notUsed; nsContentUtils::SplitMimeType(aType, mimeType, notUsed); if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) { return;
--- a/content/html/content/test/test_bug353415-1.html +++ b/content/html/content/test/test_bug353415-1.html @@ -1,16 +1,16 @@ <!DOCTYPE html> <html> <head> <title>Test</title> <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> </head> <body> -<iframe name="submit_frame" onLoad="doCheck();"></iframe> +<iframe name="submit_frame"></iframe> <form method="get" id="form1" target="submit_frame" action="../../../../../blah"> <input type="text" name="field1" value="teststring"><br> <input type="radio" name="field2" value="0" checked> 0 <input type="radio" name="field3" value="1"> 1<br> <input type="checkbox" name="field4" value="1" checked> 1 <input type="checkbox" name="field5" value="2"> 2 <input type="checkbox" name="field6" value="3" checked> 3 <select name="field7"> @@ -22,18 +22,21 @@ <input name="field8" value="8"> <input name="field9" value="9"> <input type="image" name="field10"> <label name="field11"> <input name="field12"> <input type="button" name="field13" value="button"> </form> <script> - document.forms[0].submit(); + SimpleTest.waitForExplicitFinish(); - SimpleTest.waitForExplicitFinish(); - function doCheck(){ - is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=", "Submit string was correct."); - SimpleTest.finish(); - } + addLoadEvent(function() { + document.getElementsByName('submit_frame')[0].onload = function() { + is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=", "Submit string was correct."); + SimpleTest.finish(); + }; + + document.forms[0].submit(); + }); </script> </body> </html>
--- a/content/html/content/test/test_bug353415-2.html +++ b/content/html/content/test/test_bug353415-2.html @@ -49,17 +49,19 @@ <input type="button" name="field13-2" value="button"> <input type="hidden" name="field14-2" value="14"> </tr> </table> </form> <script> SimpleTest.waitForExplicitFinish(); - frames['submit_frame'].onload = function() { - is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1-2=teststring&field2-2=0&field4-2=1&field6-2=3&field7-2=2&field8-2=8&field9-2=9&field12-2=&field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=&field14=14&field14-2=14", "Submit string was correct."); - SimpleTest.finish(); - } + addLoadEvent(function() { + document.getElementsByName('submit_frame')[0].onload = function() { + is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1-2=teststring&field2-2=0&field4-2=1&field6-2=3&field7-2=2&field8-2=8&field9-2=9&field12-2=&field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=&field14=14&field14-2=14", "Submit string was correct."); + SimpleTest.finish(); + }; - document.forms[0].submit(); + document.forms[0].submit(); + }); </script> </body> </html>
--- a/content/html/content/test/test_bug430351.html +++ b/content/html/content/test/test_bug430351.html @@ -56,16 +56,17 @@ var focusableElements = [ "<button type=\"submit\" tabindex=\"0\"></button>", "<button type=\"submit\" tabindex=\"1\"></button>", "<button type=\"submit\" contenteditable=\"true\"></button>", "<div tabindex=\"-1\"></div>", "<div tabindex=\"0\"></div>", "<div tabindex=\"1\"></div>", "<div contenteditable=\"true\"></div>", + "<div tabindex=\"0\" disabled></div>", "<embed>", "<embed tabindex=\"-1\">", "<embed tabindex=\"0\">", "<embed tabindex=\"0\" disabled>", "<embed tabindex=\"1\">", "<embed disabled>", "<embed contenteditable=\"true\">", @@ -160,34 +161,43 @@ var focusableElements = [ "<object classid=\"java:a\" tabindex=\"1\"></object>", "<object classid=\"java:a\" disabled></object>", "<object classid=\"java:a\" contenteditable=\"true\"></object>", "<select></select>", "<select tabindex=\"-1\"></select>", "<select tabindex=\"0\"></select>", "<select tabindex=\"1\"></select>", - "<select contenteditable=\"true\"></select>" + "<select contenteditable=\"true\"></select>", + + "<option tabindex='-1'></option>", + "<option tabindex='0'></option>", + "<option tabindex='1'></option>", + "<option contenteditable></option>", + + "<optgroup tabindex='-1'></optgroup>", + "<optgroup tabindex='0'></optgroup>", + "<optgroup tabindex='1'></optgroup>", + "<optgroup contenteditable></optgroup>" ]; var nonFocusableElements = [ "<a></a>", "<a disabled></a>", "<button tabindex=\"0\" disabled></button>", "<button disabled></button>", "<button type=\"reset\" tabindex=\"0\" disabled></button>", "<button type=\"reset\" disabled></button>", "<button type=\"submit\" tabindex=\"0\" disabled></button>", "<button type=\"submit\" disabled></button>", "<div></div>", - "<div tabindex=\"0\" disabled></div>", "<div disabled></div>", "<img>", "<img disabled>", "<img contenteditable=\"true\">", "<img usemap=\"#map\">", "<img usemap=\"#map\" tabindex=\"-1\">", @@ -238,17 +248,23 @@ var nonFocusableElements = [ "<input type=\"submit\" disabled>", "<input type=\"text\" tabindex=\"0\" disabled>", "<input type=\"text\" disabled>", "<object></object>", "<select tabindex=\"0\" disabled></select>", - "<select disabled></select>" + "<select disabled></select>", + + "<option></option>", + "<option tabindex='1' disabled></option>", + + "<optgroup></optgroup>", + "<optgroup tabindex='1' disabled></optgroup>" ]; var focusableInContentEditable = [ "<button></button>", "<button tabindex=\"-1\"></button>", "<button tabindex=\"0\"></button>", "<button tabindex=\"1\"></button>", "<button contenteditable=\"true\"></button>", @@ -263,16 +279,17 @@ var focusableInContentEditable = [ "<button type=\"submit\" tabindex=\"-1\"></button>", "<button type=\"submit\" tabindex=\"0\"></button>", "<button type=\"submit\" tabindex=\"1\"></button>", "<button type=\"submit\" contenteditable=\"true\"></button>", "<div tabindex=\"-1\"></div>", "<div tabindex=\"0\"></div>", "<div tabindex=\"1\"></div>", + "<div tabindex=\"0\" disabled></div>", "<embed>", "<embed tabindex=\"-1\">", "<embed tabindex=\"0\">", "<embed tabindex=\"0\" disabled>", "<embed tabindex=\"1\">", "<embed disabled>", "<embed contenteditable=\"true\">", @@ -360,17 +377,25 @@ var focusableInContentEditable = [ // Disabled doesn't work for <object>. "<object tabindex=\"0\" disabled></object>", "<object disabled></object>", "<select></select>", "<select tabindex=\"-1\"></select>", "<select tabindex=\"0\"></select>", "<select tabindex=\"1\"></select>", - "<select contenteditable=\"true\"></select>" + "<select contenteditable=\"true\"></select>", + + "<option tabindex='-1'></option>", + "<option tabindex='0'></option>", + "<option tabindex='1'></option>", + + "<optgroup tabindex='-1'></optgroup>", + "<optgroup tabindex='0'></optgroup>", + "<optgroup tabindex='1'></optgroup>" ]; var focusableInDesignMode = [ "<embed>", "<embed tabindex=\"-1\">", "<embed tabindex=\"0\">", "<embed tabindex=\"0\" disabled>", "<embed tabindex=\"1\">",
--- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1353,17 +1353,17 @@ nsHTMLDocument::Open(const nsAString& aC // No calling document.open() on XHTML return NS_ERROR_DOM_INVALID_STATE_ERR; } nsCAutoString contentType; 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") && !type.EqualsLiteral("replace")) { contentType.AssignLiteral("text/plain"); } }
--- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/nsSVGFilters.cpp @@ -139,22 +139,22 @@ nsSVGFE::SetupScalingFilter(nsSVGFilterI result.mRescaling = aKernelUnitLength->IsExplicitlySet(); if (!result.mRescaling) { result.mSource = aSource->mImage; result.mTarget = aTarget->mImage; result.mDataRect = aDataRect; return result; } - float kernelX = aInstance->GetPrimitiveNumber(nsSVGUtils::X, - aKernelUnitLength, - nsSVGNumberPair::eFirst); - float kernelY = aInstance->GetPrimitiveNumber(nsSVGUtils::Y, - aKernelUnitLength, - nsSVGNumberPair::eSecond); + gfxFloat kernelX = aInstance->GetPrimitiveNumber(nsSVGUtils::X, + aKernelUnitLength, + nsSVGNumberPair::eFirst); + gfxFloat kernelY = aInstance->GetPrimitiveNumber(nsSVGUtils::Y, + aKernelUnitLength, + nsSVGNumberPair::eSecond); if (kernelX <= 0 || kernelY <= 0) return result; bool overflow = false; gfxIntSize scaledSize = nsSVGUtils::ConvertToSurfaceSize(gfxSize(aTarget->mImage->Width() / kernelX, aTarget->mImage->Height() / kernelY), &overflow);
--- a/content/svg/content/src/nsSVGScriptElement.cpp +++ b/content/svg/content/src/nsSVGScriptElement.cpp @@ -81,26 +81,31 @@ public: NS_FORWARD_NSIDOMELEMENT(nsSVGScriptElementBase::) NS_FORWARD_NSIDOMSVGELEMENT(nsSVGScriptElementBase::) // nsIScriptElement virtual void GetScriptType(nsAString& type); virtual void GetScriptText(nsAString& text); virtual void GetScriptCharset(nsAString& charset); virtual void FreezeUriAsyncDefer(); + virtual CORSMode GetCORSMode() const; // nsScriptElement virtual bool HasScriptContent(); // nsIContent specializations: virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, 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; virtual nsXPCClassInfo* GetClassInfo(); protected: virtual StringAttributesInfo GetStringInfo(); enum { HREF }; @@ -283,8 +288,31 @@ nsSVGScriptElement::AfterSetAttr(PRInt32 const nsAttrValue* aValue, bool aNotify) { if (aNamespaceID == kNameSpaceID_XLink && aName == nsGkAtoms::href) { MaybeProcessScript(); } 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)); +} +
--- a/content/svg/content/src/nsSVGStyleElement.cpp +++ b/content/svg/content/src/nsSVGStyleElement.cpp @@ -332,19 +332,19 @@ nsSVGStyleElement::GetStyleSheetInfo(nsA *aIsAlternate = false; nsAutoString title; GetAttr(kNameSpaceID_None, nsGkAtoms::title, title); title.CompressWhitespace(); 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()) { aType.AssignLiteral("text/css"); } return; }
--- a/content/xbl/src/nsXBLPrototypeHandler.cpp +++ b/content/xbl/src/nsXBLPrototypeHandler.cpp @@ -927,31 +927,28 @@ nsXBLPrototypeHandler::ConstructPrototyp if (key.IsEmpty()) aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, key); } } 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 { key.Assign(aKeyCode); if (mType & NS_HANDLER_TYPE_XUL) aKeyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, key); if (!key.IsEmpty()) {
--- a/content/xslt/src/base/txStringUtils.h +++ b/content/xslt/src/base/txStringUtils.h @@ -39,31 +39,29 @@ #ifndef txStringUtils_h__ #define txStringUtils_h__ #include "nsAString.h" #include "nsIAtom.h" #include "nsUnicharUtils.h" -#define TX_ToLowerCase ToLowerCase - typedef nsCaseInsensitiveStringComparator txCaseInsensitiveStringComparator; /** * Check equality between a string and an atom containing ASCII. */ inline bool TX_StringEqualsAtom(const nsASingleFragmentString& aString, nsIAtom* aAtom) { return aAtom->Equals(aString); } inline already_AddRefed<nsIAtom> TX_ToLowerCaseAtom(nsIAtom* aAtom) { nsAutoString str; aAtom->ToString(str); - TX_ToLowerCase(str); + nsContentUtils::ASCIIToLower(str); return do_GetAtom(str); } #endif // txStringUtils_h__
--- a/content/xslt/src/xpath/txExprParser.cpp +++ b/content/xslt/src/xpath/txExprParser.cpp @@ -933,17 +933,17 @@ txExprParser::resolveQName(const nsAStri return NS_ERROR_OUT_OF_MEMORY; } return aContext->resolveNamespacePrefix(*aPrefix, aNamespace); } // the lexer dealt with idx == 0 *aPrefix = 0; if (aIsNameTest && aContext->caseInsensitiveNameTests()) { nsAutoString lcname; - TX_ToLowerCase(aQName, lcname); + nsContentUtils::ASCIIToLower(aQName, lcname); *aLocalName = NS_NewAtom(lcname); } else { *aLocalName = NS_NewAtom(aQName); } if (!*aLocalName) { return NS_ERROR_OUT_OF_MEMORY; }
--- a/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp +++ b/content/xslt/src/xpath/txMozillaXPathTreeWalker.cpp @@ -448,17 +448,17 @@ txXPathNodeUtils::getLocalName(const txX } aNode.Content()->GetAttrNameAt(aNode.mIndex)->LocalName()-> ToString(aLocalName); // Check for html if (aNode.Content()->NodeInfo()->NamespaceEquals(kNameSpaceID_None) && aNode.Content()->IsHTML()) { - ToUpperCase(aLocalName); + nsContentUtils::ASCIIToUpper(aLocalName); } } /* static */ void txXPathNodeUtils::getNodeName(const txXPathNode& aNode, nsAString& aName) { if (aNode.isDocument()) {
--- a/content/xslt/src/xpath/txResultRecycler.cpp +++ b/content/xslt/src/xpath/txResultRecycler.cpp @@ -224,33 +224,16 @@ txResultRecycler::getNodeSet(const txXPa *aResult = nodes; } NS_ADDREF(*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<txNodeSet*>(mNodeSetResults.pop()); - (*aResult)->append(aNode); - (*aResult)->mRecycler = this; - } - NS_ADDREF(*aResult); - - return NS_OK; -} - -nsresult txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult) { if (mNumberResults.isEmpty()) { *aResult = new NumberResult(aValue, this); NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); } else { NumberResult* numRes =
--- a/content/xslt/src/xpath/txResultRecycler.h +++ b/content/xslt/src/xpath/txResultRecycler.h @@ -81,17 +81,16 @@ public: * Functions to return results that will be fully used by the caller. * Returns nsnull on out-of-memory and an inited result otherwise. */ nsresult getStringResult(StringResult** aResult); nsresult getStringResult(const nsAString& aValue, txAExprResult** aResult); 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); /** * Functions to return a txAExprResult that is shared across several * clients and must not be modified. Never returns nsnull. */ void getEmptyStringResult(txAExprResult** aResult); void getBoolResult(bool aValue, txAExprResult** aResult);
--- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp +++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp @@ -155,17 +155,17 @@ txMozillaXMLOutput::attribute(nsIAtom* a const nsSubstring& aLocalName, const PRInt32 aNsID, const nsString& aValue) { nsCOMPtr<nsIAtom> lname; if (mOpenedElementIsHTML && aNsID == kNameSpaceID_None) { nsAutoString lnameStr; - ToLowerCase(aLocalName, lnameStr); + nsContentUtils::ASCIIToLower(aLocalName, lnameStr); lname = do_GetAtom(lnameStr); } else { lname = do_GetAtom(aLocalName); } NS_ENSURE_TRUE(lname, NS_ERROR_OUT_OF_MEMORY); @@ -494,17 +494,17 @@ txMozillaXMLOutput::startElement(nsIAtom { PRInt32 nsId = aNsID; nsCOMPtr<nsIAtom> lname; if (mOutputFormat.mMethod == eHTMLOutput && aNsID == kNameSpaceID_None) { nsId = kNameSpaceID_XHTML; nsAutoString lnameStr; - ToLowerCase(aLocalName, lnameStr); + nsContentUtils::ASCIIToLower(aLocalName, lnameStr); lname = do_GetAtom(lnameStr); } else { lname = do_GetAtom(aLocalName); } // No biggie if we lose the prefix due to OOM NS_ENSURE_TRUE(lname, NS_ERROR_OUT_OF_MEMORY); @@ -797,17 +797,17 @@ txMozillaXMLOutput::endHTMLElement(nsICo else if (mCreatingNewDocument && atom == nsGkAtoms::meta) { // handle HTTP-EQUIV data nsAutoString httpEquiv; aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv, httpEquiv); if (!httpEquiv.IsEmpty()) { nsAutoString value; aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::content, value); if (!value.IsEmpty()) { - ToLowerCase(httpEquiv); + nsContentUtils::ASCIIToLower(httpEquiv); nsCOMPtr<nsIAtom> header = do_GetAtom(httpEquiv); processHTTPEquiv(header, value); } } } return NS_OK; }
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -783,21 +783,17 @@ void nsXULPDGlobalObject::ClearGlobalObjectOwner() { NS_ASSERTION(!mCachedPrincipal, "This shouldn't ever be set until now!"); // Cache mGlobalObjectOwner's principal if possible. if (this != nsXULPrototypeDocument::gSystemGlobal) mCachedPrincipal = mGlobalObjectOwner->DocumentPrincipal(); - if (mContext) { - mContext->FinalizeContext(); - mContext = NULL; - } - + mContext = NULL; mGlobalObjectOwner = NULL; } void nsXULPDGlobalObject::OnFinalize(JSObject* aObject) { mJSObject = NULL;
--- a/docshell/base/nsDefaultURIFixup.cpp +++ b/docshell/base/nsDefaultURIFixup.cpp @@ -49,16 +49,17 @@ #ifdef MOZ_TOOLKIT_SEARCH #include "nsIBrowserSearchService.h" #endif #include "nsIURIFixup.h" #include "nsDefaultURIFixup.h" #include "mozilla/Preferences.h" +#include "nsIObserverService.h" using namespace mozilla; /* Implementation file */ NS_IMPL_ISUPPORTS1(nsDefaultURIFixup, nsIURIFixup) nsDefaultURIFixup::nsDefaultURIFixup() { @@ -373,17 +374,27 @@ NS_IMETHODIMP nsDefaultURIFixup::Keyword // Escape keyword, then prepend URL nsCAutoString spec; if (!NS_Escape(keyword, spec, url_XPAlphas)) { return NS_ERROR_OUT_OF_MEMORY; } spec.Insert(url, 0); - return NS_NewURI(aURI, spec); + nsresult rv = NS_NewURI(aURI, spec); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService(); + if (obsSvc) { + obsSvc->NotifyObservers(*aURI, + "defaultURIFixup-using-keyword-pref", + nsnull); + } + return NS_OK; } #ifdef MOZ_TOOLKIT_SEARCH // Try falling back to the search service's default search engine nsCOMPtr<nsIBrowserSearchService> searchSvc = do_GetService("@mozilla.org/browser/search-service;1"); if (searchSvc) { nsCOMPtr<nsISearchEngine> defaultEngine; searchSvc->GetOriginalDefaultEngine(getter_AddRefs(defaultEngine));
--- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -447,17 +447,16 @@ #include "nsIDOMGeoPositionError.h" // Workers #include "mozilla/dom/workers/Workers.h" #include "nsDOMFile.h" #include "nsDOMFileReader.h" #include "nsIDOMFileException.h" -#include "nsIDOMFileError.h" #include "nsIDOMFormData.h" #include "nsIDOMDOMStringMap.h" #include "nsIDOMDesktopNotification.h" #include "nsIDOMNavigatorDesktopNotification.h" #include "nsIDOMNavigatorGeolocation.h" #include "Navigator.h" @@ -1389,18 +1388,16 @@ static nsDOMClassInfoData sClassInfoData NS_DEFINE_CLASSINFO_DATA(FileList, nsFileListSH, ARRAY_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(Blob, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH, 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, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(MozBlobBuilder, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(DOMStringMap, nsDOMStringMapSH, @@ -3959,20 +3956,16 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(ClientRectList, nsIDOMClientRectList) DOM_CLASSINFO_MAP_ENTRY(nsIDOMClientRectList) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(FileList, nsIDOMFileList) 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 DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile) DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob) DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile) DOM_CLASSINFO_MAP_END
--- a/dom/base/nsDOMClassInfoClasses.h +++ b/dom/base/nsDOMClassInfoClasses.h @@ -397,17 +397,16 @@ DOMCI_CLASS(SVGForeignObjectElement) DOMCI_CLASS(XULCommandEvent) DOMCI_CLASS(CommandEvent) DOMCI_CLASS(OfflineResourceList) DOMCI_CLASS(FileList) DOMCI_CLASS(Blob) DOMCI_CLASS(File) DOMCI_CLASS(FileException) -DOMCI_CLASS(FileError) DOMCI_CLASS(FileReader) DOMCI_CLASS(MozURLProperty) DOMCI_CLASS(MozBlobBuilder) DOMCI_CLASS(DOMStringMap) // DOM modal content window class, almost identical to Window DOMCI_CLASS(ModalContentWindow)
--- a/dom/base/nsDOMJSUtils.h +++ b/dom/base/nsDOMJSUtils.h @@ -1,15 +1,17 @@ #ifndef nsDOMJSUtils_h__ #define nsDOMJSUtils_h__ #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 * GetScriptContextFromJSContext(JSContext *cx) { if (!(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) { return nsnull; } @@ -45,11 +47,11 @@ GetScriptContextPrincipalFromJSContext(J // jsval* and the args are found at: // ((jsval*)aArgv)[0], ..., ((jsval*)aArgv)[aArgc - 1] // The resulting object will take a copy of the array, and ensure each // element is rooted. // Optionally, aArgv may be NULL, in which case the array is allocated and // 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__
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2397,17 +2397,16 @@ nsGlobalWindow::SetDocShell(nsIDocShell* // SetArguments(), drop our reference to the arguments. mArguments = nsnull; mArgumentsLast = nsnull; mArgumentsOrigin = nsnull; } if (mContext) { mContext->GC(js::gcreason::SET_DOC_SHELL); - mContext->FinalizeContext(); mContext = nsnull; } #ifdef DEBUG nsCycleCollector_DEBUG_shouldBeFreed(mContext); nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this)); #endif } @@ -5927,17 +5926,17 @@ nsGlobalWindow::OpenDialog(const nsAStri jsval *argv = nsnull; // XXX - need to get this as nsISupports? ncc->GetArgc(&argc); ncc->GetArgvPtr(&argv); // Strip the url, name and options from the args seen by scripts. PRUint32 argOffset = argc < 3 ? argc : 3; - nsCOMPtr<nsIArray> argvArray; + nsCOMPtr<nsIJSArgArray> argvArray; rv = NS_CreateJSArgv(cx, argc - argOffset, argv + argOffset, getter_AddRefs(argvArray)); NS_ENSURE_SUCCESS(rv, rv); return OpenInternal(aUrl, aName, aOptions, true, // aDialog false, // aContentModal false, // aCalledNoScript @@ -6527,65 +6526,50 @@ nsGlobalWindow::ForceClose() DispatchCustomEvent("DOMWindowClose"); return FinalClose(); } nsresult nsGlobalWindow::FinalClose() { - nsresult rv; // Flag that we were closed. mIsClosed = true; nsCOMPtr<nsIJSContextStack> stack = do_GetService(sJSStackContractID); JSContext *cx = nsnull; if (stack) { stack->Peek(&cx); } if (cx) { 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<nsIDOMWindow *> - (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; } void nsGlobalWindow::ReallyCloseWindow() { FORWARD_TO_OUTER_VOID(ReallyCloseWindow, ()); @@ -8862,18 +8846,17 @@ nsGlobalWindow::OpenInternal(const nsASt // If script in some other window is doing a window.open on us and // it's being blocked, then it's OK to close us afterwards, probably. // But if we're doing a window.open on ourselves and block the popup, // prevent this window from closing until after this script terminates // so that whatever popup blocker UI the app has will be visible. if (mContext == GetScriptContextFromJSContext(aJSCallerContext)) { mBlockScriptedClosingFlag = true; mContext->SetTerminationFunction(CloseBlockScriptTerminationFunc, - static_cast<nsPIDOMWindow*> - (this)); + this); } } FireAbuseEvents(true, false, aUrl, aName, aOptions); return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE; } }
--- a/dom/base/nsIScriptContext.h +++ b/dom/base/nsIScriptContext.h @@ -51,16 +51,17 @@ class nsIScriptSecurityManager; class nsIPrincipal; class nsIAtom; class nsIArray; class nsIVariant; class nsIObjectInputStream; class nsIObjectOutputStream; template<class> class nsScriptObjectHolder; class nsIScriptObjectPrincipal; +class nsIDOMWindow; typedef void (*nsScriptTerminationFunc)(nsISupports* aRef); #define NS_ISCRIPTCONTEXTPRINCIPAL_IID \ { 0xd012cdb3, 0x8f1e, 0x4440, \ { 0x8c, 0xbd, 0x32, 0x7f, 0x98, 0x1d, 0x37, 0xb4 } } class nsIScriptContextPrincipal : public nsISupports @@ -70,18 +71,18 @@ public: virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0; }; 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... */ #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT /** * It is used by the application to initialize a runtime and run scripts. * A script runtime would implement this interface. @@ -340,21 +341,16 @@ public: * reentrancy issues during the initialization process. * * @return true if initialized, false if not * */ 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 * * @return NS_OK if the method is successful */ virtual void GC(js::gcreason::Reason aReason) = 0; /** @@ -384,28 +380,28 @@ public: * than JS (ie, this should be moved to a private interface!) * Called to specify a function that should be called when the current * script (if there is one) terminates. Generally used if breakdown * of script state needs to happen, but should be deferred till * the end of script evaluation. * * @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. */ virtual bool GetScriptsEnabled() = 0; virtual void SetScriptsEnabled(bool aEnabled, bool aFireTimeouts) = 0; // 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 */ virtual bool GetProcessingScriptTag() = 0; virtual void SetProcessingScriptTag(bool aResult) = 0; /**
--- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2288,27 +2288,27 @@ nsJSContext::InitializeExternalClasses() { nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager(); NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED); return nameSpaceManager->InitForContext(this); } nsresult -nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArgs) +nsJSContext::SetProperty(JSObject* aTarget, const char* aPropName, nsISupports* aArgs) { PRUint32 argc; jsval *argv = nsnull; JSAutoRequest ar(mContext); Maybe<nsRootedJSValueArray> 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; // got the arguments, now attach them. // window.dialogArguments is supposed to be an array if a JS array // was passed to showModalDialog(), deal with that here. @@ -2322,21 +2322,19 @@ nsJSContext::SetProperty(void *aTarget, } JSObject *args = ::JS_NewArrayObject(mContext, argc, argv); vargs = OBJECT_TO_JSVAL(args); } // 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<JSObject *>(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 nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs, JSObject *aScope, PRUint32 *aArgc, jsval **aArgv, Maybe<nsRootedJSValueArray> &aTempStorage) @@ -2355,17 +2353,17 @@ nsJSContext::ConvertSupportsTojsvals(nsI *aArgv = nsnull; *aArgc = 0; nsIXPConnect *xpc = nsContentUtils::XPConnect(); NS_ENSURE_TRUE(xpc, NS_ERROR_UNEXPECTED); 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<nsIArray> argsArray(do_QueryInterface(aArgs)); if (argsArray) { rv = argsArray->GetLength(&argCount); NS_ENSURE_SUCCESS(rv, rv); if (argCount == 0) @@ -2376,17 +2374,17 @@ nsJSContext::ConvertSupportsTojsvals(nsI // Use the caller's auto guards to release and unroot. aTempStorage.construct(mContext); bool ok = aTempStorage.ref().SetCapacity(mContext, argCount); NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); 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<nsISupports> arg; jsval *thisval = argv + argCtr; argsArray->QueryElementAt(argCtr, NS_GET_IID(nsISupports), getter_AddRefs(arg)); if (!arg) { *thisval = JSVAL_NULL; continue; } @@ -2971,22 +2969,16 @@ nsJSContext::DidInitializeContext() bool nsJSContext::IsContextInitialized() { return mIsInitialized; } void -nsJSContext::FinalizeContext() -{ - ; -} - -void nsJSContext::ScriptEvaluated(bool aTerminated) { if (aTerminated && mTerminations) { // Make sure to null out mTerminations before doing anything that // might cause new termination funcs to be added! nsJSContext::TerminationFuncClosure* start = mTerminations; mTerminations = nsnull; @@ -3001,30 +2993,25 @@ nsJSContext::ScriptEvaluated(bool aTermi JS_MaybeGC(mContext); if (aTerminated) { mOperationCallbackTime = 0; mModalStateTime = 0; } } -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 nsJSContext::GetScriptsEnabled() { return mScriptsEnabled; } @@ -3917,17 +3904,17 @@ nsresult NS_CreateJSRuntime(nsIScriptRun } // A fast-array class for JS. This class supports both nsIJSScriptArray and // nsIArray. If it is JS itself providing and consuming this class, all work // can be done via nsIJSScriptArray, and avoid the conversion of elements // 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(); // nsISupports NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSArgArray, nsIJSArgArray) @@ -4057,17 +4044,17 @@ NS_IMETHODIMP nsJSArgArray::IndexOf(PRUi /* nsISimpleEnumerator enumerate (); */ NS_IMETHODIMP nsJSArgArray::Enumerate(nsISimpleEnumerator **_retval) { return NS_ERROR_NOT_IMPLEMENTED; } // The factory function nsresult NS_CreateJSArgv(JSContext *aContext, PRUint32 argc, void *argv, - nsIArray **aArray) + nsIJSArgArray **aArray) { nsresult rv; nsJSArgArray *ret = new nsJSArgArray(aContext, argc, static_cast<jsval *>(argv), &rv); if (ret == nsnull) return NS_ERROR_OUT_OF_MEMORY; if (NS_FAILED(rv)) { delete ret;
--- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -42,16 +42,17 @@ #include "nsCOMPtr.h" #include "jsapi.h" #include "jsfriendapi.h" #include "nsIObserver.h" #include "nsIXPCScriptNotify.h" #include "prtime.h" #include "nsCycleCollectionParticipant.h" #include "nsIXPConnect.h" +#include "nsIArray.h" class nsIXPConnectJSObjectHolder; class nsRootedJSValueArray; class nsScriptNameSpaceManager; namespace mozilla { template <class> class Maybe; } @@ -138,25 +139,24 @@ public: virtual nsresult ConnectToInner(nsIScriptGlobalObject *aNewInner, JSObject *aOuterGlobal); virtual nsresult InitContext(); virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject, nsIScriptGlobalObject *aCurrentInner); 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); virtual bool GetExecutingScript(); virtual void SetGCOnDestruction(bool aGCOnDestruction); @@ -343,21 +343,20 @@ public: static nsScriptNameSpaceManager* GetNameSpaceManager(); }; // An interface for fast and native conversion to/from nsIArray. If an object // supports this interface, JS can reach directly in for the argv, and avoid // 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) // Bug 312003 describes why this must be "void **", but after calling argv // may be cast to jsval* and the args found at: // ((jsval*)argv)[0], ..., ((jsval*)argv)[argc - 1] virtual nsresult GetArgs(PRUint32 *argc, void **argv) = 0; };
--- a/dom/base/nsJSTimeoutHandler.cpp +++ b/dom/base/nsJSTimeoutHandler.cpp @@ -96,17 +96,17 @@ private: nsCOMPtr<nsIScriptContext> mContext; // filename, line number and JS language version string of the // caller of setTimeout() nsCString mFileName; PRUint32 mLineNo; PRUint32 mVersion; - nsCOMPtr<nsIArray> mArgv; + nsCOMPtr<nsIJSArgArray> mArgv; // The JS expression to evaluate or function to call, if !mExpr JSFlatString *mExpr; JSObject *mFunObj; }; // nsJSScriptTimeoutHandler @@ -321,28 +321,27 @@ nsJSScriptTimeoutHandler::Init(nsGlobalW NS_ENSURE_SUCCESS(rv, rv); mFunObj = funobj; // Create our arg array. argc is the number of arguments passed // 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<nsIArray> array; + nsCOMPtr<nsIJSArgArray> 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)); if (NS_FAILED(rv)) { return NS_ERROR_OUT_OF_MEMORY; } PRUint32 dummy; jsval *jsargv = nsnull; - nsCOMPtr<nsIJSArgArray> jsarray(do_QueryInterface(array)); - jsarray->GetArgs(&dummy, reinterpret_cast<void **>(&jsargv)); + array->GetArgs(&dummy, reinterpret_cast<void **>(&jsargv)); // jsargv might be null if we have argc <= 2 if (jsargv) { for (PRInt32 i = 2; (PRUint32)i < argc; ++i) { jsargv[i - 2] = argv[i]; } } else { NS_ASSERTION(argc <= 2, "Why do we have no jsargv when we have arguments?");
--- a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl +++ b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl @@ -54,26 +54,28 @@ typedef long WebGLsizeiptr; typedef unsigned long WebGLuint; typedef float WebGLfloat; typedef float WebGLclampf; %{C++ // 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 // [scriptable, builtinclass, uuid(0df9f4ed-f5ff-4e51-a6ff-2bd9785a7639)] interface nsIWebGLTexture : nsISupports { @@ -170,17 +172,17 @@ interface nsIWebGLExtensionLoseContext : [scriptable, uuid(73bfb64d-94bd-4a7a-9eab-6b6d32e57aa0)] interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension { const WebGLenum TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE; 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 { // // CONSTANTS // /* ClearBufferMask */ const unsigned long DEPTH_BUFFER_BIT = 0x00000100; @@ -781,29 +783,29 @@ interface nsIDOMWebGLRenderingContext : in WebGLsizei width, in WebGLsizei height, in WebGLint border, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels); [noscript] void texImage2D_imageData(in WebGLenum target, in WebGLint level, in WebGLenum internalformat, in WebGLsizei width, in WebGLsizei height, in WebGLint border, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels); // 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, in WebGLint xoffset, in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels); [noscript] void texSubImage2D_imageData(in WebGLenum target, in WebGLint level, in WebGLint xoffset, in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels); // 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); void texParameteri(in WebGLenum target, in WebGLenum pname, in WebGLint param); //void glTexParameter(in WebGLenum target, in WebGLenum pname, in nsIWebGLArray params); // Modified: All the glUniform*v forms below are modified by replacing 'count' and 'v' with a nsIWebGLArray void uniform1f (in nsIWebGLUniformLocation location, in WebGLfloat x);