author | David Anderson <danderson@mozilla.com> |
Fri, 06 Apr 2012 16:38:53 -0700 | |
changeset 106096 | 6040d30988ff69895b11b0541071a6afd295f8e9 |
parent 106094 | ad6e00aaa6cde20f7b844a73f2839e66e2f6521f (current diff) |
parent 91169 | a402c2064466dee340d4ff19db55c04c74e04a77 (diff) |
child 106097 | 071792b470d9eabfba8785fdd175cdde1708f070 |
push id | 23447 |
push user | danderson@mozilla.com |
push date | Tue, 11 Sep 2012 17:34:27 +0000 |
treeherder | mozilla-central@fdfaef738a00 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 14.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/build/Makefile.in +++ b/accessible/build/Makefile.in @@ -53,16 +53,17 @@ GRE_MODULE = 1 LIBXUL_LIBRARY = 1 CPPSRCS = nsAccessibilityFactory.cpp LOCAL_INCLUDES = -I$(srcdir)/../src SHARED_LIBRARY_LIBS = \ ../src/base/$(LIB_PREFIX)accessibility_base_s.$(LIB_SUFFIX) \ + ../src/generic/$(LIB_PREFIX)accessibility_generic_s.$(LIB_SUFFIX) \ ../src/html/$(LIB_PREFIX)accessibility_html_s.$(LIB_SUFFIX) \ ../src/xpcom/$(LIB_PREFIX)accessibility_xpcom_s.$(LIB_SUFFIX) \ ../src/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) \ ../src/xforms/$(LIB_PREFIX)accessibility_xforms_s.$(LIB_SUFFIX) \ $(NULL) ifdef MOZ_XUL SHARED_LIBRARY_LIBS += ../src/xul/$(LIB_PREFIX)accessibility_xul_s.$(LIB_SUFFIX)
--- a/accessible/src/Makefile.in +++ b/accessible/src/Makefile.in @@ -56,16 +56,17 @@ PLATFORM_DIR += other endif endif endif DIRS += $(PLATFORM_DIR) DIRS += \ base \ + generic \ html \ xpcom \ xforms \ $(null) ifdef MOZ_XUL DIRS += xul endif
new file mode 100644 --- /dev/null +++ b/accessible/src/base/ARIAStateMap.cpp @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "ARIAStateMap.h" + +#include "States.h" + +#include "mozilla/dom/Element.h" + +using namespace mozilla; +using namespace mozilla::a11y; +using namespace mozilla::a11y::aria; + +/** + * Used to store state map rule data for ARIA attribute of enum type. + */ +struct EnumTypeData +{ + EnumTypeData(nsIAtom* aAttrName, + nsIAtom** aValue1, PRUint64 aState1, + nsIAtom** aValue2, PRUint64 aState2, + nsIAtom** aValue3 = 0, PRUint64 aState3 = 0) : + mState1(aState1), mState2(aState2), mState3(aState3), mDefaultState(0), + mAttrName(aAttrName), mValue1(aValue1), mValue2(aValue2), mValue3(aValue3), + mNullValue(nsnull) + { } + + EnumTypeData(nsIAtom* aAttrName, PRUint64 aDefaultState, + nsIAtom** aValue1, PRUint64 aState1) : + mState1(aState1), mState2(0), mState3(0), mDefaultState(aDefaultState), + mAttrName(aAttrName), mValue1(aValue1), mValue2(nsnull), mValue3(nsnull), + mNullValue(nsnull) + { } + + // States applied if corresponding enum values are matched. + const PRUint64 mState1; + const PRUint64 mState2; + const PRUint64 mState3; + + // Default state if no one enum value is matched. + const PRUint64 mDefaultState; + + // ARIA attribute name. + nsIAtom* const mAttrName; + + // States if the attribute value is matched to the enum value. Used as + // nsIContent::AttrValuesArray. + nsIAtom* const* const mValue1; + nsIAtom* const* const mValue2; + nsIAtom* const* const mValue3; + nsIAtom* const* const mNullValue; +}; + +enum ETokenType +{ + eBoolType = 0, + eMixedType = 1, // can take 'mixed' value + eDefinedIfAbsent = 2 // permanent and false state are applied if absent +}; + +/** + * Used to store state map rule data for ARIA attribute of token type (including + * mixed value). + */ +struct TokenTypeData +{ + TokenTypeData(nsIAtom* aAttrName, PRUint32 aType, + PRUint64 aPermanentState, + PRUint64 aTrueState, + PRUint64 aFalseState = 0) : + mAttrName(aAttrName), mType(aType), mPermanentState(aPermanentState), + mTrueState(aTrueState), mFalseState(aFalseState) + { } + + // ARIA attribute name. + nsIAtom* const mAttrName; + + // Type. + const PRUint32 mType; + + // State applied if the attribute is defined or mType doesn't have + // eDefinedIfAbsent flag set. + const PRUint64 mPermanentState; + + // States applied if the attribute value is true/false. + const PRUint64 mTrueState; + const PRUint64 mFalseState; +}; + +/** + * Map enum type attribute value to accessible state. + */ +static void MapEnumType(dom::Element* aElement, PRUint64* aState, + const EnumTypeData& aData); + +/** + * Map token type attribute value to states. + */ +static void MapTokenType(dom::Element* aContent, PRUint64* aState, + const TokenTypeData& aData); + +bool +aria::MapToState(EStateRule aRule, dom::Element* aElement, PRUint64* aState) +{ + switch (aRule) { + case eARIAAutoComplete: + { + static const EnumTypeData data( + nsGkAtoms::aria_autocomplete, + &nsGkAtoms::inlinevalue, states::SUPPORTS_AUTOCOMPLETION, + &nsGkAtoms::list, states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION, + &nsGkAtoms::both, states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION); + + MapEnumType(aElement, aState, data); + return true; + } + + case eARIABusy: + { + static const EnumTypeData data( + nsGkAtoms::aria_busy, + &nsGkAtoms::_true, states::BUSY, + &nsGkAtoms::error, states::INVALID); + + MapEnumType(aElement, aState, data); + return true; + } + + case eARIACheckableBool: + { + static const TokenTypeData data( + nsGkAtoms::aria_checked, eBoolType | eDefinedIfAbsent, + states::CHECKABLE, states::CHECKED); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIACheckableMixed: + { + static const TokenTypeData data( + nsGkAtoms::aria_checked, eMixedType | eDefinedIfAbsent, + states::CHECKABLE, states::CHECKED); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIACheckedMixed: + { + static const TokenTypeData data( + nsGkAtoms::aria_checked, eMixedType, + states::CHECKABLE, states::CHECKED); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIADisabled: + { + static const TokenTypeData data( + nsGkAtoms::aria_disabled, eBoolType, + 0, states::UNAVAILABLE); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIAExpanded: + { + static const TokenTypeData data( + nsGkAtoms::aria_expanded, eBoolType, + 0, states::EXPANDED, states::COLLAPSED); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIAHasPopup: + { + static const TokenTypeData data( + nsGkAtoms::aria_haspopup, eBoolType, + 0, states::HASPOPUP); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIAInvalid: + { + static const TokenTypeData data( + nsGkAtoms::aria_invalid, eBoolType, + 0, states::INVALID); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIAMultiline: + { + static const TokenTypeData data( + nsGkAtoms::aria_multiline, eBoolType | eDefinedIfAbsent, + 0, states::MULTI_LINE, states::SINGLE_LINE); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIAMultiSelectable: + { + static const TokenTypeData data( + nsGkAtoms::aria_multiselectable, eBoolType, + 0, states::MULTISELECTABLE | states::EXTSELECTABLE); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIAOrientation: + { + static const EnumTypeData data( + nsGkAtoms::aria_orientation, states::HORIZONTAL, + &nsGkAtoms::vertical, states::VERTICAL); + + MapEnumType(aElement, aState, data); + return true; + } + + case eARIAPressed: + { + static const TokenTypeData data( + nsGkAtoms::aria_pressed, eMixedType, + states::CHECKABLE, states::PRESSED); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIAReadonly: + { + static const TokenTypeData data( + nsGkAtoms::aria_readonly, eBoolType, + 0, states::READONLY); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIAReadonlyOrEditable: + { + static const TokenTypeData data( + nsGkAtoms::aria_readonly, eBoolType | eDefinedIfAbsent, + 0, states::READONLY, states::EDITABLE); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIARequired: + { + static const TokenTypeData data( + nsGkAtoms::aria_required, eBoolType, + 0, states::REQUIRED); + + MapTokenType(aElement, aState, data); + return true; + } + + case eARIASelectable: + { + static const TokenTypeData data( + nsGkAtoms::aria_selected, eBoolType | eDefinedIfAbsent, + states::SELECTABLE, states::SELECTED); + + MapTokenType(aElement, aState, data); + return true; + } + + case eReadonlyUntilEditable: + { + if (!(*aState & states::EDITABLE)) + *aState |= states::READONLY; + + return true; + } + + default: + return false; + } +} + +static void +MapEnumType(dom::Element* aElement, PRUint64* aState, const EnumTypeData& aData) +{ + switch (aElement->FindAttrValueIn(kNameSpaceID_None, aData.mAttrName, + &aData.mValue1, eCaseMatters)) { + case 0: + *aState |= aData.mState1; + return; + case 1: + *aState |= aData.mState2; + return; + case 2: + *aState |= aData.mState3; + return; + } + + *aState |= aData.mDefaultState; +} + +static void +MapTokenType(dom::Element* aElement, PRUint64* aState, + const TokenTypeData& aData) +{ + if (aElement->HasAttr(kNameSpaceID_None, aData.mAttrName)) { + if ((aData.mType & eMixedType) && + aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName, + nsGkAtoms::mixed, eCaseMatters)) { + *aState |= aData.mPermanentState | states::MIXED; + return; + } + + if (aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName, + nsGkAtoms::_false, eCaseMatters)) { + *aState |= aData.mPermanentState | aData.mFalseState; + return; + } + + if (!aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName, + nsGkAtoms::_undefined, eCaseMatters) && + !aElement->AttrValueIs(kNameSpaceID_None, aData.mAttrName, + nsGkAtoms::_empty, eCaseMatters)) { + *aState |= aData.mPermanentState | aData.mTrueState; + } + return; + } + + if (aData.mType & eDefinedIfAbsent) + *aState |= aData.mPermanentState | aData.mFalseState; +}
new file mode 100644 --- /dev/null +++ b/accessible/src/base/ARIAStateMap.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _mozilla_a11y_aria_ARIAStateMap_h_ +#define _mozilla_a11y_aria_ARIAStateMap_h_ + +#include "prtypes.h" + +namespace mozilla { + +namespace dom { +class Element; +} + +namespace a11y { +namespace aria { + +/** + * List of the ARIA state mapping rules. + */ +enum EStateRule +{ + eARIANone, + eARIAAutoComplete, + eARIABusy, + eARIACheckableBool, + eARIACheckableMixed, + eARIACheckedMixed, + eARIADisabled, + eARIAExpanded, + eARIAHasPopup, + eARIAInvalid, + eARIAMultiline, + eARIAMultiSelectable, + eARIAOrientation, + eARIAPressed, + eARIAReadonly, + eARIAReadonlyOrEditable, + eARIARequired, + eARIASelectable, + eReadonlyUntilEditable +}; + +/** + * Expose the accessible states for the given element accordingly to state + * mapping rule. + * + * @param aRule [in] state mapping rule ID + * @param aElement [in] node of the accessible + * @param aState [in/out] accessible states + * @return true if state map rule ID is valid + */ +bool MapToState(EStateRule aRule, dom::Element* aElement, PRUint64* aState); + +} // namespace aria +} // namespace a11y +} // namespace mozilla + +#endif
--- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -47,25 +47,25 @@ LIBRARY_NAME = accessibility_base_s LIBXUL_LIBRARY = 1 CPPSRCS = \ AccCollector.cpp \ AccEvent.cpp \ AccGroupInfo.cpp \ AccIterator.cpp \ + ARIAStateMap.cpp \ filters.cpp \ FocusManager.cpp \ NotificationController.cpp \ nsAccDocManager.cpp \ nsAccessNode.cpp \ nsARIAGridAccessible.cpp \ nsARIAMap.cpp \ nsDocAccessible.cpp \ - nsOuterDocAccessible.cpp \ nsCoreUtils.cpp \ nsAccUtils.cpp \ nsAccessibilityService.cpp \ nsAccessible.cpp \ nsAccessiblePivot.cpp \ nsAccTreeWalker.cpp \ nsBaseWidgetAccessible.cpp \ nsEventShell.cpp \ @@ -87,16 +87,17 @@ EXPORTS = \ nsAccessible.h \ nsAccessNode.h \ nsARIAMap.h \ $(NULL) EXPORTS_NAMESPACES = mozilla/a11y EXPORTS_mozilla/a11y = \ + ARIAStateMap.h \ FocusManager.h \ States.h \ Role.h \ $(NULL) # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1
--- a/accessible/src/base/Statistics.h +++ b/accessible/src/base/Statistics.h @@ -43,43 +43,37 @@ #include "mozilla/Telemetry.h" namespace mozilla { namespace a11y { namespace statistics { inline void A11yInitialized() - { Telemetry::Accumulate(Telemetry::A11Y_INSTANTIATED, 1); } + { Telemetry::Accumulate(Telemetry::A11Y_INSTANTIATED_FLAG, true); } inline void A11yConsumers(PRUint32 aConsumer) { Telemetry::Accumulate(Telemetry::A11Y_CONSUMERS, aConsumer); } /** * Report that ISimpleDOM* has been used. */ inline void ISimpleDOMUsed() - { - static bool firstTime = true; - if (firstTime) { - Telemetry::Accumulate(Telemetry::A11Y_ISIMPLEDOM_USAGE, 1); - firstTime = false; - } - } + { Telemetry::Accumulate(Telemetry::A11Y_ISIMPLEDOM_USAGE_FLAG, true); } /** * Report that IAccessibleTable has been used. */ inline void IAccessibleTableUsed() - { Telemetry::Accumulate(Telemetry::A11Y_IATABLE_USAGE, 1); } + { Telemetry::Accumulate(Telemetry::A11Y_IATABLE_USAGE_FLAG, true); } /** * Report that XForms accessibility has been instantiated. */ inline void XFormsAccessibleUsed() - { Telemetry::Accumulate(Telemetry::A11Y_XFORMS_USAGE, 1); } + { Telemetry::Accumulate(Telemetry::A11Y_XFORMS_USAGE_FLAG, true); } } // namespace statistics } // namespace a11y } // namespace mozilla #endif
--- a/accessible/src/base/TextAttrs.cpp +++ b/accessible/src/base/TextAttrs.cpp @@ -755,10 +755,19 @@ TextAttrsMgr::TextPosTextAttr:: { nscoord coordValue = styleCoord.GetCoordValue(); return coordValue > 0 ? eTextPosSuper : (coordValue < 0 ? eTextPosSub : eTextPosBaseline); } } + const nsIContent* content = aFrame->GetContent(); + if (content && content->IsHTML()) { + const nsIAtom* tagName = content->Tag(); + if (tagName == nsGkAtoms::sup) + return eTextPosSuper; + if (tagName == nsGkAtoms::sub) + return eTextPosSub; + } + return eTextPosNone; }
--- a/accessible/src/base/TextAttrs.h +++ b/accessible/src/base/TextAttrs.h @@ -111,23 +111,21 @@ protected: * @param aStartHTOffset [in, out] the start offset * @param aEndHTOffset [in, out] the end offset */ class TextAttr; void GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen, PRInt32* aStartHTOffset, PRInt32* aEndHTOffset); private: + nsAccessible* mOffsetAcc; nsHyperTextAccessible* mHyperTextAcc; - + PRInt32 mOffsetAccIdx; bool mIncludeDefAttrs; - nsAccessible* mOffsetAcc; - PRInt32 mOffsetAccIdx; - protected: /** * Interface class of text attribute class implementations. */ class TextAttr { public:
--- a/accessible/src/base/nsARIAMap.cpp +++ b/accessible/src/base/nsARIAMap.cpp @@ -34,30 +34,30 @@ * 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 "nsARIAMap.h" -#include "nsIAccessibleRole.h" #include "Role.h" #include "States.h" #include "nsIContent.h" using namespace mozilla::a11y; +using namespace mozilla::a11y::aria; /** * This list of WAI-defined roles are currently hardcoded. * Eventually we will most likely be loading an RDF resource that contains this information * Using RDF will also allow for role extensibility. See bug 280138. * - * Definition of nsRoleMapEntry and nsStateMapEntry contains comments explaining this table. + * Definition of nsRoleMapEntry contains comments explaining this table. * * When no nsIAccessibleRole enum mapping exists for an ARIA role, the * role will be exposed via the object attribute "xml-roles". * In addition, in MSAA, the unmapped role will also be exposed as a BSTR string role. * * There are no nsIAccessibleRole enums for the following landmark roles: * banner, contentinfo, main, navigation, note, search, secondary, seealso, breadcrumbs */ @@ -602,102 +602,22 @@ nsRoleMapEntry nsARIAMap::gEmptyRoleMap roles::NOTHING, kUseMapRole, eNoValue, eNoAction, eNoLiveAttr, kNoReqStates }; -nsStateMapEntry nsARIAMap::gWAIStateMap[] = { - // eARIANone - nsStateMapEntry(), - - // eARIAAutoComplete - nsStateMapEntry(&nsGkAtoms::aria_autocomplete, - "inline", states::SUPPORTS_AUTOCOMPLETION, - "list", states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION, - "both", states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION), - - // eARIABusy - nsStateMapEntry(&nsGkAtoms::aria_busy, - "true", states::BUSY, - "error", states::INVALID), - - // eARIACheckableBool - nsStateMapEntry(&nsGkAtoms::aria_checked, kBoolType, - states::CHECKABLE, states::CHECKED, 0, true), - - // eARIACheckableMixed - nsStateMapEntry(&nsGkAtoms::aria_checked, kMixedType, - states::CHECKABLE, states::CHECKED, 0, true), - - // eARIACheckedMixed - nsStateMapEntry(&nsGkAtoms::aria_checked, kMixedType, - states::CHECKABLE, states::CHECKED, 0), - - // eARIADisabled - nsStateMapEntry(&nsGkAtoms::aria_disabled, kBoolType, - 0, states::UNAVAILABLE), - - // eARIAExpanded - nsStateMapEntry(&nsGkAtoms::aria_expanded, kBoolType, - 0, states::EXPANDED, states::COLLAPSED), - - // eARIAHasPopup - nsStateMapEntry(&nsGkAtoms::aria_haspopup, kBoolType, - 0, states::HASPOPUP), - - // eARIAInvalid - nsStateMapEntry(&nsGkAtoms::aria_invalid, kBoolType, - 0, states::INVALID), - - // eARIAMultiline - nsStateMapEntry(&nsGkAtoms::aria_multiline, kBoolType, - 0, states::MULTI_LINE, states::SINGLE_LINE, true), - - // eARIAMultiSelectable - nsStateMapEntry(&nsGkAtoms::aria_multiselectable, kBoolType, - 0, states::MULTISELECTABLE | states::EXTSELECTABLE), - - // eARIAOrientation - nsStateMapEntry(&nsGkAtoms::aria_orientation, eUseFirstState, - "horizontal", states::HORIZONTAL, - "vertical", states::VERTICAL), - - // eARIAPressed - nsStateMapEntry(&nsGkAtoms::aria_pressed, kMixedType, - states::CHECKABLE, states::PRESSED), - - // eARIAReadonly - nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType, - 0, states::READONLY), - - // eARIAReadonlyOrEditable - nsStateMapEntry(&nsGkAtoms::aria_readonly, kBoolType, - 0, states::READONLY, states::EDITABLE, true), - - // eARIARequired - nsStateMapEntry(&nsGkAtoms::aria_required, kBoolType, - 0, states::REQUIRED), - - // eARIASelectable - nsStateMapEntry(&nsGkAtoms::aria_selected, kBoolType, - states::SELECTABLE, states::SELECTED, 0, true), - - // eReadonlyUntilEditable - nsStateMapEntry(states::READONLY, states::EDITABLE) -}; - /** * Universal (Global) states: * The following state rules are applied to any accessible element, * whether there is an ARIA role or not: */ -eStateMapEntryID nsARIAMap::gWAIUnivStateMap[] = { +EStateRule nsARIAMap::gWAIUnivStateMap[] = { eARIABusy, eARIADisabled, eARIAExpanded, // Currently under spec review but precedent exists eARIAHasPopup, // Note this is technically a "property" eARIAInvalid, eARIARequired, // XXX not global, Bug 553117 eARIANone }; @@ -741,187 +661,8 @@ nsAttributeCharacteristics nsARIAMap::gW {&nsGkAtoms::aria_sort, ATTR_VALTOKEN }, {&nsGkAtoms::aria_valuenow, ATTR_BYPASSOBJ }, {&nsGkAtoms::aria_valuemin, ATTR_BYPASSOBJ }, {&nsGkAtoms::aria_valuemax, ATTR_BYPASSOBJ }, {&nsGkAtoms::aria_valuetext, ATTR_BYPASSOBJ } }; PRUint32 nsARIAMap::gWAIUnivAttrMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIUnivAttrMap); - - -//////////////////////////////////////////////////////////////////////////////// -// nsStateMapEntry - -nsStateMapEntry::nsStateMapEntry() : - mAttributeName(nsnull), - mIsToken(false), - mPermanentState(0), - mValue1(nsnull), - mState1(0), - mValue2(nsnull), - mState2(0), - mValue3(nsnull), - mState3(0), - mDefaultState(0), - mDefinedIfAbsent(false) -{} - -nsStateMapEntry::nsStateMapEntry(PRUint64 aDefaultState, - PRUint64 aExclusingState) : - mAttributeName(nsnull), - mIsToken(false), - mPermanentState(0), - mValue1(nsnull), - mState1(0), - mValue2(nsnull), - mState2(0), - mValue3(nsnull), - mState3(0), - mDefaultState(aDefaultState), - mDefinedIfAbsent(false), - mExcludingState(aExclusingState) -{ -} - -nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName, eStateValueType aType, - PRUint64 aPermanentState, - PRUint64 aTrueState, - PRUint64 aFalseState, - bool aDefinedIfAbsent) : - mAttributeName(aAttrName), - mIsToken(true), - mPermanentState(aPermanentState), - mValue1("false"), - mState1(aFalseState), - mValue2(nsnull), - mState2(0), - mValue3(nsnull), - mState3(0), - mDefaultState(aTrueState), - mDefinedIfAbsent(aDefinedIfAbsent), - mExcludingState(0) -{ - if (aType == kMixedType) { - mValue2 = "mixed"; - mState2 = states::MIXED; - } -} - -nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName, - const char* aValue1, PRUint64 aState1, - const char* aValue2, PRUint64 aState2, - const char* aValue3, PRUint64 aState3) : - mAttributeName(aAttrName), mIsToken(false), mPermanentState(0), - mValue1(aValue1), mState1(aState1), - mValue2(aValue2), mState2(aState2), - mValue3(aValue3), mState3(aState3), - mDefaultState(0), mDefinedIfAbsent(false), mExcludingState(0) -{ -} - -nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName, - EDefaultStateRule aDefaultStateRule, - const char* aValue1, PRUint64 aState1, - const char* aValue2, PRUint64 aState2, - const char* aValue3, PRUint64 aState3) : - mAttributeName(aAttrName), mIsToken(true), mPermanentState(0), - mValue1(aValue1), mState1(aState1), - mValue2(aValue2), mState2(aState2), - mValue3(aValue3), mState3(aState3), - mDefaultState(0), mDefinedIfAbsent(true), mExcludingState(0) -{ - if (aDefaultStateRule == eUseFirstState) - mDefaultState = aState1; -} - -bool -nsStateMapEntry::MapToStates(nsIContent* aContent, PRUint64* aState, - eStateMapEntryID aStateMapEntryID) -{ - // Return true if we should continue. - if (aStateMapEntryID == eARIANone) - return false; - - const nsStateMapEntry& entry = nsARIAMap::gWAIStateMap[aStateMapEntryID]; - - // Non ARIA attribute case. Expose default state until excluding state is - // presented. - if (!entry.mAttributeName) { - if (!(*aState & entry.mExcludingState)) - *aState |= entry.mDefaultState; - - return true; - } - - if (entry.mIsToken) { - // If attribute is considered as defined when it's absent then let's act - // attribute value is "false" supposedly. - bool hasAttr = aContent->HasAttr(kNameSpaceID_None, *entry.mAttributeName); - if (entry.mDefinedIfAbsent && !hasAttr) { - if (entry.mPermanentState) - *aState |= entry.mPermanentState; - if (entry.mState1) - *aState |= entry.mState1; - return true; - } - - // We only have attribute state mappings for NMTOKEN (and boolean) based - // ARIA attributes. According to spec, a value of "undefined" is to be - // treated equivalent to "", or the absence of the attribute. We bail out - // for this case here. - // Note: If this method happens to be called with a non-token based - // attribute, for example: aria-label="" or aria-label="undefined", we will - // bail out and not explore a state mapping, which is safe. - if (!hasAttr || - aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName, - nsGkAtoms::_empty, eCaseMatters) || - aContent->AttrValueIs(kNameSpaceID_None, *entry.mAttributeName, - nsGkAtoms::_undefined, eCaseMatters)) { - - if (entry.mPermanentState) - *aState &= ~entry.mPermanentState; - return true; - } - - if (entry.mPermanentState) - *aState |= entry.mPermanentState; - } - - nsAutoString attrValue; - if (!aContent->GetAttr(kNameSpaceID_None, *entry.mAttributeName, attrValue)) - return true; - - // Apply states for matched value. If no values was matched then apply default - // states. - bool applyDefaultStates = true; - if (entry.mValue1) { - if (attrValue.EqualsASCII(entry.mValue1)) { - applyDefaultStates = false; - - if (entry.mState1) - *aState |= entry.mState1; - } else if (entry.mValue2) { - if (attrValue.EqualsASCII(entry.mValue2)) { - applyDefaultStates = false; - - if (entry.mState2) - *aState |= entry.mState2; - - } else if (entry.mValue3) { - if (attrValue.EqualsASCII(entry.mValue3)) { - applyDefaultStates = false; - - if (entry.mState3) - *aState |= entry.mState3; - - } - } - } - } - - if (applyDefaultStates) { - if (entry.mDefaultState) - *aState |= entry.mDefaultState; - } - - return true; -}
--- a/accessible/src/base/nsARIAMap.h +++ b/accessible/src/base/nsARIAMap.h @@ -35,16 +35,17 @@ * 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 _nsARIAMap_H_ #define _nsARIAMap_H_ +#include "mozilla/a11y/ARIAStateMap.h" #include "mozilla/a11y/Role.h" #include "prtypes.h" class nsIAtom; class nsIContent; //////////////////////////////////////////////////////////////////////////////// // Value constants @@ -148,136 +149,22 @@ struct nsAttributeCharacteristics // State map entry /** * Used in nsRoleMapEntry.state if no nsIAccessibleStates are automatic for * a given role. */ #define kNoReqStates 0 -enum eStateValueType -{ - kBoolType, - kMixedType -}; - enum EDefaultStateRule { //eNoDefaultState, eUseFirstState }; -/** - * ID for state map entry, used in nsRoleMapEntry. - */ -enum eStateMapEntryID -{ - eARIANone, - eARIAAutoComplete, - eARIABusy, - eARIACheckableBool, - eARIACheckableMixed, - eARIACheckedMixed, - eARIADisabled, - eARIAExpanded, - eARIAHasPopup, - eARIAInvalid, - eARIAMultiline, - eARIAMultiSelectable, - eARIAOrientation, - eARIAPressed, - eARIAReadonly, - eARIAReadonlyOrEditable, - eARIARequired, - eARIASelectable, - eReadonlyUntilEditable -}; - -class nsStateMapEntry -{ -public: - /** - * Used to create stub. - */ - nsStateMapEntry(); - - /** - * Used to expose permanent states presented until accessible has an excluding - * state. - */ - nsStateMapEntry(PRUint64 aDefaultState, PRUint64 aExclusingState); - - /** - * Used for ARIA attributes having boolean or mixed values. - */ - nsStateMapEntry(nsIAtom** aAttrName, eStateValueType aType, - PRUint64 aPermanentState, - PRUint64 aTrueState, - PRUint64 aFalseState = 0, - bool aDefinedIfAbsent = false); - - /** - * Used for ARIA attributes having enumerated values. - */ - nsStateMapEntry(nsIAtom** aAttrName, - const char* aValue1, PRUint64 aState1, - const char* aValue2, PRUint64 aState2, - const char* aValue3 = 0, PRUint64 aState3 = 0); - - /** - * Used for ARIA attributes having enumerated values, and where a default - * attribute state should be assumed when not supplied by the author. - */ - nsStateMapEntry(nsIAtom** aAttrName, EDefaultStateRule aDefaultStateRule, - const char* aValue1, PRUint64 aState1, - const char* aValue2, PRUint64 aState2, - const char* aValue3 = 0, PRUint64 aState3 = 0); - - /** - * Maps ARIA state map pointed by state map entry ID to accessible states. - * - * @param aContent [in] node of the accessible - * @param aState [in/out] accessible states - * @param aStateMapEntryID [in] state map entry ID - * @return true if state map entry ID is valid - */ - static bool MapToStates(nsIContent* aContent, PRUint64* aState, - eStateMapEntryID aStateMapEntryID); - -private: - // ARIA attribute name - nsIAtom** mAttributeName; - - // Indicates if attribute is token (can be undefined) - bool mIsToken; - - // State applied always if attribute is defined - PRUint64 mPermanentState; - - // States applied if attribute value is matched to the stored value - const char* mValue1; - PRUint64 mState1; - - const char* mValue2; - PRUint64 mState2; - - const char* mValue3; - PRUint64 mState3; - - // States applied if no stored values above are matched - PRUint64 mDefaultState; - - // Permanent and false states are applied if attribute is absent - bool mDefinedIfAbsent; - - // If this state is presented in state bits then default state is not exposed. - PRUint64 mExcludingState; -}; - - //////////////////////////////////////////////////////////////////////////////// // Role map entry /** * For each ARIA role, this maps the nsIAccessible information. */ struct nsRoleMapEntry { @@ -297,25 +184,25 @@ struct nsRoleMapEntry EActionRule actionRule; // 'live' and 'container-live' object attributes mapping rule: how to expose // these object attributes if ARIA 'live' attribute is missed. ELiveAttrRule liveAttRule; // Automatic state mapping rule: always include in nsIAccessibleStates PRUint64 state; // or kNoReqStates if no nsIAccessibleStates are automatic for this role. - + // ARIA properties supported for this role // (in other words, the aria-foo attribute to nsIAccessibleStates mapping rules) // Currently you cannot have unlimited mappings, because // a variable sized array would not allow the use of // C++'s struct initialization feature. - eStateMapEntryID attributeMap1; - eStateMapEntryID attributeMap2; - eStateMapEntryID attributeMap3; + mozilla::a11y::aria::EStateRule attributeMap1; + mozilla::a11y::aria::EStateRule attributeMap2; + mozilla::a11y::aria::EStateRule attributeMap3; }; //////////////////////////////////////////////////////////////////////////////// // ARIA map /** * These are currently initialized (hardcoded) in nsARIAMap.cpp, @@ -339,40 +226,36 @@ struct nsARIAMap /** * Empty role map entry. Used by accessibility service to create an accessible * if the accessible can't use role of used accessible class. For example, * it is used for table cells that aren't contained by table. */ static nsRoleMapEntry gEmptyRoleMap; /** - * State map of ARIA state attributes. - */ - static nsStateMapEntry gWAIStateMap[]; - - /** * State map of ARIA states applied to any accessible not depending on * the role. */ - static eStateMapEntryID gWAIUnivStateMap[]; - + static mozilla::a11y::aria::EStateRule gWAIUnivStateMap[]; + /** * Map of attribute to attribute characteristics. */ static nsAttributeCharacteristics gWAIUnivAttrMap[]; static PRUint32 gWAIUnivAttrMapLength; /** * Return accessible state from ARIA universal states applied to the given * element. */ - static PRUint64 UniversalStatesFor(nsIContent* aContent) + static PRUint64 UniversalStatesFor(mozilla::dom::Element* aElement) { PRUint64 state = 0; PRUint32 index = 0; - while (nsStateMapEntry::MapToStates(aContent, &state, gWAIUnivStateMap[index])) + while (mozilla::a11y::aria::MapToState(gWAIUnivStateMap[index], + aElement, &state)) index++; return state; } }; #endif
--- a/accessible/src/base/nsAccDocManager.cpp +++ b/accessible/src/base/nsAccDocManager.cpp @@ -36,17 +36,16 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsAccDocManager.h" #include "nsAccessibilityService.h" #include "nsAccUtils.h" #include "nsApplicationAccessible.h" -#include "nsOuterDocAccessible.h" #include "nsRootAccessibleWrap.h" #include "States.h" #include "nsCURILoader.h" #include "nsDocShellLoadTypes.h" #include "nsIChannel.h" #include "nsIContentViewer.h" #include "nsIDOMDocument.h"
--- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -74,17 +74,16 @@ #include "nsIHTMLDocument.h" #include "nsImageFrame.h" #include "nsILink.h" #include "nsIObserverService.h" #include "nsLayoutUtils.h" #include "nsNPAPIPluginInstance.h" #include "nsISupportsUtils.h" #include "nsObjectFrame.h" -#include "nsOuterDocAccessible.h" #include "nsRootAccessibleWrap.h" #include "nsTextFragment.h" #include "mozilla/Services.h" #include "nsEventStates.h" #ifdef MOZ_XUL #include "nsXULAlertAccessible.h" #include "nsXULColorPickerAccessible.h" @@ -105,16 +104,17 @@ // For embedding plugin accessibles #ifdef MOZ_ACCESSIBILITY_ATK #include "AtkSocketAccessible.h" #endif #include "nsXFormsFormControlsAccessible.h" #include "nsXFormsWidgetsAccessible.h" +#include "OuterDocAccessible.h" #include "mozilla/FunctionTimer.h" #include "mozilla/dom/Element.h" using namespace mozilla; using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// @@ -205,19 +205,19 @@ nsAccessibilityService::GetRootDocumentA } return nsnull; } already_AddRefed<nsAccessible> nsAccessibilityService::CreateOuterDocAccessible(nsIContent* aContent, nsIPresShell* aPresShell) { - nsAccessible* accessible = - new nsOuterDocAccessible(aContent, - nsAccUtils::GetDocAccessibleFor(aPresShell)); + nsAccessible* accessible = + new OuterDocAccessible(aContent, + nsAccUtils::GetDocAccessibleFor(aPresShell)); NS_ADDREF(accessible); return accessible; } already_AddRefed<nsAccessible> nsAccessibilityService::CreateHTMLButtonAccessible(nsIContent* aContent, nsIPresShell* aPresShell) { @@ -1351,17 +1351,17 @@ nsAccessibilityService::CreateAccessible return nsnull; PRInt32 type; nsresult rv = accessibleProvider->GetAccessibleType(&type); if (NS_FAILED(rv)) return nsnull; if (type == nsIAccessibleProvider::OuterDoc) { - nsAccessible* accessible = new nsOuterDocAccessible(aContent, aDoc); + nsAccessible* accessible = new OuterDocAccessible(aContent, aDoc); NS_IF_ADDREF(accessible); return accessible; } nsAccessible* accessible = nsnull; switch (type) { #ifdef MOZ_XUL
--- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -816,17 +816,17 @@ nsAccessible::ChildAtPoint(PRInt32 aX, P if (!accessible) return fallbackAnswer; if (accessible == this) { // Manually walk through accessible children and see if the are within this // point. Skip offscreen or invisible accessibles. This takes care of cases // where layout won't walk into things for us, such as image map areas and // sub documents (XXX: subdocuments should be handled by methods of - // nsOuterDocAccessibles). + // OuterDocAccessibles). PRInt32 childCount = GetChildCount(); for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) { nsAccessible *child = GetChildAt(childIdx); PRInt32 childX, childY, childWidth, childHeight; child->GetBounds(&childX, &childY, &childWidth, &childHeight); if (aX >= childX && aX < childX + childWidth && aY >= childY && aY < childY + childHeight && @@ -1604,18 +1604,23 @@ nsAccessible::State() } return state; } void nsAccessible::ApplyARIAState(PRUint64* aState) { + if (!mContent->IsElement()) + return; + + dom::Element* element = mContent->AsElement(); + // Test for universal states first - *aState |= nsARIAMap::UniversalStatesFor(mContent); + *aState |= nsARIAMap::UniversalStatesFor(element); if (mRoleMapEntry) { // We only force the readonly bit off if we have a real mapping for the aria // role. This preserves the ability for screen readers to use readonly // (primarily on the document) as the hint for creating a virtual buffer. if (mRoleMapEntry->role != roles::NOTHING) *aState &= ~states::READONLY; @@ -1645,27 +1650,22 @@ nsAccessible::ApplyARIAState(PRUint64* a } } } if (!mRoleMapEntry) return; *aState |= mRoleMapEntry->state; - if (nsStateMapEntry::MapToStates(mContent, aState, - mRoleMapEntry->attributeMap1) && - nsStateMapEntry::MapToStates(mContent, aState, - mRoleMapEntry->attributeMap2)) { - nsStateMapEntry::MapToStates(mContent, aState, - mRoleMapEntry->attributeMap3); - } + + if (aria::MapToState(mRoleMapEntry->attributeMap1, element, aState) && + aria::MapToState(mRoleMapEntry->attributeMap2, element, aState)) + aria::MapToState(mRoleMapEntry->attributeMap3, element, aState); } -// Not implemented by this class - /* DOMString getValue (); */ NS_IMETHODIMP nsAccessible::GetValue(nsAString& aValue) { if (IsDefunct()) return NS_ERROR_FAILURE; if (mRoleMapEntry) { @@ -2820,19 +2820,19 @@ bool nsAccessible::IsSelect() { // If we have an ARIA role attribute present and the role allows multi // selectable state, then we need to support SelectAccessible interface. If // either attribute (role or multiselectable) change, then we'll destroy this // accessible so that we can follow COM identity rules. return mRoleMapEntry && - (mRoleMapEntry->attributeMap1 == eARIAMultiSelectable || - mRoleMapEntry->attributeMap2 == eARIAMultiSelectable || - mRoleMapEntry->attributeMap3 == eARIAMultiSelectable); + (mRoleMapEntry->attributeMap1 == aria::eARIAMultiSelectable || + mRoleMapEntry->attributeMap2 == aria::eARIAMultiSelectable || + mRoleMapEntry->attributeMap3 == aria::eARIAMultiSelectable); } already_AddRefed<nsIArray> nsAccessible::SelectedItems() { nsCOMPtr<nsIMutableArray> selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID); if (!selectedItems) return nsnull;
--- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -59,17 +59,16 @@ class AccEvent; class AccGroupInfo; class EmbeddedObjCollector; class KeyBinding; class nsAccessible; class nsHyperTextAccessible; class nsHTMLImageAccessible; class nsHTMLImageMapAccessible; class nsHTMLLIAccessible; -struct nsRoleMapEntry; class Relation; namespace mozilla { namespace a11y { class TableAccessible; } } class nsTextAccessible; class nsXULTreeAccessible;
--- a/accessible/src/base/nsFormControlAccessible.cpp +++ b/accessible/src/base/nsFormControlAccessible.cpp @@ -75,16 +75,32 @@ NS_IMPL_QUERY_INTERFACE_INHERITED1(Progr template<int Max> role ProgressMeterAccessible<Max>::NativeRole() { return roles::PROGRESSBAR; } +template<int Max> +PRUint64 +ProgressMeterAccessible<Max>::NativeState() +{ + PRUint64 state = nsFormControlAccessible::NativeState(); + + // An undetermined progressbar (i.e. without a value) has a mixed state. + nsAutoString attrValue; + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue); + + if (attrValue.IsEmpty()) + state |= states::MIXED; + + return state; +} + //////////////////////////////////////////////////////////////////////////////// // ProgressMeterAccessible<Max>: Widgets template<int Max> bool ProgressMeterAccessible<Max>::IsWidget() const { return true;
--- a/accessible/src/base/nsFormControlAccessible.h +++ b/accessible/src/base/nsFormControlAccessible.h @@ -58,16 +58,17 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIACCESSIBLEVALUE // nsIAccessible NS_IMETHOD GetValue(nsAString &aValue); // nsAccessible virtual mozilla::a11y::role NativeRole(); + virtual PRUint64 NativeState(); // Widgets virtual bool IsWidget() const; }; /** * Generic class used for radio buttons. */
new file mode 100644 --- /dev/null +++ b/accessible/src/generic/Makefile.in @@ -0,0 +1,31 @@ +# 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/. + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = accessibility +LIBRARY_NAME = accessibility_generic_s +LIBXUL_LIBRARY = 1 + + +CPPSRCS = \ + OuterDocAccessible.cpp \ + $(NULL) + +# we don't want the shared lib, but we want to force the creation of a static lib. +FORCE_STATIC_LIB = 1 + +include $(topsrcdir)/config/rules.mk + +LOCAL_INCLUDES = \ + -I$(srcdir)/../xpcom \ + -I$(srcdir)/../base \ + -I$(srcdir)/../../../layout/generic \ + -I$(srcdir)/../../../layout/xul/base/src \ + $(NULL)
rename from accessible/src/base/nsOuterDocAccessible.cpp rename to accessible/src/generic/OuterDocAccessible.cpp --- a/accessible/src/base/nsOuterDocAccessible.cpp +++ b/accessible/src/generic/OuterDocAccessible.cpp @@ -31,53 +31,58 @@ * 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 "nsOuterDocAccessible.h" +#include "OuterDocAccessible.h" #include "nsAccUtils.h" #include "nsDocAccessible.h" #include "Role.h" #include "States.h" +using namespace mozilla; using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// -// nsOuterDocAccessible +// OuterDocAccessible //////////////////////////////////////////////////////////////////////////////// -nsOuterDocAccessible:: - nsOuterDocAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : +OuterDocAccessible:: + OuterDocAccessible(nsIContent* aContent, nsDocAccessible* aDoc) : nsAccessibleWrap(aContent, aDoc) { } +OuterDocAccessible::~OuterDocAccessible() +{ +} + //////////////////////////////////////////////////////////////////////////////// // nsISupports -NS_IMPL_ISUPPORTS_INHERITED0(nsOuterDocAccessible, +NS_IMPL_ISUPPORTS_INHERITED0(OuterDocAccessible, nsAccessible) //////////////////////////////////////////////////////////////////////////////// // nsAccessible public (DON'T add methods here) role -nsOuterDocAccessible::NativeRole() +OuterDocAccessible::NativeRole() { return roles::INTERNAL_FRAME; } nsAccessible* -nsOuterDocAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY, - EWhichChildAtPoint aWhichChild) +OuterDocAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY, + EWhichChildAtPoint aWhichChild) { PRInt32 docX = 0, docY = 0, docWidth = 0, docHeight = 0; nsresult rv = GetBounds(&docX, &docY, &docWidth, &docHeight); NS_ENSURE_SUCCESS(rv, nsnull); if (aX < docX || aX >= docX + docWidth || aY < docY || aY >= docY + docHeight) return nsnull; @@ -87,103 +92,104 @@ nsOuterDocAccessible::ChildAtPoint(PRInt NS_ENSURE_TRUE(child, nsnull); if (aWhichChild == eDeepestChild) return child->ChildAtPoint(aX, aY, eDeepestChild); return child; } nsresult -nsOuterDocAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes) +OuterDocAccessible::GetAttributesInternal(nsIPersistentProperties* aAttributes) { nsAutoString tag; aAttributes->GetStringProperty(NS_LITERAL_CSTRING("tag"), tag); if (!tag.IsEmpty()) { // We're overriding the ARIA attributes on an sub document, but we don't want to // override the other attributes return NS_OK; } return nsAccessible::GetAttributesInternal(aAttributes); } //////////////////////////////////////////////////////////////////////////////// // nsIAccessible PRUint8 -nsOuterDocAccessible::ActionCount() +OuterDocAccessible::ActionCount() { // Internal frame, which is the doc's parent, should not have a click action. return 0; } NS_IMETHODIMP -nsOuterDocAccessible::GetActionName(PRUint8 aIndex, nsAString& aName) +OuterDocAccessible::GetActionName(PRUint8 aIndex, nsAString& aName) { aName.Truncate(); return NS_ERROR_INVALID_ARG; } NS_IMETHODIMP -nsOuterDocAccessible::GetActionDescription(PRUint8 aIndex, nsAString& aDescription) +OuterDocAccessible::GetActionDescription(PRUint8 aIndex, + nsAString& aDescription) { aDescription.Truncate(); return NS_ERROR_INVALID_ARG; } NS_IMETHODIMP -nsOuterDocAccessible::DoAction(PRUint8 aIndex) +OuterDocAccessible::DoAction(PRUint8 aIndex) { return NS_ERROR_INVALID_ARG; } //////////////////////////////////////////////////////////////////////////////// // nsAccessNode public void -nsOuterDocAccessible::Shutdown() +OuterDocAccessible::Shutdown() { // XXX: sometimes outerdoc accessible is shutdown because of layout style // change however the presshell of underlying document isn't destroyed and // the document doesn't get pagehide events. Shutdown underlying document if // any to avoid hanging document accessible. NS_LOG_ACCDOCDESTROY_MSG("A11y outerdoc shutdown") NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this) - nsAccessible *childAcc = mChildren.SafeElementAt(0, nsnull); + nsAccessible* childAcc = mChildren.SafeElementAt(0, nsnull); if (childAcc) { NS_LOG_ACCDOCDESTROY("outerdoc's child document shutdown", childAcc->GetDocumentNode()) childAcc->Shutdown(); } nsAccessibleWrap::Shutdown(); } //////////////////////////////////////////////////////////////////////////////// // nsAccessible public void -nsOuterDocAccessible::InvalidateChildren() +OuterDocAccessible::InvalidateChildren() { // Do not invalidate children because nsAccDocManager is responsible for // document accessible lifetime when DOM document is created or destroyed. If // DOM document isn't destroyed but its presshell is destroyed (for example, // when DOM node of outerdoc accessible is hidden), then outerdoc accessible // notifies nsAccDocManager about this. If presshell is created for existing // DOM document (for example when DOM node of outerdoc accessible is shown) // then allow nsAccDocManager to handle this case since the document // accessible is created and appended as a child when it's requested. SetChildrenFlag(eChildrenUninitialized); } bool -nsOuterDocAccessible::AppendChild(nsAccessible *aAccessible) +OuterDocAccessible::AppendChild(nsAccessible* aAccessible) { // We keep showing the old document for a bit after creating the new one, // and while building the new DOM and frame tree. That's done on purpose // to avoid weird flashes of default background color. // The old viewer will be destroyed after the new one is created. // For a11y, it should be safe to shut down the old document now. if (mChildren.Length()) mChildren[0]->Shutdown(); @@ -194,19 +200,19 @@ nsOuterDocAccessible::AppendChild(nsAcce NS_LOG_ACCDOCCREATE("append document to outerdoc", aAccessible->GetDocumentNode()) NS_LOG_ACCDOCCREATE_ACCADDRESS("outerdoc", this) return true; } bool -nsOuterDocAccessible::RemoveChild(nsAccessible *aAccessible) +OuterDocAccessible::RemoveChild(nsAccessible* aAccessible) { - nsAccessible *child = mChildren.SafeElementAt(0, nsnull); + nsAccessible* child = mChildren.SafeElementAt(0, nsnull); if (child != aAccessible) { NS_ERROR("Wrong child to remove!"); return false; } NS_LOG_ACCDOCDESTROY_FOR("remove document from outerdoc", child->GetDocumentNode(), child) NS_LOG_ACCDOCDESTROY_ACCADDRESS("outerdoc", this) @@ -219,17 +225,17 @@ nsOuterDocAccessible::RemoveChild(nsAcce return wasRemoved; } //////////////////////////////////////////////////////////////////////////////// // nsAccessible protected void -nsOuterDocAccessible::CacheChildren() +OuterDocAccessible::CacheChildren() { // Request document accessible for the content document to make sure it's // created. It will appended to outerdoc accessible children asynchronously. nsIDocument* outerDoc = mContent->GetCurrentDoc(); if (outerDoc) { nsIDocument* innerDoc = outerDoc->GetSubDocumentFor(mContent); if (innerDoc) GetAccService()->GetDocAccessible(innerDoc);
rename from accessible/src/base/nsOuterDocAccessible.h rename to accessible/src/generic/OuterDocAccessible.h --- a/accessible/src/base/nsOuterDocAccessible.h +++ b/accessible/src/generic/OuterDocAccessible.h @@ -31,34 +31,38 @@ * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -#ifndef _nsOuterDocAccessible_H_ -#define _nsOuterDocAccessible_H_ +#ifndef MOZILLA_A11Y_OUTERDOCACCESSIBLE_H_ +#define MOZILLA_A11Y_OUTERDOCACCESSIBLE_H_ #include "nsAccessibleWrap.h" +namespace mozilla { +namespace a11y { + /** * Used for <browser>, <frame>, <iframe>, <page> or editor> elements. * - * In these variable names, "outer" relates to the nsOuterDocAccessible as + * In these variable names, "outer" relates to the OuterDocAccessible as * opposed to the nsDocAccessibleWrap which is "inner". The outer node is * a something like tags listed above, whereas the inner node corresponds to * the inner document root. */ -class nsOuterDocAccessible : public nsAccessibleWrap +class OuterDocAccessible : public nsAccessibleWrap { public: - nsOuterDocAccessible(nsIContent* aContent, nsDocAccessible* aDoc); + OuterDocAccessible(nsIContent* aContent, nsDocAccessible* aDoc); + virtual ~OuterDocAccessible(); NS_DECL_ISUPPORTS_INHERITED // nsIAccessible NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName); NS_IMETHOD GetActionDescription(PRUint8 aIndex, nsAString& aDescription); NS_IMETHOD DoAction(PRUint8 aIndex); @@ -78,9 +82,12 @@ public: // ActionAccessible virtual PRUint8 ActionCount(); protected: // nsAccessible virtual void CacheChildren(); }; +} // namespace a11y +} // namespace mozilla + #endif
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp +++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp @@ -427,17 +427,17 @@ NS_IMETHODIMP nsHTMLTextFieldAccessible: return NS_ERROR_FAILURE; } void nsHTMLTextFieldAccessible::ApplyARIAState(PRUint64* aState) { nsHyperTextAccessibleWrap::ApplyARIAState(aState); - nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete); + aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState); } PRUint64 nsHTMLTextFieldAccessible::State() { PRUint64 state = nsHyperTextAccessibleWrap::State(); if (state & states::DEFUNCT) return state;
--- a/accessible/src/mac/mozAccessible.h +++ b/accessible/src/mac/mozAccessible.h @@ -143,19 +143,16 @@ GetObjectOrRepresentedView(id <mozAccess // invalidates and removes all our children from our cached array. - (void)invalidateChildren; /** * Append a child if they are already cached. */ - (void)appendChild:(nsAccessible*)aAccessible; -// invalidates the cached parent, used by invalidateChildren. -- (void)invalidateParent; - // makes ourselves "expired". after this point, we might be around if someone // has retained us (e.g., a third-party), but we really contain no information. - (void)expire; - (BOOL)isExpired; #ifdef DEBUG - (void)printHierarchy; - (void)printHierarchyWithLevel:(unsigned)numSpaces;
--- a/accessible/src/mac/mozAccessible.mm +++ b/accessible/src/mac/mozAccessible.mm @@ -349,36 +349,33 @@ GetNativeFromGeckoAccessible(nsIAccessib } #pragma mark - - (id <mozAccessible>)parent { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - if (mParent) - return mParent; - nsAccessible* accessibleParent = mGeckoAccessible->GetUnignoredParent(); if (accessibleParent) { id nativeParent = GetNativeFromGeckoAccessible(accessibleParent); if (nativeParent) - return mParent = GetClosestInterestingAccessible(nativeParent); + return GetClosestInterestingAccessible(nativeParent); } // GetUnignoredParent() returns null when there is no unignored accessible all the way up to // the root accessible. so we'll have to return whatever native accessible is above our root accessible // (which might be the owning NSWindow in the application, for example). // // get the native root accessible, and tell it to return its first parent unignored accessible. nsRootAccessible* root = mGeckoAccessible->RootAccessible(); id nativeParent = GetNativeFromGeckoAccessible(static_cast<nsIAccessible*>(root)); NSAssert1 (nativeParent, @"!!! we can't find a parent for %@", self); - return mParent = GetClosestInterestingAccessible(nativeParent); + return GetClosestInterestingAccessible(nativeParent); NS_OBJC_END_TRY_ABORT_BLOCK_NIL; } - (BOOL)hasRepresentedView { return NO; } @@ -610,18 +607,16 @@ GetNativeFromGeckoAccessible(nsIAccessib NS_OBJC_END_TRY_ABORT_BLOCK_NIL; } - (void)invalidateChildren { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - [mChildren makeObjectsPerformSelector:@selector(invalidateParent)]; - // make room for new children [mChildren release]; mChildren = nil; NS_OBJC_END_TRY_ABORT_BLOCK; } - (void)appendChild:(nsAccessible*)aAccessible @@ -630,21 +625,16 @@ GetNativeFromGeckoAccessible(nsIAccessib if (!mChildren) return; mozAccessible *curNative = GetNativeFromGeckoAccessible(aAccessible); if (curNative) [mChildren addObject:GetObjectOrRepresentedView(curNative)]; } -- (void)invalidateParent -{ - mParent = nil; -} - - (void)expire { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; [self invalidateChildren]; mIsExpired = YES; NS_OBJC_END_TRY_ABORT_BLOCK;
--- a/accessible/src/mac/nsRoleMap.h +++ b/accessible/src/mac/nsRoleMap.h @@ -137,17 +137,17 @@ static const NSString* AXRoles [] = { NSAccessibilityGroupRole, // roles::TEXT_CONTAINER 92 NSAccessibilityButtonRole, // roles::TOGGLE_BUTTON 93 NSAccessibilityTableRole, // roles::TREE_TABLE 94 NSAccessibilityUnknownRole, // roles::VIEWPORT 95 NSAccessibilityGroupRole, // roles::HEADER 96 NSAccessibilityGroupRole, // roles::FOOTER 97 NSAccessibilityGroupRole, // roles::PARAGRAPH 98 @"AXRuler", // roles::RULER 99 10.4+ only, so we re-define the constant. - NSAccessibilityComboBoxRole, // roles::AUTOCOMPLETE 100 + NSAccessibilityUnknownRole, // roles::AUTOCOMPLETE 100 NSAccessibilityTextFieldRole, // roles::EDITBAR 101 NSAccessibilityTextFieldRole, // roles::ENTRY 102 NSAccessibilityStaticTextRole, // roles::CAPTION 103 NSAccessibilityScrollAreaRole, // roles::DOCUMENT_FRAME 104 @"AXHeading", // roles::HEADING 105 NSAccessibilityGroupRole, // roles::PAGE 106 NSAccessibilityGroupRole, // roles::SECTION 107 NSAccessibilityUnknownRole, // roles::REDUNDANT_OBJECT 108
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp +++ b/accessible/src/xul/nsXULFormControlAccessible.cpp @@ -749,17 +749,17 @@ NS_IMETHODIMP nsXULTextFieldAccessible:: return NS_ERROR_FAILURE; } void nsXULTextFieldAccessible::ApplyARIAState(PRUint64* aState) { nsHyperTextAccessibleWrap::ApplyARIAState(aState); - nsStateMapEntry::MapToStates(mContent, aState, eARIAAutoComplete); + aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState); } PRUint64 nsXULTextFieldAccessible::NativeState() { PRUint64 state = nsHyperTextAccessibleWrap::NativeState();
--- a/accessible/tests/mochitest/Makefile.in +++ b/accessible/tests/mochitest/Makefile.in @@ -96,17 +96,17 @@ include $(topsrcdir)/config/rules.mk test_aria_role_equation.html \ test_aria_roles.html \ test_aria_roles.xul \ test_aria_token_attrs.html \ test_bug420863.html \ test_descr.html \ test_nsIAccessibleDocument.html \ test_nsIAccessibleImage.html \ - test_nsOuterDocAccessible.html \ + test_OuterDocAccessible.html \ test_role_nsHyperTextAcc.html \ test_textboxes.html \ test_textboxes.xul \ testTextboxes.js \ text.js \ treeview.css \ treeview.js \ $(NULL)
--- a/accessible/tests/mochitest/actions/test_select.html +++ b/accessible/tests/mochitest/actions/test_select.html @@ -7,16 +7,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" src="../actions.js"></script> <script type="application/javascript"> //gA11yEventDumpToConsole = true; // debugging
--- a/accessible/tests/mochitest/actions/test_tree.xul +++ b/accessible/tests/mochitest/actions/test_tree.xul @@ -10,16 +10,18 @@ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="../treeview.js" /> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript" src="../actions.js" /> <script type="application/javascript"> <![CDATA[
--- a/accessible/tests/mochitest/actions/test_treegrid.xul +++ b/accessible/tests/mochitest/actions/test_treegrid.xul @@ -12,16 +12,18 @@ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="../treeview.js" /> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript" src="../actions.js" /> <script type="application/javascript"> <![CDATA[
--- a/accessible/tests/mochitest/attributes/test_text.html +++ b/accessible/tests/mochitest/attributes/test_text.html @@ -137,53 +137,44 @@ attrs = {"color": gComputedStyle.color}; testTextAttrs(ID, 9, attrs, defAttrs, 8, 11); // Normal attrs = {}; testTextAttrs(ID, 11, attrs, defAttrs, 11, 18); ////////////////////////////////////////////////////////////////////////// - // area6 (CSS vertical-align property, bug 445938) + // area6 (CSS vertical-align property, refer to bug 445938 for details + // and sup and sub elements, refer to bug 735645 for details) ID = "area6"; defAttrs = buildDefaultTextAttrs(ID, "12pt"); testDefaultTextAttrs(ID, defAttrs); attrs = {}; testTextAttrs(ID, 0, attrs, defAttrs, 0, 5); - tempElem = getNode(ID).firstChild.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"text-position": gComputedStyle.verticalAlign, - "font-size": "10pt"}; + attrs = { "text-position": "super", "font-size": "10pt" }; testTextAttrs(ID, 5, attrs, defAttrs, 5, 13); attrs = {}; testTextAttrs(ID, 13, attrs, defAttrs, 13, 27); - tempElem = tempElem.nextSibling.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"text-position": gComputedStyle.verticalAlign}; + attrs = { "text-position": "super" }; testTextAttrs(ID, 27, attrs, defAttrs, 27, 35); attrs = {}; testTextAttrs(ID, 35, attrs, defAttrs, 35, 39); - tempElem = tempElem.nextSibling.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"text-position": gComputedStyle.verticalAlign, - "font-size": "10pt"}; + attrs = { "text-position": "sub", "font-size": "10pt" }; testTextAttrs(ID, 39, attrs, defAttrs, 39, 50); attrs = {}; testTextAttrs(ID, 50, attrs, defAttrs, 50, 55); - tempElem = tempElem.nextSibling.nextSibling; - gComputedStyle = document.defaultView.getComputedStyle(tempElem, ""); - attrs = {"text-position": gComputedStyle.verticalAlign}; + attrs = { "text-position": "sub" }; testTextAttrs(ID, 55, attrs, defAttrs, 55, 64); attrs = {}; testTextAttrs(ID, 64, attrs, defAttrs, 64, 69); attrs = { "text-position": "super" }; testTextAttrs(ID, 69, attrs, defAttrs, 69, 84); @@ -539,16 +530,21 @@ 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> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=735645" + title="expose sub and sup elements in text attributes"> + Mozilla Bug 735645 + </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;">
--- a/accessible/tests/mochitest/events/test_aria_alert.html +++ b/accessible/tests/mochitest/events/test_aria_alert.html @@ -7,16 +7,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript"> function showAlert(aID) { this.DOMNode = document.createElement("div");
--- a/accessible/tests/mochitest/events/test_aria_menu.html +++ b/accessible/tests/mochitest/events/test_aria_menu.html @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript"> const kViaDisplayStyle = 0; const kViaVisibilityStyle = 1;
--- a/accessible/tests/mochitest/events/test_aria_statechange.html +++ b/accessible/tests/mochitest/events/test_aria_statechange.html @@ -7,16 +7,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript"> /**
--- a/accessible/tests/mochitest/events/test_focus_aria_activedescendant.html +++ b/accessible/tests/mochitest/events/test_focus_aria_activedescendant.html @@ -8,16 +8,18 @@ https://bugzilla.mozilla.org/show_bug.cg <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript"> //gA11yEventDumpToConsole = true; // debugging function changeARIAActiveDescendant(aID, aItemID)
--- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul +++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul @@ -16,16 +16,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript" src="../autocomplete.js" /> <script type="application/javascript">
--- a/accessible/tests/mochitest/events/test_focus_canvas.html +++ b/accessible/tests/mochitest/events/test_focus_canvas.html @@ -11,16 +11,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> //gA11yEventDumpToConsole = true; var gQueue = null; function doTests() {
--- a/accessible/tests/mochitest/events/test_focus_contextmenu.xul +++ b/accessible/tests/mochitest/events/test_focus_contextmenu.xul @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> //gA11yEventDumpID = "eventdump"; // debug stuff //gA11yEventDumpToConsole = true; // debug stuff
--- a/accessible/tests/mochitest/events/test_focus_controls.html +++ b/accessible/tests/mochitest/events/test_focus_controls.html @@ -11,16 +11,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> //gA11yEventDumpToConsole = true; var gQueue = null; function doTests() {
--- a/accessible/tests/mochitest/events/test_focus_dialog.html +++ b/accessible/tests/mochitest/events/test_focus_dialog.html @@ -11,16 +11,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> function openCloseDialog(aID) { this.eventSeq = [ new focusChecker(getNode(aID)) ];
--- a/accessible/tests/mochitest/events/test_focus_doc.html +++ b/accessible/tests/mochitest/events/test_focus_doc.html @@ -10,16 +10,18 @@ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../events.js"></script> + <script type="application/javascript" + src="../role.js"></script> <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> var gQueue = null; //var gA11yEventDumpID = "eventdump"; //gA11yEventDumpToConsole = true;
--- a/accessible/tests/mochitest/events/test_focus_general.xul +++ b/accessible/tests/mochitest/events/test_focus_general.xul @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> function getColorBtn(aBtnObj) { var colorpicker = aBtnObj.colorpicker;
--- a/accessible/tests/mochitest/events/test_focus_listcontrols.xul +++ b/accessible/tests/mochitest/events/test_focus_listcontrols.xul @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> //gA11yEventDumpID = "eventdump"; // debug stuff //gA11yEventDumpToConsole = true; // debug stuff
--- a/accessible/tests/mochitest/events/test_focus_menu.xul +++ b/accessible/tests/mochitest/events/test_focus_menu.xul @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> //gA11yEventDumpID = "eventdump"; // debug stuff //gA11yEventDumpToConsole = true; // debug stuff
--- a/accessible/tests/mochitest/events/test_focus_selects.html +++ b/accessible/tests/mochitest/events/test_focus_selects.html @@ -11,16 +11,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> //gA11yEventDumpID = "eventdump"; // debug stuff //gA11yEventDumpToConsole = true; var gQueue = null;
--- a/accessible/tests/mochitest/events/test_focus_tabbox.xul +++ b/accessible/tests/mochitest/events/test_focus_tabbox.xul @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> //gA11yEventDumpID = "eventdump"; // debug stuff //gA11yEventDumpToConsole = true; // debug stuff
--- a/accessible/tests/mochitest/events/test_focus_tree.xul +++ b/accessible/tests/mochitest/events/test_focus_tree.xul @@ -14,16 +14,18 @@ src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../treeview.js" /> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> <![CDATA[ ////////////////////////////////////////////////////////////////////////////
--- a/accessible/tests/mochitest/events/test_selection.html +++ b/accessible/tests/mochitest/events/test_selection.html @@ -11,16 +11,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> //////////////////////////////////////////////////////////////////////////// // Invokers //////////////////////////////////////////////////////////////////////////// // Do tests
--- a/accessible/tests/mochitest/events/test_selection.xul +++ b/accessible/tests/mochitest/events/test_selection.xul @@ -11,16 +11,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> function advanceTab(aTabsID, aDirection, aNextTabID) { this.eventSeq = [
--- a/accessible/tests/mochitest/events/test_selection_aria.html +++ b/accessible/tests/mochitest/events/test_selection_aria.html @@ -11,16 +11,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> //////////////////////////////////////////////////////////////////////////// // Invokers function selectTreeItem(aTreeID, aItemID) {
--- a/accessible/tests/mochitest/events/test_statechange.html +++ b/accessible/tests/mochitest/events/test_statechange.html @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> //////////////////////////////////////////////////////////////////////////// // Invokers function makeEditableDoc(aDocNode, aIsEnabled) {
--- a/accessible/tests/mochitest/events/test_textattrchange.html +++ b/accessible/tests/mochitest/events/test_textattrchange.html @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript" src="../attributes.js"></script> <script type="application/javascript">
--- a/accessible/tests/mochitest/focus/test_focusedChild.html +++ b/accessible/tests/mochitest/focus/test_focusedChild.html @@ -7,16 +7,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript"> function openWnd() { this.eventSeq = [ new invokerChecker(EVENT_FOCUS,
--- a/accessible/tests/mochitest/focus/test_takeFocus.html +++ b/accessible/tests/mochitest/focus/test_takeFocus.html @@ -7,16 +7,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript"> //////////////////////////////////////////////////////////////////////////// // Invokers
--- a/accessible/tests/mochitest/focus/test_takeFocus.xul +++ b/accessible/tests/mochitest/focus/test_takeFocus.xul @@ -9,16 +9,18 @@ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript" src="../treeview.js" /> <script type="application/javascript">
--- a/accessible/tests/mochitest/states.js +++ b/accessible/tests/mochitest/states.js @@ -1,13 +1,14 @@ //////////////////////////////////////////////////////////////////////////////// // Helper functions for accessible states testing. // // requires: // common.js +// role.js // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // State constants // const STATE_BUSY is defined in common.js const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED; @@ -66,17 +67,17 @@ const kExtraState = 1; * @param aAbsentState State bits that are not wanted. * @param aAbsentExtraState Extra state bits that are not wanted. * @param aTestName The test name. */ function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState, aAbsentExtraState, aTestName) { var [state, extraState] = getStates(aAccOrElmOrID); - + var role = getRole(aAccOrElmOrID); var id = prettyName(aAccOrElmOrID) + (aTestName ? " [" + aTestName + "]": ""); // Primary test. isState(state & aState, aState, false, "wrong state bits for " + id + "!"); if (aExtraState) isState(extraState & aExtraState, aExtraState, true, @@ -130,17 +131,17 @@ function testStates(aAccOrElmOrID, aStat "Not expanded " + id + " must be collapsed!"); } else if (aAbsentState & STATE_COLLAPSED) { isState(state & STATE_EXPANDED, STATE_EXPANDED, false, "Not collapsed " + id + " must be expanded!"); } } // checked/mixed/checkable - if (state & STATE_CHECKED || state & STATE_MIXED) + if (state & STATE_CHECKED || state & STATE_MIXED && role != ROLE_PROGRESSBAR) isState(state & STATE_CHECKABLE, STATE_CHECKABLE, false, "Checked or mixed element must be checkable!"); if (state & STATE_CHECKED) isState(state & STATE_MIXED, 0, false, "Checked element cannot be state mixed!"); if (state & STATE_MIXED)
--- a/accessible/tests/mochitest/states/Makefile.in +++ b/accessible/tests/mochitest/states/Makefile.in @@ -45,16 +45,17 @@ relativesrcdir = accessible/states include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk _TEST_FILES =\ test_aria.html \ test_aria_imgmap.html \ test_aria_widgetitems.html \ test_buttons.html \ + test_controls.html \ test_controls.xul \ test_doc.html \ test_docarticle.html \ test_editablebody.html \ test_expandable.xul \ test_frames.html \ test_inputs.html \ test_link.html \
--- a/accessible/tests/mochitest/states/test_aria_widgetitems.html +++ b/accessible/tests/mochitest/states/test_aria_widgetitems.html @@ -8,16 +8,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript"> function focusARIAItem(aID, aIsSelected) { this.DOMNode = getNode(aID);
--- a/accessible/tests/mochitest/states/test_buttons.html +++ b/accessible/tests/mochitest/states/test_buttons.html @@ -6,16 +6,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> function doTest() { // Default state. testStates("f1_image", STATE_DEFAULT | STATE_FOCUSABLE); testStates("f2_submit", STATE_DEFAULT | STATE_FOCUSABLE);
new file mode 100644 --- /dev/null +++ b/accessible/tests/mochitest/states/test_controls.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html> +<head> + <title>HTML control states</title> + <link rel="stylesheet" type="text/css" + href="chrome://mochikit/content/tests/SimpleTest/test.css" /> + + <script type="application/javascript" + src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + + <script type="application/javascript" + src="../common.js"></script> + <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" + src="../states.js"></script> + + <script type="application/javascript"> + function doTest() + { + // Undetermined progressbar (no value or aria-value attribute): mixed state + testStates("progress", STATE_MIXED); + // Determined progressbar (has value): shouldn't have mixed state + testStates("progress2", 0, 0, STATE_MIXED); + // Determined progressbar (has aria-value): shouldn't have mixed state + // testStates("progress3", 0, 0, STATE_MIXED); + todo(false, "we should respect ARIA"); + + SimpleTest.finish(); + } + + SimpleTest.waitForExplicitFinish(); + addA11yLoadEvent(doTest); + </script> +</head> + +<body> + <a target="_blank" + href="https://bugzilla.mozilla.org/show_bug.cgi?id=670853" + title="Bug 670853 - undetermined progressmeters should expose mixed state"> + Mozilla Bug 670853 + </a> + <p id="display"></p> + <div id="content" style="display: none"></div> + <pre id="test"> + </pre> + + <progress id="progress"></progress> + <progress id="progress2" value="1"></progress> + <progress id="progress3" aria-valuenow="1"></progress> + +</body> +</html>
--- a/accessible/tests/mochitest/states/test_controls.xul +++ b/accessible/tests/mochitest/states/test_controls.xul @@ -7,16 +7,18 @@ title="Accessible XUL input control state tests"> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript"> <![CDATA[ function doTest() { testStates("checkbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
--- a/accessible/tests/mochitest/states/test_doc.html +++ b/accessible/tests/mochitest/states/test_doc.html @@ -6,16 +6,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> function doTest() { // Bug 566542: root accesible should expose active state when focused. testStates(getRootAccessible(), 0, EXT_STATE_ACTIVE);
--- a/accessible/tests/mochitest/states/test_docarticle.html +++ b/accessible/tests/mochitest/states/test_docarticle.html @@ -6,16 +6,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> function doTest() { var docAcc = getAccessible(document, [nsIAccessibleDocument]); if (docAcc) { testStates(docAcc, STATE_READONLY);
--- a/accessible/tests/mochitest/states/test_editablebody.html +++ b/accessible/tests/mochitest/states/test_editablebody.html @@ -8,16 +8,18 @@ https://bugzilla.mozilla.org/show_bug.cg <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> function doTest() { testStates(document, 0, EXT_STATE_EDITABLE); testStates("p", 0, EXT_STATE_EDITABLE);
--- a/accessible/tests/mochitest/states/test_expandable.xul +++ b/accessible/tests/mochitest/states/test_expandable.xul @@ -19,16 +19,18 @@ src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" /> <script type="application/javascript" src="../autocomplete.js" /> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> <![CDATA[ //gA11yEventDumpToConsole = true; // debuggin
--- a/accessible/tests/mochitest/states/test_frames.html +++ b/accessible/tests/mochitest/states/test_frames.html @@ -7,16 +7,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> function doTest() { frameDoc = document.getElementById("frame_doc").contentDocument; frameDocArticle = document.getElementById("frame_doc_article").contentDocument; frameDocCheckbox = document.getElementById("frame_doc_checkbox").contentDocument;
--- a/accessible/tests/mochitest/states/test_inputs.html +++ b/accessible/tests/mochitest/states/test_inputs.html @@ -6,16 +6,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> function doTest() { //////////////////////////////////////////////////////////////////////////// // 'editable' and 'multiline' states. testStates("input", 0, EXT_STATE_EDITABLE, 0, EXT_STATE_MULTI_LINE); @@ -102,16 +104,17 @@ //////////////////////////////////////////////////////////////////////////// // autocomplete states testStates("autocomplete-default", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION); testStates("autocomplete-off", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION); testStates("autocomplete-formoff", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION); testStates("autocomplete-list", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION); testStates("autocomplete-list2", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION); + testStates("autocomplete-tel", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION); SimpleTest.finish(); } SimpleTest.waitForExplicitFinish(); addA11yLoadEvent(doTest); </script> </head> @@ -225,11 +228,12 @@ <input id="autocomplete-formoff"> </form> <datalist id="cities"> <option>Paris</option> <option>San Francisco</option> </datalist> <input id="autocomplete-list" list="cities"> <input id="autocomplete-list2" list="cities" autocomplete="off"> + <input id="autocomplete-tel" type="tel"> </body> </html>
--- a/accessible/tests/mochitest/states/test_popup.xul +++ b/accessible/tests/mochitest/states/test_popup.xul @@ -7,16 +7,18 @@ title="XUL popup attribute test"> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript"> <![CDATA[ function doTest() { // label with popup testStates("labelWithPopup", STATE_HASPOPUP);
--- a/accessible/tests/mochitest/states/test_selects.html +++ b/accessible/tests/mochitest/states/test_selects.html @@ -5,16 +5,18 @@ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript"> function doTest() { // combobox var combobox = getAccessible("combobox"); testStates(combobox,
--- a/accessible/tests/mochitest/states/test_stale.html +++ b/accessible/tests/mochitest/states/test_stale.html @@ -6,16 +6,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../events.js"></script> <script type="application/javascript"> function addChild(aContainerID) { this.containerNode = getNode(aContainerID);
--- a/accessible/tests/mochitest/states/test_tree.xul +++ b/accessible/tests/mochitest/states/test_tree.xul @@ -12,16 +12,18 @@ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" /> <script type="application/javascript" src="../treeview.js" /> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript"> <![CDATA[ //////////////////////////////////////////////////////////////////////////// // Test
--- a/accessible/tests/mochitest/table/test_sels_ariagrid.html +++ b/accessible/tests/mochitest/table/test_sels_ariagrid.html @@ -9,16 +9,18 @@ https://bugzilla.mozilla.org/show_bug.cg href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../table.js"></script> <script type="application/javascript"> function doTest() { //////////////////////////////////////////////////////////////////////////
--- a/accessible/tests/mochitest/table/test_sels_table.html +++ b/accessible/tests/mochitest/table/test_sels_table.html @@ -7,16 +7,18 @@ href="chrome://mochikit/content/tests/SimpleTest/test.css" /> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="../common.js"></script> <script type="application/javascript" + src="../role.js"></script> + <script type="application/javascript" src="../states.js"></script> <script type="application/javascript" src="../table.js"></script> <script type="text/javascript"> function doTest() {
--- a/accessible/tests/mochitest/table/test_sels_tree.xul +++ b/accessible/tests/mochitest/table/test_sels_tree.xul @@ -12,16 +12,18 @@ <script type="application/javascript" src="../treeview.js" /> <script type="application/javascript" src="../common.js" /> <script type="application/javascript" src="../events.js" /> <script type="application/javascript" + src="../role.js" /> + <script type="application/javascript" src="../states.js" /> <script type="application/javascript" src="../table.js" /> <script type="application/javascript"> <![CDATA[ //////////////////////////////////////////////////////////////////////////// // Test
rename from accessible/tests/mochitest/test_nsOuterDocAccessible.html rename to accessible/tests/mochitest/test_OuterDocAccessible.html
--- a/accessible/tests/mochitest/tree/test_txtctrl.html +++ b/accessible/tests/mochitest/tree/test_txtctrl.html @@ -71,16 +71,29 @@ { role: ROLE_TEXT_LEAF, children: [] } ] }; testAccessibleTree("txc5", accTree); + + // input@type="tel", value + accTree = { + role: ROLE_ENTRY, + children: [ + { // text child + role: ROLE_TEXT_LEAF, + children: [] + } + ] + }; + + testAccessibleTree("txc6", accTree); SimpleTest.finish(); } SimpleTest.waitForExplicitFinish(); addA11yLoadEvent(doTest); </script> </head> @@ -112,11 +125,12 @@ </div> <input id="txc2" value="hello"> <input id="txc3"> <textarea id="txc4"> hello1 hello2 </textarea> <input id="txc5" type="password" value="hello"> + <input id="txc6" type="tel" value="4167771234"> </body> </html>
--- a/aclocal.m4 +++ b/aclocal.m4 @@ -2,17 +2,16 @@ dnl dnl Local autoconf macros used with mozilla dnl The contents of this file are under the Public Domain. dnl builtin(include, build/autoconf/glib.m4)dnl builtin(include, build/autoconf/nspr.m4)dnl builtin(include, build/autoconf/nss.m4)dnl builtin(include, build/autoconf/pkg.m4)dnl -builtin(include, build/autoconf/freetype2.m4)dnl builtin(include, build/autoconf/codeset.m4)dnl builtin(include, build/autoconf/altoptions.m4)dnl builtin(include, build/autoconf/mozprog.m4)dnl builtin(include, build/autoconf/mozheader.m4)dnl builtin(include, build/autoconf/mozcommonheader.m4)dnl builtin(include, build/autoconf/acwinpaths.m4)dnl builtin(include, build/autoconf/lto.m4)dnl builtin(include, build/autoconf/gcc-pr49911.m4)dnl
--- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -302,16 +302,17 @@ pref("editor.singleLine.pasteNewlines", // threshold where a tap becomes a drag, in 1/240" reference pixels // The names of the preferences are to be in sync with nsEventStateManager.cpp pref("ui.dragThresholdX", 25); pref("ui.dragThresholdY", 25); // Layers Acceleration pref("layers.acceleration.disabled", false); +pref("layers.offmainthreadcomposition.enabled", true); // Web Notifications pref("notification.feature.enabled", true); // IndexedDB pref("indexedDB.feature.enabled", true); pref("dom.indexedDB.warningQuota", 5);
--- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -40,24 +40,23 @@ XPCOMUtils.defineLazyServiceGetter(Servi }); // FIXME Bug 707625 // until we have a proper security model, add some rights to // the pre-installed web applications // XXX never grant 'content-camera' to non-gaia apps function addPermissions(urls) { let permissions = [ - 'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', + 'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'pin-app', 'websettings-read', 'websettings-readwrite', 'content-camera', 'webcontacts-manage', 'wifi-manage', 'desktop-notification', 'geolocation' ]; urls.forEach(function(url) { url = url.trim(); - dump("XxXxX adding permissions for " + url); let uri = Services.io.newURI(url, null, null); let allow = Ci.nsIPermissionManager.ALLOW_ACTION; permissions.forEach(function(permission) { Services.perms.add(uri, permission, allow); }); }); } @@ -89,16 +88,17 @@ var shell = { ['keydown', 'keypress', 'keyup'].forEach((function listenKey(type) { window.addEventListener(type, this, false, true); window.addEventListener(type, this, true, true); }).bind(this)); window.addEventListener('MozApplicationManifest', this); window.addEventListener('mozfullscreenchange', this); + window.addEventListener('sizemodechange', this); this.contentBrowser.addEventListener('load', this, true); // Until the volume can be set from the content side, set it to a // a specific value when the device starts. This way the front-end // can display a notification when the volume change and show a volume // level modified from this point. try { Services.audioManager.masterVolume = 0.5; @@ -126,16 +126,17 @@ var shell = { let browser = this.contentBrowser; browser.homePage = homeURL; browser.goHome(); }, stop: function shell_stop() { window.removeEventListener('MozApplicationManifest', this); window.removeEventListener('mozfullscreenchange', this); + window.removeEventListener('sizemodechange', this); }, toggleDebug: function shell_toggleDebug() { this.isDebug = !this.isDebug; if (this.isDebug) { Services.prefs.setBoolPref("layers.acceleration.draw-fps", true); Services.prefs.setBoolPref("nglayout.debug.paint_flashing", true); @@ -222,16 +223,23 @@ var shell = { case 'mozfullscreenchange': // When the screen goes fullscreen make sure to set the focus to the // main window so noboby can prevent the ESC key to get out fullscreen // mode if (document.mozFullScreen) Services.fm.focusedWindow = window; break; + case 'sizemodechange': + if (window.windowState == window.STATE_MINIMIZED) { + this.contentBrowser.docShell.isActive = false; + } else { + this.contentBrowser.docShell.isActive = true; + } + break; case 'load': this.contentBrowser.removeEventListener('load', this, true); let chromeWindow = window.QueryInterface(Ci.nsIDOMChromeWindow); chromeWindow.browserDOMWindow = new nsBrowserAccess(); this.sendEvent(window, 'ContentStart'); break;
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -607,16 +607,18 @@ pref("plugins.hide_infobar_for_outdated_ #ifdef XP_MACOSX pref("plugins.use_layers", true); pref("plugins.hide_infobar_for_carbon_failure_plugin", false); #endif pref("plugins.update.url", "https://www.mozilla.com/%LOCALE%/plugincheck/"); pref("plugins.update.notifyUser", false); +pref("plugins.click_to_play", false); + #ifdef XP_WIN pref("browser.preferences.instantApply", false); #else pref("browser.preferences.instantApply", true); #endif #ifdef XP_MACOSX pref("browser.preferences.animateFadeIn", true); #else
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -251,16 +251,22 @@ XPCOMUtils.defineLazyGetter(this, "PageM * We can avoid adding multiple load event listeners and save some time by adding * one listener that calls all real handlers. */ function pageShowEventHandlers(event) { // Filter out events that are not about the document load we are interested in if (event.originalTarget == content.document) { charsetLoadListener(event); XULBrowserWindow.asyncUpdateUI(); + + // The PluginClickToPlay events are not fired when navigating using the + // BF cache. |event.persisted| is true when the page is loaded from the + // BF cache, so this code reshows the notification if necessary. + if (event.persisted) + gPluginHandler.reshowClickToPlayNotification(); } } function UpdateBackForwardCommands(aWebNavigation) { var backBroadcaster = document.getElementById("Browser:Back"); var forwardBroadcaster = document.getElementById("Browser:Forward"); // Avoid setting attributes on broadcasters if the value hasn't changed! @@ -1423,16 +1429,17 @@ function HandleAppCommandEvent(evt) { function prepareForStartup() { gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false); gBrowser.addEventListener("PluginNotFound", gPluginHandler, true); gBrowser.addEventListener("PluginCrashed", gPluginHandler, true); gBrowser.addEventListener("PluginBlocklisted", gPluginHandler, true); gBrowser.addEventListener("PluginOutdated", gPluginHandler, true); gBrowser.addEventListener("PluginDisabled", gPluginHandler, true); + gBrowser.addEventListener("PluginClickToPlay", gPluginHandler, true); gBrowser.addEventListener("NewPluginInstalled", gPluginHandler.newPluginInstalled, true); #ifdef XP_MACOSX gBrowser.addEventListener("npapi-carbon-event-model-failure", gPluginHandler, true); #endif Services.obs.addObserver(gPluginHandler.pluginCrashed, "plugin-crashed", false); window.addEventListener("AppCommand", HandleAppCommandEvent, true); @@ -5183,18 +5190,23 @@ var TabsProgressListener = { // We also want to make changes to page UI for unprivileged about pages. BrowserOnAboutPageLoad(aWebProgress.DOMWindow.document); } }, onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI, aFlags) { // Filter out any sub-frame loads - if (aBrowser.contentWindow == aWebProgress.DOMWindow) + if (aBrowser.contentWindow == aWebProgress.DOMWindow) { + // initialize the click-to-play state + aBrowser._clickToPlayDoorhangerShown = false; + aBrowser._clickToPlayPluginsActivated = false; + FullZoom.onLocationChange(aLocationURI, false, aBrowser); + } }, onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) { if (gPrefService.getBoolPref("accessibility.blockautorefresh")) { let brandBundle = document.getElementById("bundle_brand"); let brandShortName = brandBundle.getString("brandShortName"); let refreshButtonText = gNavigatorBundle.getString("refreshBlocked.goButton"); @@ -7138,30 +7150,50 @@ var gPluginHandler = { case "PluginBlocklisted": case "PluginOutdated": #ifdef XP_MACOSX case "npapi-carbon-event-model-failure": #endif self.pluginUnavailable(plugin, event.type); break; + case "PluginClickToPlay": + self._handleClickToPlayEvent(plugin); + break; + case "PluginDisabled": let manageLink = doc.getAnonymousElementByAttribute(plugin, "class", "managePluginsLink"); self.addLinkClickCallback(manageLink, "managePlugins"); break; } // Hide the in-content UI if it's too big. The crashed plugin handler already did this. - if (event.type != "PluginCrashed") { + if (event.type != "PluginCrashed" && event.type != "PluginClickToPlay") { let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox"); if (self.isTooSmall(plugin, overlay)) overlay.style.visibility = "hidden"; } }, + activatePlugins: function PH_activatePlugins(aContentWindow) { + let browser = gBrowser.getBrowserForDocument(aContentWindow.document); + browser._clickToPlayPluginsActivated = true; + let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + let plugins = cwu.plugins; + for (let plugin of plugins) { + let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + if (!objLoadingContent.activated) + objLoadingContent.playPlugin(); + } + let notification = PopupNotifications.getNotification("click-to-play-plugins", browser); + if (notification) + notification.remove(); + }, + newPluginInstalled : function(event) { // browser elements are anonymous so we can't just use target. var browser = event.originalTarget; // clear the plugin list, now that at least one plugin has been installed browser.missingPlugins = null; var notificationBox = gBrowser.getNotificationBox(browser); var notification = notificationBox.getNotificationWithValue("missing-plugins"); @@ -7205,16 +7237,63 @@ var gPluginHandler = { browser.reload(); }, // Callback for user clicking the help icon openHelpPage: function () { openHelpLink("plugin-crashed", false); }, + // Event listener for click-to-play plugins. + _handleClickToPlayEvent: function PH_handleClickToPlayEvent(aPlugin) { + let doc = aPlugin.ownerDocument; + let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document); + if (browser._clickToPlayPluginsActivated) { + let objLoadingContent = aPlugin.QueryInterface(Ci.nsIObjectLoadingContent); + objLoadingContent.playPlugin(); + return; + } + + let overlay = doc.getAnonymousElementByAttribute(aPlugin, "class", "mainBox"); + overlay.addEventListener("click", function(aEvent) { + if (aEvent.button == 0 && aEvent.isTrusted) + gPluginHandler.activatePlugins(aEvent.target.ownerDocument.defaultView.top); + }, true); + + if (!browser._clickToPlayDoorhangerShown) + gPluginHandler._showClickToPlayNotification(browser); + }, + + reshowClickToPlayNotification: function PH_reshowClickToPlayNotification() { + if (!Services.prefs.getBoolPref("plugins.click_to_play")) + return; + + let browser = gBrowser.selectedBrowser; + let contentWindow = browser.contentWindow; + let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + if (cwu.plugins.length) + gPluginHandler._showClickToPlayNotification(browser); + }, + + _showClickToPlayNotification: function PH_showClickToPlayNotification(aBrowser) { + aBrowser._clickToPlayDoorhangerShown = true; + let contentWindow = aBrowser.contentWindow; + let messageString = gNavigatorBundle.getString("activatePluginsMessage.message"); + let action = { + label: gNavigatorBundle.getString("activatePluginsMessage.label"), + accessKey: gNavigatorBundle.getString("activatePluginsMessage.accesskey"), + callback: function() { gPluginHandler.activatePlugins(contentWindow); } + }; + let options = { dismissed: true }; + PopupNotifications.show(aBrowser, "click-to-play-plugins", + messageString, "addons-notification-icon", + action, null, options); + }, + // event listener for missing/blocklisted/outdated/carbonFailure plugins. pluginUnavailable: function (plugin, eventType) { let browser = gBrowser.getBrowserForDocument(plugin.ownerDocument .defaultView.top.document); if (!browser.missingPlugins) browser.missingPlugins = {}; var pluginInfo = getPluginInfo(plugin);
--- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -242,16 +242,18 @@ endif moz.png \ video.ogg \ test_bug435035.html \ test_bug462673.html \ page_style_sample.html \ feed_tab.html \ plugin_unknown.html \ plugin_test.html \ + plugin_test2.html \ + plugin_test3.html \ plugin_both.html \ plugin_both2.html \ alltabslistener.html \ zoom_test.html \ dummy_page.html \ browser_tabMatchesInAwesomebar.js \ file_bug550565_popup.html \ file_bug550565_favicon.ico \
--- a/browser/base/content/test/browser_pluginnotification.js +++ b/browser/base/content/test/browser_pluginnotification.js @@ -1,25 +1,30 @@ var rootDir = getRootDirectory(gTestPath); const gTestRoot = rootDir; var gTestBrowser = null; var gNextTest = null; +var gClickToPlayPluginActualEvents = 0; +var gClickToPlayPluginExpectedEvents = 6; function get_test_plugin() { var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost); var tags = ph.getPluginTags(); // Find the test plugin for (var i = 0; i < tags.length; i++) { if (tags[i].name == "Test Plug-in") return tags[i]; } + ok(false, "Unable to find plugin"); } +Components.utils.import("resource://gre/modules/Services.jsm"); + // This listens for the next opened tab and checks it is of the right url. // opencallback is called when the new tab is fully loaded // closecallback is called when the tab is closed function TabOpenListener(url, opencallback, closecallback) { this.url = url; this.opencallback = opencallback; this.closecallback = closecallback; @@ -58,31 +63,39 @@ TabOpenListener.prototype = { executeSoon(this.closecallback); this.closecallback = null; } } }; function test() { waitForExplicitFinish(); + registerCleanupFunction(function() { Services.prefs.clearUserPref("plugins.click_to_play"); }); + Services.prefs.setBoolPref("plugins.click_to_play", false); var newTab = gBrowser.addTab(); gBrowser.selectedTab = newTab; gTestBrowser = gBrowser.selectedBrowser; gTestBrowser.addEventListener("load", pageLoad, true); + gTestBrowser.addEventListener("PluginClickToPlay", handlePluginClickToPlay, true); prepareTest(test1, gTestRoot + "plugin_unknown.html"); } function finishTest() { gTestBrowser.removeEventListener("load", pageLoad, true); + gTestBrowser.removeEventListener("PluginClickToPlay", handlePluginClickToPlay, true); gBrowser.removeCurrentTab(); window.focus(); finish(); } +function handlePluginClickToPlay() { + gClickToPlayPluginActualEvents++; +} + function pageLoad() { // The plugin events are async dispatched and can come after the load event // This just allows the events to fire before we then go on to test the states executeSoon(gNextTest); } function prepareTest(nextTest, url) { gNextTest = nextTest; @@ -179,10 +192,128 @@ function test7() { ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 7, Should not have displayed the blocked plugin notification"); ok(gTestBrowser.missingPlugins, "Test 7, Should be a missing plugin list"); ok("application/x-unknown" in gTestBrowser.missingPlugins, "Test 7, Should know about application/x-unknown"); ok("application/x-test" in gTestBrowser.missingPlugins, "Test 7, Should know about application/x-test"); var plugin = get_test_plugin(); plugin.disabled = false; plugin.blocklisted = false; - finishTest(); + Services.prefs.setBoolPref("plugins.click_to_play", true); + + prepareTest(test8, gTestRoot + "plugin_test.html"); +} + +// Tests a page with a working plugin that is click-to-play +function test8() { + var notificationBox = gBrowser.getNotificationBox(gTestBrowser); + ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 8, Should not have displayed the missing plugin notification"); + ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 8, Should not have displayed the blocked plugin notification"); + ok(!gTestBrowser.missingPlugins, "Test 8, Should not be a missing plugin list"); + ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 8, Should have a click-to-play notification"); + + prepareTest(test9a, gTestRoot + "plugin_test2.html"); +} + +// Tests that activating one click-to-play plugin will activate the other plugins (part 1/1) +function test9a() { + var notificationBox = gBrowser.getNotificationBox(gTestBrowser); + ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 9a, Should not have displayed the missing plugin notification"); + ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 9a, Should not have displayed the blocked plugin notification"); + ok(!gTestBrowser.missingPlugins, "Test 9a, Should not be a missing plugin list"); + ok(PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 9a, Should have a click-to-play notification"); + var plugin1 = gTestBrowser.contentDocument.getElementById("test"); + var doc = gTestBrowser.contentDocument; + var plugins = []; + plugins.push(doc.getElementById("test")); + plugins.push(doc.getElementById("test1")); + plugins.push(doc.getElementById("test2")); + plugins.forEach(function(plugin) { + var rect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect(); + ok(rect.width == 200, "Test 9a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked"); + ok(rect.height == 200, "Test 9a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked"); + var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(!objLoadingContent.activated, "Test 9a, Plugin with id=" + plugin.id + " should not be activated"); + }); + + EventUtils.synthesizeMouse(plugin1, 100, 100, { }); + setTimeout(test9b, 0); } + +// Tests that activating one click-to-play plugin will activate the other plugins (part 2/2) +function test9b() { + var notificationBox = gBrowser.getNotificationBox(gTestBrowser); + ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 9b, Should not have displayed the missing plugin notification"); + ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 9b, Should not have displayed the blocked plugin notification"); + ok(!gTestBrowser.missingPlugins, "Test 9b, Should not be a missing plugin list"); + ok(!PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser), "Test 9b, Click to play notification should be removed now"); + var doc = gTestBrowser.contentDocument; + var plugins = []; + plugins.push(doc.getElementById("test")); + plugins.push(doc.getElementById("test1")); + plugins.push(doc.getElementById("test2")); + plugins.forEach(function(plugin) { + var pluginRect = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox").getBoundingClientRect(); + ok(pluginRect.width == 0, "Test 9b, Plugin with id=" + plugin.id + " should have click-to-play overlay with zero width"); + ok(pluginRect.height == 0, "Test 9b, Plugin with id=" + plugin.id + " should have click-to-play overlay with zero height"); + var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(objLoadingContent.activated, "Test 9b, Plugin with id=" + plugin.id + " should be activated"); + }); + + prepareTest(test10a, gTestRoot + "plugin_test3.html"); +} + +// Tests that activating a hidden click-to-play plugin through the notification works (part 1/2) +function test10a() { + var notificationBox = gBrowser.getNotificationBox(gTestBrowser); + ok(!notificationBox.getNotificationWithValue("missing-plugins"), "Test 10a, Should not have displayed the missing plugin notification"); + ok(!notificationBox.getNotificationWithValue("blocked-plugins"), "Test 10a, Should not have displayed the blocked plugin notification"); + ok(!gTestBrowser.missingPlugins, "Test 10a, Should not be a missing plugin list"); + var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "Test 10a, Should have a click-to-play notification"); + var plugin = gTestBrowser.contentDocument.getElementById("test"); + var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(!objLoadingContent.activated, "Test 10c, Plugin should not be activated"); + + popupNotification.mainAction.callback(); + setTimeout(test10b, 0); +} + +// Tests that activating a hidden click-to-play plugin through the notification works (part 2/2) +function test10b() { + var plugin = gTestBrowser.contentDocument.getElementById("test"); + var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent); + ok(objLoadingContent.activated, "Test 10c, Plugin should be activated"); + + prepareTest(test11a, gTestRoot + "plugin_test3.html"); +} + +// Tests that the going back will reshow the notification for click-to-play plugins (part 1/3) +function test11a() { + var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(popupNotification, "Test 11a, Should have a click-to-play notification"); + + prepareTest(test11b, "about:blank"); +} + +// Tests that the going back will reshow the notification for click-to-play plugins (part 2/3) +function test11b() { + var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + ok(!popupNotification, "Test 11b, Should not have a click-to-play notification"); + + gTestBrowser.addEventListener("pageshow", test11c, false); + gTestBrowser.contentWindow.history.back(); +} + +// Tests that the going back will reshow the notification for click-to-play plugins (part 3/3) +function test11c() { + gTestBrowser.removeEventListener("pageshow", test11c, false); + // Make sure that the event handlers for pageshow can execute before checking for their effects. + executeSoon(function() { + todo(false, "The following test that checks for the notification fails intermittently, bug 742619."); + //var popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); + //ok(popupNotification, "Test 11c, Should have a click-to-play notification"); + is(gClickToPlayPluginActualEvents, gClickToPlayPluginExpectedEvents, + "There should be a PluginClickToPlay event for each plugin that was " + + "blocked due to the plugins.click_to_play pref"); + finishTest(); + }); +}
--- a/browser/base/content/test/plugin_both.html +++ b/browser/base/content/test/plugin_both.html @@ -1,6 +1,10 @@ +<!DOCTYPE html> <html> +<head> +<meta charset="utf-8"> +</head> <body> <embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown"> <embed id="test" style="width: 100px; height: 100px" type="application/x-test"> </body> </html>
--- a/browser/base/content/test/plugin_both2.html +++ b/browser/base/content/test/plugin_both2.html @@ -1,6 +1,10 @@ +<!DOCTYPE html> <html> +<head> +<meta charset="utf-8"> +</head> <body> <embed id="test" style="width: 100px; height: 100px" type="application/x-test"> <embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown"> </body> </html>
--- a/browser/base/content/test/plugin_test.html +++ b/browser/base/content/test/plugin_test.html @@ -1,5 +1,9 @@ +<!DOCTYPE html> <html> +<head> +<meta charset="utf-8"> +</head> <body> <embed id="test" style="width: 200px; height: 200px" type="application/x-test"> </body> </html>
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/plugin_test2.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="test" style="width: 200px; height: 200px" type="application/x-test"> +<embed id="test1" style="width: 200px; height: 200px" type="application/x-test"> +<embed id="test2" style="width: 200px; height: 200px" type="application/x-test"> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/plugin_test3.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +</head> +<body> +<embed id="test" style="width: 0px; height: 0px" type="application/x-test"> +</body> +</html>
--- a/browser/base/content/test/plugin_unknown.html +++ b/browser/base/content/test/plugin_unknown.html @@ -1,5 +1,9 @@ +<!DOCTYPE html> <html> +<head> +<meta charset="utf-8"> +</head> <body> <embed id="unknown" style="width: 100px; height: 100px" type="application/x-unknown"> </body> </html>
--- a/browser/components/build/nsBrowserCompsCID.h +++ b/browser/components/build/nsBrowserCompsCID.h @@ -36,16 +36,22 @@ ///////////////////////////////////////////////////////////////////////////// #define NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "@mozilla.org/profile/migrator;1?app=browser&type=" #ifdef XP_WIN #define NS_WINIEPROFILEMIGRATOR_CID \ { 0xbc15c73d, 0xc05b, 0x497b, { 0xa3, 0x73, 0x4b, 0xae, 0x6c, 0x17, 0x86, 0x31 } } + +#define NS_WINIEHISTORYENUMERATOR_CID \ +{ 0x93480624, 0x806e, 0x4756, { 0xb7, 0xcb, 0x0f, 0xb7, 0xdd, 0x74, 0x6a, 0x8f } } + +#define NS_IEHISTORYENUMERATOR_CONTRACTID \ + "@mozilla.org/profile/migrator/iehistoryenumerator;1" #endif #ifdef XP_MACOSX #define NS_SAFARIPROFILEMIGRATOR_CID \ { 0x29e3b139, 0xad19, 0x44f3, { 0xb2, 0xc2, 0xe9, 0xf1, 0x3b, 0xa2, 0xbb, 0xc6 } } #endif #define NS_SHELLSERVICE_CID \
--- a/browser/components/build/nsModule.cpp +++ b/browser/components/build/nsModule.cpp @@ -46,16 +46,17 @@ #elif defined(XP_MACOSX) #include "nsMacShellService.h" #elif defined(MOZ_WIDGET_GTK2) #include "nsGNOMEShellService.h" #endif #if defined(XP_WIN) && !defined(__MINGW32__) #include "nsIEProfileMigrator.h" +#include "nsIEHistoryEnumerator.h" #elif defined(XP_MACOSX) #include "nsSafariProfileMigrator.h" #endif #include "rdf.h" #include "nsFeedSniffer.h" #include "AboutRedirector.h" #include "nsIAboutModule.h" @@ -73,16 +74,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindows #elif defined(XP_MACOSX) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService) #elif defined(MOZ_WIDGET_GTK2) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init) #endif #if defined(XP_WIN) && !defined(__MINGW32__) NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEProfileMigrator) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsIEHistoryEnumerator) #elif defined(XP_MACOSX) NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafariProfileMigrator) #endif NS_GENERIC_FACTORY_CONSTRUCTOR(nsFeedSniffer) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrivateBrowsingServiceWrapper, Init) @@ -91,16 +93,17 @@ NS_DEFINE_NAMED_CID(NS_BROWSERDIRECTORYP NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID); #elif defined(MOZ_WIDGET_GTK2) NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID); #endif NS_DEFINE_NAMED_CID(NS_FEEDSNIFFER_CID); NS_DEFINE_NAMED_CID(NS_BROWSER_ABOUT_REDIRECTOR_CID); #if defined(XP_WIN) && !defined(__MINGW32__) NS_DEFINE_NAMED_CID(NS_WINIEPROFILEMIGRATOR_CID); +NS_DEFINE_NAMED_CID(NS_WINIEHISTORYENUMERATOR_CID); #elif defined(XP_MACOSX) NS_DEFINE_NAMED_CID(NS_SHELLSERVICE_CID); NS_DEFINE_NAMED_CID(NS_SAFARIPROFILEMIGRATOR_CID); #endif NS_DEFINE_NAMED_CID(NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID); static const mozilla::Module::CIDEntry kBrowserCIDs[] = { { &kNS_BROWSERDIRECTORYPROVIDER_CID, false, NULL, DirectoryProviderConstructor }, @@ -108,16 +111,17 @@ static const mozilla::Module::CIDEntry k { &kNS_SHELLSERVICE_CID, false, NULL, nsWindowsShellServiceConstructor }, #elif defined(MOZ_WIDGET_GTK2) { &kNS_SHELLSERVICE_CID, false, NULL, nsGNOMEShellServiceConstructor }, #endif { &kNS_FEEDSNIFFER_CID, false, NULL, nsFeedSnifferConstructor }, { &kNS_BROWSER_ABOUT_REDIRECTOR_CID, false, NULL, AboutRedirector::Create }, #if defined(XP_WIN) && !defined(__MINGW32__) { &kNS_WINIEPROFILEMIGRATOR_CID, false, NULL, nsIEProfileMigratorConstructor }, + { &kNS_WINIEHISTORYENUMERATOR_CID, false, NULL, nsIEHistoryEnumeratorConstructor }, #elif defined(XP_MACOSX) { &kNS_SHELLSERVICE_CID, false, NULL, nsMacShellServiceConstructor }, { &kNS_SAFARIPROFILEMIGRATOR_CID, false, NULL, nsSafariProfileMigratorConstructor }, #endif { &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID, false, NULL, nsPrivateBrowsingServiceWrapperConstructor }, { NULL } }; @@ -142,16 +146,17 @@ static const mozilla::Module::ContractID { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-tabs", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "sync-progress", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, #endif { NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "permissions", &kNS_BROWSER_ABOUT_REDIRECTOR_CID }, #if defined(XP_WIN) && !defined(__MINGW32__) { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "ie", &kNS_WINIEPROFILEMIGRATOR_CID }, + { NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID }, #elif defined(XP_MACOSX) { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID }, { NS_BROWSERPROFILEMIGRATOR_CONTRACTID_PREFIX "safari", &kNS_SAFARIPROFILEMIGRATOR_CID }, #endif { NS_PRIVATE_BROWSING_SERVICE_CONTRACTID, &kNS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID }, { NULL } };
--- a/browser/components/migration/src/Makefile.in +++ b/browser/components/migration/src/Makefile.in @@ -43,20 +43,20 @@ include $(DEPTH)/config/autoconf.mk MODULE = migration LIBRARY_NAME = migration_s FORCE_STATIC_LIB = 1 ifndef MOZ_MEMORY USE_STATIC_LIBS = 1 endif - ifeq ($(OS_ARCH)_$(GNU_CXX),WINNT_) CPPSRCS += nsIEProfileMigrator.cpp \ nsBrowserProfileMigratorUtils.cpp \ + nsIEHistoryEnumerator.cpp \ $(NULL) endif ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) CPPSRCS += nsSafariProfileMigrator.cpp \ nsBrowserProfileMigratorUtils.cpp \ $(NULL) endif
--- a/browser/components/migration/src/MigrationUtils.jsm +++ b/browser/components/migration/src/MigrationUtils.jsm @@ -134,19 +134,25 @@ let MigratorPrototype = { /** * DO NOT OVERRIDE - After deCOMing migration, the UI will just call * migrate for each resource. * * @see nsIBrowserProfileMigrator */ migrate: function MP_migrate(aItems, aStartup, aProfile) { // Not using aStartup because it's going away soon. - if (MigrationUtils.isStartupMigration && !this.startupOnlyMigrator) + if (MigrationUtils.isStartupMigration && !this.startupOnlyMigrator) { MigrationUtils.profileStartup.doStartup(); + // Notify glue we are about to do initial migration, otherwise it may try + // to restore default bookmarks overwriting the imported ones. + Cc["@mozilla.org/browser/browserglue;1"].getService(Ci.nsIObserver) + .observe(null, "initial-migration", null); + } + let resources = this._getMaybeCachedResources(aProfile); if (resources.length == 0) throw new Error("migrate called for a non-existent source"); if (aItems != Ci.nsIBrowserProfileMigrator.ALL) resources = [r for each (r in resources) if (aItems & r.type)]; // TODO: use Map (for the items) and Set (for the resources)
new file mode 100644 --- /dev/null +++ b/browser/components/migration/src/nsIEHistoryEnumerator.cpp @@ -0,0 +1,139 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIEHistoryEnumerator.h" + +#include <urlhist.h> +#include <shlguid.h> + +#include "nsStringAPI.h" +#include "nsNetUtil.h" +#include "nsIVariant.h" +#include "nsCOMArray.h" +#include "nsArrayEnumerator.h" + +namespace { + + PRTime FileTimeToPRTime(FILETIME* filetime) + { + SYSTEMTIME st; + ::FileTimeToSystemTime(filetime, &st); + PRExplodedTime prt; + prt.tm_year = st.wYear; + // SYSTEMTIME's day-of-month parameter is 1-based, + // PRExplodedTime's is 0-based. + prt.tm_month = st.wMonth - 1; + prt.tm_mday = st.wDay; + prt.tm_hour = st.wHour; + prt.tm_min = st.wMinute; + prt.tm_sec = st.wSecond; + prt.tm_usec = st.wMilliseconds * 1000; + prt.tm_wday = 0; + prt.tm_yday = 0; + prt.tm_params.tp_gmt_offset = 0; + prt.tm_params.tp_dst_offset = 0; + return PR_ImplodeTime(&prt); + } + +} // Anonymous namespace. + +//////////////////////////////////////////////////////////////////////////////// +//// nsIEHistoryEnumerator + +NS_IMPL_ISUPPORTS1(nsIEHistoryEnumerator, nsISimpleEnumerator) + +nsIEHistoryEnumerator::nsIEHistoryEnumerator() +{ + ::CoInitialize(NULL); +} + +nsIEHistoryEnumerator::~nsIEHistoryEnumerator() +{ + ::CoUninitialize(); +} + +void +nsIEHistoryEnumerator::EnsureInitialized() +{ + if (mURLEnumerator) + return; + + HRESULT hr = ::CoCreateInstance(CLSID_CUrlHistory, + NULL, + CLSCTX_INPROC_SERVER, + IID_IUrlHistoryStg2, + getter_AddRefs(mIEHistory)); + if (FAILED(hr)) + return; + + hr = mIEHistory->EnumUrls(getter_AddRefs(mURLEnumerator)); + if (FAILED(hr)) + return; +} + +NS_IMETHODIMP +nsIEHistoryEnumerator::HasMoreElements(bool* _retval NS_OUTPARAM) +{ + *_retval = false; + + EnsureInitialized(); + MOZ_ASSERT(mURLEnumerator, "Should have instanced an IE History URLEnumerator"); + if (!mURLEnumerator) + return NS_OK; + + STATURL statURL; + ULONG fetched; + + // First argument is not implemented, so doesn't matter what we pass. + HRESULT hr = mURLEnumerator->Next(1, &statURL, &fetched); + if (FAILED(hr) || fetched != 1UL) { + // Reached the last entry. + return NS_OK; + } + + nsCOMPtr<nsIURI> uri; + if (statURL.pwcsUrl) { + nsDependentString url(statURL.pwcsUrl); + nsresult rv = NS_NewURI(getter_AddRefs(uri), url); + ::CoTaskMemFree(statURL.pwcsUrl); + if (NS_FAILED(rv)) { + // Got a corrupt or invalid URI, continue to the next entry. + return HasMoreElements(_retval); + } + } + + nsDependentString title(statURL.pwcsTitle); + + PRTime lastVisited = FileTimeToPRTime(&(statURL.ftLastVisited)); + + mCachedNextEntry = do_CreateInstance("@mozilla.org/hash-property-bag;1"); + MOZ_ASSERT(mCachedNextEntry, "Should have instanced a new property bag"); + if (mCachedNextEntry) { + mCachedNextEntry->SetPropertyAsInterface(NS_LITERAL_STRING("uri"), uri); + mCachedNextEntry->SetPropertyAsAString(NS_LITERAL_STRING("title"), title); + mCachedNextEntry->SetPropertyAsInt64(NS_LITERAL_STRING("time"), lastVisited); + + *_retval = true; + } + + if (statURL.pwcsTitle) + ::CoTaskMemFree(statURL.pwcsTitle); + + return NS_OK; +} + +NS_IMETHODIMP +nsIEHistoryEnumerator::GetNext(nsISupports** _retval NS_OUTPARAM) +{ + *_retval = nsnull; + + if (!mCachedNextEntry) + return NS_ERROR_FAILURE; + + NS_ADDREF(*_retval = mCachedNextEntry); + // Release the cached entry, so it can't be returned twice. + mCachedNextEntry = nsnull; + + return NS_OK; +}
new file mode 100644 --- /dev/null +++ b/browser/components/migration/src/nsIEHistoryEnumerator.h @@ -0,0 +1,36 @@ +/* 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 iehistoryenumerator___h___ +#define iehistoryenumerator___h___ + +#include <urlhist.h> + +#include "nsISimpleEnumerator.h" +#include "nsIWritablePropertyBag2.h" +#include "nsAutoPtr.h" + +class nsIEHistoryEnumerator : public nsISimpleEnumerator +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISIMPLEENUMERATOR + + nsIEHistoryEnumerator(); + +private: + ~nsIEHistoryEnumerator(); + + /** + * Initializes the history reader, if needed. + */ + void EnsureInitialized(); + + nsRefPtr<IUrlHistoryStg2> mIEHistory; + nsRefPtr<IEnumSTATURL> mURLEnumerator; + + nsRefPtr<nsIWritablePropertyBag2> mCachedNextEntry; +}; + +#endif
--- a/browser/components/places/tests/unit/test_browserGlue_prefs.js +++ b/browser/components/places/tests/unit/test_browserGlue_prefs.js @@ -69,29 +69,29 @@ let gTests = [ // Sanity check: we should not have any bookmark on the toolbar. let itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0); do_check_eq(itemId, -1); // Set preferences. Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true); - // Force nsBrowserGlue::_initPlaces(). - print("Simulate Places init"); waitForImportAndSmartBookmarks(function () { // Check bookmarks.html has been imported, and a smart bookmark has been // created. itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, SMART_BOOKMARKS_ON_TOOLBAR); do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "example"); // Check preferences have been reverted. do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML)); run_next_test(); }); + // Force nsBrowserGlue::_initPlaces(). + do_log_info("Simulate Places init"); bg.QueryInterface(Ci.nsIObserver).observe(null, TOPIC_BROWSERGLUE_TEST, TOPICDATA_FORCE_PLACES_INIT); }, function test_import_noSmartBookmarks() { do_log_info("import from bookmarks.html, but don't create smart bookmarks \ @@ -102,29 +102,29 @@ let gTests = [ let itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0); do_check_eq(itemId, -1); // Set preferences. Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, -1); Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true); - // Force nsBrowserGlue::_initPlaces(). - print("Simulate Places init"); waitForImportAndSmartBookmarks(function () { // Check bookmarks.html has been imported, but smart bookmarks have not // been created. itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0); do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "example"); // Check preferences have been reverted. do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML)); run_next_test(); }); + // Force nsBrowserGlue::_initPlaces(). + do_log_info("Simulate Places init"); bg.QueryInterface(Ci.nsIObserver).observe(null, TOPIC_BROWSERGLUE_TEST, TOPICDATA_FORCE_PLACES_INIT); }, function test_import_autoExport_updatedSmartBookmarks() { do_log_info("Import from bookmarks.html, but don't create smart bookmarks \ @@ -136,30 +136,30 @@ let gTests = [ PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0); do_check_eq(itemId, -1); // Set preferences. Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 999); Services.prefs.setBoolPref(PREF_AUTO_EXPORT_HTML, true); Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true); - // Force nsBrowserGlue::_initPlaces() - print("Simulate Places init"); waitForImportAndSmartBookmarks(function () { // Check bookmarks.html has been imported, but smart bookmarks have not // been created. itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0); do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "example"); do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML)); // Check preferences have been reverted. Services.prefs.setBoolPref(PREF_AUTO_EXPORT_HTML, false); run_next_test(); }); + // Force nsBrowserGlue::_initPlaces() + do_log_info("Simulate Places init"); bg.QueryInterface(Ci.nsIObserver).observe(null, TOPIC_BROWSERGLUE_TEST, TOPICDATA_FORCE_PLACES_INIT); }, function test_import_autoExport_oldSmartBookmarks() { do_log_info("Import from bookmarks.html, and create smart bookmarks if \ @@ -171,31 +171,31 @@ let gTests = [ PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0); do_check_eq(itemId, -1); // Set preferences. Services.prefs.setIntPref(PREF_SMART_BOOKMARKS_VERSION, 0); Services.prefs.setBoolPref(PREF_AUTO_EXPORT_HTML, true); Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true); - // Force nsBrowserGlue::_initPlaces() - print("Simulate Places init"); waitForImportAndSmartBookmarks(function () { // Check bookmarks.html has been imported, but smart bookmarks have not // been created. itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, SMART_BOOKMARKS_ON_TOOLBAR); do_check_eq(PlacesUtils.bookmarks.getItemTitle(itemId), "example"); do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML)); // Check preferences have been reverted. Services.prefs.setBoolPref(PREF_AUTO_EXPORT_HTML, false); run_next_test(); }); + // Force nsBrowserGlue::_initPlaces() + do_log_info("Simulate Places init"); bg.QueryInterface(Ci.nsIObserver).observe(null, TOPIC_BROWSERGLUE_TEST, TOPICDATA_FORCE_PLACES_INIT); }, function test_restore() { do_log_info("restore from default bookmarks.html if \ @@ -205,29 +205,29 @@ let gTests = [ // Sanity check: we should not have any bookmark on the toolbar. let itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0); do_check_eq(itemId, -1); // Set preferences. Services.prefs.setBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS, true); - // Force nsBrowserGlue::_initPlaces() - print("Simulate Places init"); waitForImportAndSmartBookmarks(function () { // Check bookmarks.html has been restored. itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, SMART_BOOKMARKS_ON_TOOLBAR); do_check_true(itemId > 0); // Check preferences have been reverted. do_check_false(Services.prefs.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS)); run_next_test(); }); + // Force nsBrowserGlue::_initPlaces() + do_log_info("Simulate Places init"); bg.QueryInterface(Ci.nsIObserver).observe(null, TOPIC_BROWSERGLUE_TEST, TOPICDATA_FORCE_PLACES_INIT); }, function test_restore_import() { @@ -239,30 +239,30 @@ let gTests = [ let itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, 0); do_check_eq(itemId, -1); // Set preferences. Services.prefs.setBoolPref(PREF_IMPORT_BOOKMARKS_HTML, true); Services.prefs.setBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS, true); - // Force nsBrowserGlue::_initPlaces() - print("Simulate Places init"); waitForImportAndSmartBookmarks(function () { // Check bookmarks.html has been restored. itemId = PlacesUtils.bookmarks.getIdForItemAt(PlacesUtils.toolbarFolderId, SMART_BOOKMARKS_ON_TOOLBAR); do_check_true(itemId > 0); // Check preferences have been reverted. do_check_false(Services.prefs.getBoolPref(PREF_RESTORE_DEFAULT_BOOKMARKS)); do_check_false(Services.prefs.getBoolPref(PREF_IMPORT_BOOKMARKS_HTML)); run_next_test(); }); + // Force nsBrowserGlue::_initPlaces() + do_log_info("Simulate Places init"); bg.QueryInterface(Ci.nsIObserver).observe(null, TOPIC_BROWSERGLUE_TEST, TOPICDATA_FORCE_PLACES_INIT); } ]; do_register_cleanup(function () {
--- a/browser/devtools/debugger/DebuggerUI.jsm +++ b/browser/devtools/debugger/DebuggerUI.jsm @@ -487,30 +487,31 @@ DebuggerUI.prototype = { * local file. * XXX: it may be better to use nsITraceableChannel to get to the sources * without relying on caching when we can (not for eval, etc.): * http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/ */ _onLoadSource: function DebuggerUI__onLoadSource(aEvent) { let gBrowser = this.aWindow.gBrowser; - let url = aEvent.detail; + let url = aEvent.detail.url; + let showOptions = aEvent.detail.options; let scheme = Services.io.extractScheme(url); switch (scheme) { case "file": case "chrome": case "resource": try { NetUtil.asyncFetch(url, function onFetch(aStream, aStatus) { if (!Components.isSuccessCode(aStatus)) { return this.logError(url, aStatus); } let source = NetUtil.readInputStreamToString(aStream, aStream.available()); aStream.close(); - this._onSourceLoaded(url, source); + this._onSourceLoaded(url, source, showOptions); }.bind(this)); } catch (ex) { return this.logError(url, ex.name); } break; default: let channel = Services.io.newChannel(url, null, null); @@ -524,17 +525,18 @@ DebuggerUI.prototype = { onDataAvailable: function (aRequest, aContext, aStream, aOffset, aCount) { chunks.push(NetUtil.readInputStreamToString(aStream, aCount)); }, onStopRequest: function (aRequest, aContext, aStatusCode) { if (!Components.isSuccessCode(aStatusCode)) { return this.logError(url, aStatusCode); } - this._onSourceLoaded(url, chunks.join(""), channel.contentType); + this._onSourceLoaded(url, chunks.join(""), channel.contentType, + showOptions); }.bind(this) }; channel.loadFlags = channel.LOAD_FROM_CACHE; channel.asyncOpen(streamListener, null); break; } }, @@ -550,40 +552,43 @@ DebuggerUI.prototype = { logError: function DebuggerUI_logError(aUrl, aStatus) { let view = this.getDebugger(gBrowser.selectedTab).DebuggerView; Components.utils.reportError(view.getFormatStr("loadingError", [ aUrl, aStatus ])); }, /** * Called when source has been loaded. * + * @private * @param string aSourceUrl * The URL of the source script. * @param string aSourceText * The text of the source script. * @param string aContentType * The content type of the source script. + * @param object [aOptions] + * Additional options for showing the script (optional). Supported + * options: + * - targetLine: place the editor at the given line number. */ _onSourceLoaded: function DebuggerUI__onSourceLoaded(aSourceUrl, aSourceText, - aContentType) { + aContentType, + aOptions) { 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); - dbg._updateEditorBreakpoints(); - dbg.debuggerWindow.StackFrames.updateEditor(); + + dbg.debuggerWindow.SourceScripts._onShowScript(script, aOptions); } }; /** * Various debugger UI preferences (currently just the pane height). */ let DebuggerUIPreferences = {
--- a/browser/devtools/debugger/debugger.js +++ b/browser/devtools/debugger/debugger.js @@ -267,23 +267,23 @@ var StackFrames = { if (aDepth !== null) { DebuggerView.Stackframes.highlightFrame(this.selectedFrame, true); } let frame = this.activeThread.cachedFrames[aDepth]; if (!frame) { return; } + // Move the editor's caret to the proper line. if (DebuggerView.Scripts.isSelected(frame.where.url) && frame.where.line) { window.editor.setCaretPosition(frame.where.line - 1); window.editor.setDebugLocation(frame.where.line - 1); } else if (DebuggerView.Scripts.contains(frame.where.url)) { DebuggerView.Scripts.selectScript(frame.where.url); - SourceScripts.onChange({ target: DebuggerView.Scripts._scripts }); window.editor.setCaretPosition(frame.where.line - 1); } else { window.editor.setDebugLocation(-1); } // Display the local variables. let localScope = DebuggerView.Properties.localScope; localScope.empty(); @@ -518,18 +518,17 @@ var SourceScripts = { * Handler for changes on the selected source script. */ onChange: function SS_onChange(aEvent) { let scripts = aEvent.target; if (!scripts.selectedItem) { return; } let script = scripts.selectedItem.getUserData("sourceScript"); - this.setEditorMode(script.url, script.contentType); - this._showScript(script); + this.showScript(script); }, /** * Sets the proper editor mode (JS or HTML) according to the specified * content type, or by determining the type from the URL. * * @param string aUrl * The script URL. @@ -623,38 +622,74 @@ var SourceScripts = { /** * Add the specified script to the list and display it in the editor if the * editor is empty. */ _addScript: function SS_addScript(aScript) { DebuggerView.Scripts.addScript(this._getScriptLabel(aScript.url), aScript); if (window.editor.getCharCount() == 0) { - this._showScript(aScript); + this.showScript(aScript); } }, /** * Load the editor with the script text if available, otherwise fire an event * to load and display the script text. + * + * @param object aScript + * The script object coming from the active thread. + * @param object [aOptions] + * Additional options for showing the script (optional). Supported + * options: + * - targetLine: place the editor at the given line number. */ - _showScript: function SS_showScript(aScript) { + showScript: function SS_showScript(aScript, aOptions) { if (!aScript.loaded) { // Notify the chrome code that we need to load a script file. var evt = document.createEvent("CustomEvent"); - evt.initCustomEvent("Debugger:LoadSource", true, false, aScript.url); + evt.initCustomEvent("Debugger:LoadSource", true, false, + {url: aScript.url, options: aOptions}); document.documentElement.dispatchEvent(evt); + window.editor.setMode(SourceEditor.MODES.TEXT); window.editor.setText(DebuggerView.getStr("loadingText")); + window.editor.resetUndo(); } else { - window.editor.setText(aScript.text); - window.updateEditorBreakpoints(); - StackFrames.updateEditor(); + this._onShowScript(aScript, aOptions); + } + }, + + /** + * Display the script source once it loads. + * + * @private + * @param object aScript + * The script object coming from the active thread. + * @param object [aOptions] + * Additional options for showing the script (optional). Supported + * options: + * - targetLine: place the editor at the given line number. + */ + _onShowScript: function SS__onShowScript(aScript, aOptions) { + aOptions = aOptions || {}; + this.setEditorMode(aScript.url, aScript.contentType); + window.editor.setText(aScript.text); + window.updateEditorBreakpoints(); + StackFrames.updateEditor(); + if (aOptions.targetLine) { + window.editor.setCaretPosition(aOptions.targetLine - 1); } window.editor.resetUndo(); - } + + // Notify the chrome code that we shown script file. + let evt = document.createEvent("CustomEvent"); + evt.initCustomEvent("Debugger:ScriptShown", true, false, + {url: aScript.url}); + document.documentElement.dispatchEvent(evt); + }, }; SourceScripts.onScripts = SourceScripts.onScripts.bind(SourceScripts); SourceScripts.onNewScript = SourceScripts.onNewScript.bind(SourceScripts); SourceScripts.onScriptsCleared = SourceScripts.onScriptsCleared.bind(SourceScripts); SourceScripts.onChange = SourceScripts.onChange.bind(SourceScripts); window.addEventListener("DOMContentLoaded", initDebugger, false);
--- a/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js +++ b/browser/devtools/debugger/test/browser_dbg_bug723069_editor-breakpoints.js @@ -16,53 +16,70 @@ let gScripts = null; let gEditor = null; let gBreakpoints = null; function test() { let tempScope = {}; Cu.import("resource:///modules/source-editor.jsm", tempScope); let SourceEditor = tempScope.SourceEditor; + let scriptShown = false; + let framesAdded = false; debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) { gTab = aTab; gDebuggee = aDebuggee; gPane = aPane; gDebugger = gPane.debuggerWindow; + gPane.activeThread.addOneTimeListener("framesadded", function() { + framesAdded = true; + runTest(); + }); - gPane.activeThread.addOneTimeListener("framesadded", function() { - Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0); - }); gDebuggee.firstCall(); }); - function onScriptsAdded() + window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) { + let url = aEvent.detail.url; + if (url.indexOf("-02.js") != -1) { + scriptShown = true; + window.removeEventListener(aEvent.type, _onEvent); + runTest(); + } + }); + + function runTest() + { + if (scriptShown && framesAdded) { + Services.tm.currentThread.dispatch({ run: onScriptShown }, 0); + } + } + + function onScriptShown() { gScripts = gDebugger.DebuggerView.Scripts; is(gDebugger.StackFrames.activeThread.state, "paused", "Should only be getting stack frames while paused."); is(gScripts._scripts.itemCount, 2, "Found the expected number of scripts."); gEditor = gDebugger.editor; isnot(gEditor.getText().indexOf("debugger"), -1, "The correct script was loaded initially."); isnot(gScripts.selected, gScripts.scriptLocations()[0], - "the correct sccript is selected"); + "the correct script is selected"); gBreakpoints = gPane.breakpoints; is(Object.keys(gBreakpoints), 0, "no breakpoints"); ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey"); is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor"); - - info("add the first breakpoint"); gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddFirst); let location = {url: gScripts.selected, line: 6}; executeSoon(function() { gPane.addBreakpoint(location, onBreakpointAddFirst); }); }
--- a/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js +++ b/browser/devtools/debugger/test/browser_dbg_bug731394_editor-contextmenu.js @@ -14,30 +14,49 @@ let gDebugger = null; function test() { let tempScope = {}; Cu.import("resource:///modules/source-editor.jsm", tempScope); let SourceEditor = tempScope.SourceEditor; let contextMenu = null; + let scriptShown = false; + let framesAdded = false; debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) { gTab = aTab; gDebuggee = aDebuggee; gPane = aPane; gDebugger = gPane.debuggerWindow; gPane.activeThread.addOneTimeListener("framesadded", function() { - Services.tm.currentThread.dispatch({ run: onScriptsAdded }, 0); + framesAdded = true; + runTest(); }); gDebuggee.firstCall(); }); - function onScriptsAdded() + window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) { + let url = aEvent.detail.url; + if (url.indexOf("-02.js") != -1) { + scriptShown = true; + window.removeEventListener(aEvent.type, _onEvent); + runTest(); + } + }); + + function runTest() + { + if (scriptShown && framesAdded) { + Services.tm.currentThread.dispatch({ run: onScriptShown }, 0); + } + } + + function onScriptShown() { 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.");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js @@ -20,25 +20,37 @@ function test() gDebugger = gPane.debuggerWindow; testFrameParameters(); }); } function testFrameParameters() { + dump("Started testFrameParameters!\n"); + gDebugger.addEventListener("Debugger:FetchedParameters", function test() { + dump("Entered Debugger:FetchedParameters!\n"); + gDebugger.removeEventListener("Debugger:FetchedParameters", test, false); Services.tm.currentThread.dispatch({ run: function() { + dump("After currentThread.dispatch!\n"); + var frames = gDebugger.DebuggerView.Stackframes._frames, childNodes = frames.childNodes, localScope = gDebugger.DebuggerView.Properties.localScope, localNodes = localScope.querySelector(".details").childNodes; + dump("Got our variables:\n"); + dump("frames - " + frames.constructor + "\n"); + dump("childNodes - " + childNodes.constructor + "\n"); + dump("localScope - " + localScope.constructor + "\n"); + dump("localNodes - " + localNodes.constructor + "\n"); + is(gDebugger.StackFrames.activeThread.state, "paused", "Should only be getting stack frames while paused."); is(frames.querySelectorAll(".dbg-stackframe").length, 3, "Should have three frames."); is(localNodes.length, 8, "The localScope should contain all the created variable elements.");
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js +++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js @@ -20,24 +20,35 @@ function test() gDebugger = gPane.debuggerWindow; testFrameParameters(); }); } function testFrameParameters() { + dump("Started testFrameParameters!\n"); + gDebugger.addEventListener("Debugger:FetchedParameters", function test() { + dump("Entered Debugger:FetchedParameters!\n"); + gDebugger.removeEventListener("Debugger:FetchedParameters", test, false); Services.tm.currentThread.dispatch({ run: function() { + dump("After currentThread.dispatch!\n"); + var frames = gDebugger.DebuggerView.Stackframes._frames, localScope = gDebugger.DebuggerView.Properties.localScope, localNodes = localScope.querySelector(".details").childNodes; + dump("Got our variables:\n"); + dump("frames - " + frames.constructor + "\n"); + dump("localScope - " + localScope.constructor + "\n"); + dump("localNodes - " + localNodes.constructor + "\n"); + is(gDebugger.StackFrames.activeThread.state, "paused", "Should only be getting stack frames while paused."); is(frames.querySelectorAll(".dbg-stackframe").length, 3, "Should have three frames."); is(localNodes.length, 8, "The localScope should contain all the created variable elements."); @@ -82,19 +93,19 @@ function testFrameParameters() .textContent, 5, "Should have the right argument length."); resumeAndFinish(); }, 100); }}, 0); }, false); - EventUtils.synthesizeMouseAtCenter(content.document.querySelector("button"), - {}, - content.window); + EventUtils.sendMouseEvent({ type: "click" }, + content.document.querySelector("button"), + content.window); } function resumeAndFinish() { gPane.activeThread.addOneTimeListener("framescleared", function() { Services.tm.currentThread.dispatch({ run: function() { var frames = gDebugger.DebuggerView.Stackframes._frames; is(frames.querySelectorAll(".dbg-stackframe").length, 0,
--- a/browser/devtools/debugger/test/browser_dbg_stack-05.js +++ b/browser/devtools/debugger/test/browser_dbg_stack-05.js @@ -10,82 +10,101 @@ const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html"; var gPane = null; var gTab = null; var gDebuggee = null; var gDebugger = null; function test() { + let scriptShown = false; + let framesAdded = false; + debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) { gTab = aTab; gDebuggee = aDebuggee; gPane = aPane; gDebugger = gPane.debuggerWindow; - testRecurse(); + gPane.activeThread.addOneTimeListener("framesadded", function() { + framesAdded = true; + runTest(); + }); + + gDebuggee.firstCall(); }); + + window.addEventListener("Debugger:ScriptShown", function _onEvent(aEvent) { + let url = aEvent.detail.url; + if (url.indexOf("-02.js") != -1) { + scriptShown = true; + window.removeEventListener(aEvent.type, _onEvent); + runTest(); + } + }); + + function runTest() + { + if (scriptShown && framesAdded) { + Services.tm.currentThread.dispatch({ run: testRecurse }, 0); + } + } } -function testRecurse() { - gPane.activeThread.addOneTimeListener("framesadded", function() { - Services.tm.currentThread.dispatch({ run: function() { - let frames = gDebugger.DebuggerView.Stackframes._frames; - let childNodes = frames.childNodes; +function testRecurse() +{ + let frames = gDebugger.DebuggerView.Stackframes._frames; + let childNodes = frames.childNodes; - is(frames.querySelectorAll(".dbg-stackframe").length, 4, - "Correct number of frames."); + is(frames.querySelectorAll(".dbg-stackframe").length, 4, + "Correct number of frames."); - is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length, - "All children should be frames."); + is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length, + "All children should be frames."); - ok(frames.querySelector("#stackframe-0").classList.contains("selected"), - "First frame should be selected by default."); + ok(frames.querySelector("#stackframe-0").classList.contains("selected"), + "First frame should be selected by default."); - ok(!frames.querySelector("#stackframe-2").classList.contains("selected"), - "Third frame should not be selected."); + ok(!frames.querySelector("#stackframe-2").classList.contains("selected"), + "Third frame should not be selected."); - is(gDebugger.editor.getDebugLocation(), 5, - "editor debugger location is correct."); + is(gDebugger.editor.getDebugLocation(), 5, + "editor debugger location is correct."); - EventUtils.sendMouseEvent({ type: "click" }, - frames.querySelector("#stackframe-2"), - gDebugger); - - ok(!frames.querySelector("#stackframe-0").classList.contains("selected"), - "First frame should not be selected after click."); + EventUtils.sendMouseEvent({ type: "click" }, + frames.querySelector("#stackframe-2"), + gDebugger); - ok(frames.querySelector("#stackframe-2").classList.contains("selected"), - "Third frame should be selected after click."); + ok(!frames.querySelector("#stackframe-0").classList.contains("selected"), + "First frame should not be selected after click."); - is(gDebugger.editor.getDebugLocation(), 4, - "editor debugger location is correct after click."); + ok(frames.querySelector("#stackframe-2").classList.contains("selected"), + "Third frame should be selected after click."); - EventUtils.sendMouseEvent({ type: "click" }, - frames.querySelector("#stackframe-0 .dbg-stackframe-name"), - gDebugger); + is(gDebugger.editor.getDebugLocation(), 4, + "editor debugger location is correct after click."); - ok(frames.querySelector("#stackframe-0").classList.contains("selected"), - "First frame should be selected after click inside the first frame."); + EventUtils.sendMouseEvent({ type: "click" }, + frames.querySelector("#stackframe-0 .dbg-stackframe-name"), + gDebugger); - ok(!frames.querySelector("#stackframe-2").classList.contains("selected"), - "Third frame should not be selected after click inside the first frame."); + ok(frames.querySelector("#stackframe-0").classList.contains("selected"), + "First frame should be selected after click inside the first frame."); - is(gDebugger.editor.getDebugLocation(), 5, - "editor debugger location is correct (frame 0 again)."); + ok(!frames.querySelector("#stackframe-2").classList.contains("selected"), + "Third frame should not be selected after click inside the first frame."); - gDebugger.StackFrames.activeThread.resume(function() { - is(gDebugger.editor.getDebugLocation(), -1, - "editor debugger location is correct after resume."); - closeDebuggerAndFinish(gTab); - }); - }}, 0); + is(gDebugger.editor.getDebugLocation(), 5, + "editor debugger location is correct (frame 0 again)."); + + gDebugger.StackFrames.activeThread.resume(function() { + is(gDebugger.editor.getDebugLocation(), -1, + "editor debugger location is correct after resume."); + closeDebuggerAndFinish(gTab); }); - - gDebuggee.firstCall(); } registerCleanupFunction(function() { removeTab(gTab); gPane = null; gTab = null; gDebuggee = null; gDebugger = null;
--- a/browser/devtools/highlighter/inspector.jsm +++ b/browser/devtools/highlighter/inspector.jsm @@ -934,37 +934,16 @@ InspectorUI.prototype = { // Add event handlers bound to this. this.boundRuleViewChanged = this.ruleViewChanged.bind(this); this.ruleView.element.addEventListener("CssRuleViewChanged", this.boundRuleViewChanged); this.cssRuleViewBoundCSSLinkClicked = this.ruleViewCSSLinkClicked.bind(this); this.ruleView.element.addEventListener("CssRuleViewCSSLinkClicked", this.cssRuleViewBoundCSSLinkClicked); - this.cssRuleViewBoundMouseDown = this.ruleViewMouseDown.bind(this); - this.ruleView.element.addEventListener("mousedown", - this.cssRuleViewBoundMouseDown); - this.cssRuleViewBoundMouseUp = this.ruleViewMouseUp.bind(this); - this.ruleView.element.addEventListener("mouseup", - this.cssRuleViewBoundMouseUp); - this.cssRuleViewBoundMouseMove = this.ruleViewMouseMove.bind(this); - this.cssRuleViewBoundMenuUpdate = this.ruleViewMenuUpdate.bind(this); - - this.cssRuleViewBoundCopy = this.ruleViewCopy.bind(this); - iframe.addEventListener("copy", this.cssRuleViewBoundCopy); - - this.cssRuleViewBoundCopyRule = this.ruleViewCopyRule.bind(this); - this.cssRuleViewBoundCopyDeclaration = - this.ruleViewCopyDeclaration.bind(this); - this.cssRuleViewBoundCopyProperty = this.ruleViewCopyProperty.bind(this); - this.cssRuleViewBoundCopyPropertyValue = - this.ruleViewCopyPropertyValue.bind(this); - - // Add the rule view's context menu. - this.ruleViewAddContextMenu(); doc.documentElement.appendChild(this.ruleView.element); this.ruleView.highlight(this.selection); Services.obs.notifyObservers(null, INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, null); }.bind(this); iframe.addEventListener("load", boundLoadListener, true); @@ -1046,373 +1025,33 @@ InspectorUI.prototype = { href = rule.elementStyle.element.ownerDocument.location.href; } let viewSourceUtils = this.chromeWin.gViewSourceUtils; viewSourceUtils.viewSource(href, null, doc, line); } }, /** - * This is the mousedown handler for the rule view. We use it to track whether - * text is currently getting selected. - * . - * @param aEvent The event object - */ - ruleViewMouseDown: function IUI_ruleViewMouseDown(aEvent) - { - this.ruleView.element.addEventListener("mousemove", - this.cssRuleViewBoundMouseMove); - }, - - /** - * This is the mouseup handler for the rule view. We use it to track whether - * text is currently getting selected. - * . - * @param aEvent The event object - */ - ruleViewMouseUp: function IUI_ruleViewMouseUp(aEvent) - { - this.ruleView.element.removeEventListener("mousemove", - this.cssRuleViewBoundMouseMove); - this.ruleView._selectionMode = false; - }, - - /** - * This is the mousemove handler for the rule view. We use it to track whether - * text is currently getting selected. - * . - * @param aEvent The event object - */ - ruleViewMouseMove: function IUI_ruleViewMouseMove(aEvent) - { - this.ruleView._selectionMode = true; - }, - - /** - * Add a context menu to the rule view. - */ - ruleViewAddContextMenu: function IUI_ruleViewAddContextMenu() - { - let iframe = this.getToolIframe(this.ruleViewObject); - let popupSet = this.chromeDoc.getElementById("mainPopupSet"); - let menu = this.chromeDoc.createElement("menupopup"); - menu.addEventListener("popupshowing", this.cssRuleViewBoundMenuUpdate); - menu.id = "rule-view-context-menu"; - - // Copy selection - let label = styleInspectorStrings - .GetStringFromName("rule.contextmenu.copyselection"); - let accessKey = styleInspectorStrings - .GetStringFromName("rule.contextmenu.copyselection.accesskey"); - let item = this.chromeDoc.createElement("menuitem"); - item.id = "rule-view-copy"; - item.setAttribute("label", label); - item.setAttribute("accesskey", accessKey); - item.addEventListener("command", this.cssRuleViewBoundCopy); - menu.appendChild(item); - - // Copy rule - label = styleInspectorStrings. - GetStringFromName("rule.contextmenu.copyrule"); - accessKey = styleInspectorStrings. - GetStringFromName("rule.contextmenu.copyrule.accesskey"); - item = this.chromeDoc.createElement("menuitem"); - item.id = "rule-view-copy-rule"; - item.setAttribute("label", label); - item.setAttribute("accesskey", accessKey); - item.addEventListener("command", this.cssRuleViewBoundCopyRule); - menu.appendChild(item); - - // Copy declaration - label = styleInspectorStrings. - GetStringFromName("rule.contextmenu.copydeclaration"); - accessKey = styleInspectorStrings. - GetStringFromName("rule.contextmenu.copydeclaration.accesskey"); - item = this.chromeDoc.createElement("menuitem"); - item.id = "rule-view-copy-declaration"; - item.setAttribute("label", label); - item.setAttribute("accesskey", accessKey); - item.addEventListener("command", this.cssRuleViewBoundCopyDeclaration); - menu.appendChild(item); - - // Copy property name - label = styleInspectorStrings. - GetStringFromName("rule.contextmenu.copyproperty"); - accessKey = styleInspectorStrings. - GetStringFromName("rule.contextmenu.copyproperty.accesskey"); - item = this.chromeDoc.createElement("menuitem"); - item.id = "rule-view-copy-property"; - item.setAttribute("label", label); - item.setAttribute("accesskey", accessKey); - item.addEventListener("command", this.cssRuleViewBoundCopyProperty); - menu.appendChild(item); - - // Copy property value - label = styleInspectorStrings. - GetStringFromName("rule.contextmenu.copypropertyvalue"); - accessKey = styleInspectorStrings. - GetStringFromName("rule.contextmenu.copypropertyvalue.accesskey"); - item = this.chromeDoc.createElement("menuitem"); - item.id = "rule-view-copy-property-value"; - item.setAttribute("label", label); - item.setAttribute("accesskey", accessKey); - item.addEventListener("command", this.cssRuleViewBoundCopyPropertyValue); - menu.appendChild(item); - - popupSet.appendChild(menu); - - iframe.setAttribute("context", menu.id); - }, - - /** - * Update the rule view's context menu by disabling irrelevant menuitems and - * enabling relevant ones. - * - * @param aEvent The event object - */ - ruleViewMenuUpdate: function IUI_ruleViewMenuUpdate(aEvent) - { - let iframe = this.getToolIframe(this.ruleViewObject); - let win = iframe.contentWindow; - - // Copy selection. - let disable = win.getSelection().isCollapsed; - let menuitem = this.chromeDoc.getElementById("rule-view-copy"); - menuitem.disabled = disable; - - // Copy property, copy property name & copy property value. - let node = this.chromeDoc.popupNode; - if (!node.classList.contains("ruleview-property") && - !node.classList.contains("ruleview-computed")) { - while (node = node.parentElement) { - if (node.classList.contains("ruleview-property") || - node.classList.contains("ruleview-computed")) { - break; - } - } - } - let disablePropertyItems = !node || (node && - !node.classList.contains("ruleview-property") && - !node.classList.contains("ruleview-computed")); - - menuitem = this.chromeDoc.querySelector("#rule-view-copy-declaration"); - menuitem.disabled = disablePropertyItems; - menuitem = this.chromeDoc.querySelector("#rule-view-copy-property"); - menuitem.disabled = disablePropertyItems; - menuitem = this.chromeDoc.querySelector("#rule-view-copy-property-value"); - menuitem.disabled = disablePropertyItems; - }, - - /** - * Copy selected text from the rule view. - * - * @param aEvent The event object - */ - ruleViewCopy: function IUI_ruleViewCopy(aEvent) - { - let iframe = this.getToolIframe(this.ruleViewObject); - let win = iframe.contentWindow; - let text = win.getSelection().toString(); - - // Remove any double newlines. - text = text.replace(/(\r?\n)\r?\n/g, "$1"); - - // Remove "inline" - let inline = styleInspectorStrings.GetStringFromName("rule.sourceInline"); - let rx = new RegExp("^" + inline + "\\r?\\n?", "g"); - text = text.replace(rx, ""); - - // Remove file:line - text = text.replace(/[\w\.]+:\d+(\r?\n)/g, "$1"); - - // Remove inherited from: line - let inheritedFrom = styleInspectorStrings - .GetStringFromName("rule.inheritedSource"); - inheritedFrom = inheritedFrom.replace(/\s%S\s\(%S\)/g, ""); - rx = new RegExp("(\r?\n)" + inheritedFrom + ".*", "g"); - text = text.replace(rx, "$1"); - - clipboardHelper.copyString(text); - - if (aEvent) { - aEvent.preventDefault(); - } - }, - - /** - * Copy a rule from the rule view. - * - * @param aEvent The event object - */ - ruleViewCopyRule: function IUI_ruleViewCopyRule(aEvent) - { - let node = this.chromeDoc.popupNode; - if (node.className != "ruleview-code") { - if (node.className == "ruleview-rule-source") { - node = node.nextElementSibling; - } else { - while (node = node.parentElement) { - if (node.className == "ruleview-code") { - break; - } - } - } - } - - if (node.className == "ruleview-code") { - // We need to strip expanded properties from the node because we use - // node.textContent below, which also gets text from hidden nodes. The - // simplest way to do this is to clone the node and remove them from the - // clone. - node = node.cloneNode(); - let computed = node.querySelector(".ruleview-computedlist"); - if (computed) { - computed.parentNode.removeChild(computed); - } - let autosizer = node.querySelector(".autosizer"); - if (autosizer) { - autosizer.parentNode.removeChild(autosizer); - } - } - - let text = node.textContent; - - // Format the rule - if (osString == "WINNT") { - text = text.replace(/{/g, "{\r\n "); - text = text.replace(/;/g, ";\r\n "); - text = text.replace(/\s*}/g, "\r\n}"); - } else { - text = text.replace(/{/g, "{\n "); - text = text.replace(/;/g, ";\n "); - text = text.replace(/\s*}/g, "\n}"); - } - - clipboardHelper.copyString(text); - }, - - /** - * Copy a declaration from the rule view. - * - * @param aEvent The event object - */ - ruleViewCopyDeclaration: function IUI_ruleViewCopyDeclaration(aEvent) - { - let node = this.chromeDoc.popupNode; - if (!node.classList.contains("ruleview-property") && - !node.classList.contains("ruleview-computed")) { - while (node = node.parentElement) { - if (node.classList.contains("ruleview-property") || - node.classList.contains("ruleview-computed")) { - break; - } - } - } - - // We need to strip expanded properties from the node because we use - // node.textContent below, which also gets text from hidden nodes. The - // simplest way to do this is to clone the node and remove them from the - // clone. - node = node.cloneNode(); - let computed = node.querySelector(".ruleview-computedlist"); - if (computed) { - computed.parentNode.removeChild(computed); - } - clipboardHelper.copyString(node.textContent); - }, - - /** - * Copy a property name from the rule view. - * - * @param aEvent The event object - */ - ruleViewCopyProperty: function IUI_ruleViewCopyProperty(aEvent) - { - let node = this.chromeDoc.popupNode; - - if (!node.classList.contains("ruleview-propertyname")) { - node = node.querySelector(".ruleview-propertyname"); - } - - if (node) { - clipboardHelper.copyString(node.textContent); - } - }, - - /** - * Copy a property value from the rule view. - * - * @param aEvent The event object - */ - ruleViewCopyPropertyValue: function IUI_ruleViewCopyPropertyValue(aEvent) - { - let node = this.chromeDoc.popupNode; - - if (!node.classList.contains("ruleview-propertyvalue")) { - node = node.querySelector(".ruleview-propertyvalue"); - } - - if (node) { - clipboardHelper.copyString(node.textContent); - } - }, - - /** * Destroy the rule view. */ destroyRuleView: function IUI_destroyRuleView() { - let iframe = this.getToolIframe(this.ruleViewObject); - iframe.removeEventListener("copy", this.cssRuleViewBoundCopy); - iframe.parentNode.removeChild(iframe); - if (this.ruleView) { - let menu = this.chromeDoc.querySelector("#rule-view-context-menu"); - if (menu) { - // Copy - let menuitem = this.chromeDoc.querySelector("#rule-view-copy"); - menuitem.removeEventListener("command", this.cssRuleViewBoundCopy); - - // Copy rule - menuitem = this.chromeDoc.querySelector("#rule-view-copy-rule"); - menuitem.removeEventListener("command", this.cssRuleViewBoundCopyRule); - - // Copy property - menuitem = this.chromeDoc.querySelector("#rule-view-copy-declaration"); - menuitem.removeEventListener("command", - this.cssRuleViewBoundCopyDeclaration); - - // Copy property name - menuitem = this.chromeDoc.querySelector("#rule-view-copy-property"); - menuitem.removeEventListener("command", - this.cssRuleViewBoundCopyProperty); - - // Copy property value - menuitem = this.chromeDoc.querySelector("#rule-view-copy-property-value"); - menuitem.removeEventListener("command", - this.cssRuleViewBoundCopyPropertyValue); - - menu.removeEventListener("popupshowing", this.cssRuleViewBoundMenuUpdate); - menu.parentNode.removeChild(menu); - } - this.ruleView.element.removeEventListener("CssRuleViewChanged", this.boundRuleViewChanged); this.ruleView.element.removeEventListener("CssRuleViewCSSLinkClicked", this.cssRuleViewBoundCSSLinkClicked); - this.ruleView.element.removeEventListener("mousedown", - this.cssRuleViewBoundMouseDown); - this.ruleView.element.removeEventListener("mouseup", - this.cssRuleViewBoundMouseUp); - this.ruleView.element.removeEventListener("mousemove", - this.cssRuleViewBoundMouseMove); - delete boundRuleViewChanged; - this.ruleView.clear(); + delete this.boundRuleViewChanged; + delete this.cssRuleViewBoundCSSLinkClicked; + this.ruleView.destroy(); delete this.ruleView; } + + let iframe = this.getToolIframe(this.ruleViewObject); + iframe.parentNode.removeChild(iframe); }, ///////////////////////////////////////////////////////////////////////// //// Utility Methods /** * inspect the given node, highlighting it on the page and selecting the * correct row in the tree panel @@ -2626,17 +2265,8 @@ XPCOMUtils.defineLazyGetter(this, "Style XPCOMUtils.defineLazyGetter(this, "DOMUtils", function () { return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils); }); XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() { return Cc["@mozilla.org/widget/clipboardhelper;1"]. getService(Ci.nsIClipboardHelper); }); - -XPCOMUtils.defineLazyGetter(this, "styleInspectorStrings", function() { - return Services.strings.createBundle( - "chrome://browser/locale/devtools/styleinspector.properties"); -}); - -XPCOMUtils.defineLazyGetter(this, "osString", function() { - return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; -});
--- a/browser/devtools/highlighter/test/browser_inspector_duplicate_ruleview.js +++ b/browser/devtools/highlighter/test/browser_inspector_duplicate_ruleview.js @@ -85,17 +85,19 @@ function inspectorFocusTab1() // Make sure the inspector is open. ok(InspectorUI.inspecting, "Inspector is highlighting"); ok(!InspectorUI.treePanel.isOpen(), "Inspector Tree Panel is not open"); is(InspectorUI.store.length, 1, "Inspector.store.length = 1"); is(InspectorUI.selection, div, "selection matches the div element"); ok(InspectorUI.isSidebarOpen, "sidebar is open"); ok(InspectorUI.isRuleViewOpen(), "rule view is open"); - is(InspectorUI.ruleView.doc.documentElement.children.length, 1, "RuleView elements.length == 1"); + + // The rule view element plus its popupSet + is(InspectorUI.ruleView.doc.documentElement.children.length, 2, "RuleView elements.length == 2"); requestLongerTimeout(4); executeSoon(function() { InspectorUI.closeInspectorUI(); gBrowser.removeCurrentTab(); // tab 1 gBrowser.removeCurrentTab(); // tab 2 finish(); });
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_653427_confirm_close.js +++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_653427_confirm_close.js @@ -35,16 +35,17 @@ function test() confirmEx: function() { return promptButton; } }; testNew(); testSavedFile(); + gBrowser.selectedTab = gBrowser.addTab(); content.location = "data:text/html,<p>test scratchpad save file prompt on closing"; } function testNew() { openScratchpad(function(win) { win.Scratchpad.close(function() { ok(win.closed, "new scratchpad window should close without prompting")
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_669612_unsaved.js +++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_669612_unsaved.js @@ -19,16 +19,17 @@ function test() { waitForExplicitFinish(); testListeners(); testRestoreNotFromFile(); testRestoreFromFileSaved(); testRestoreFromFileUnsaved(); + gBrowser.selectedTab = gBrowser.addTab(); content.location = "data:text/html,<p>test star* UI for unsaved file changes"; } function testListeners() { openScratchpad(function(aWin, aScratchpad) { aScratchpad.setText("new text"); ok(!isStar(aWin), "no star if scratchpad isn't from a file");
--- a/browser/devtools/styleinspector/CssRuleView.jsm +++ b/browser/devtools/styleinspector/CssRuleView.jsm @@ -59,16 +59,17 @@ const FOCUS_BACKWARD = Ci.nsIFocusManage // Used to split on css line separators const CSS_LINE_RE = /(?:[^;\(]*(?:\([^\)]*?\))?[^;\(]*)*;?/g; // Used to parse a single property line. const CSS_PROP_RE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(?:! (important))?;?$/; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource:///modules/devtools/CssLogic.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); var EXPORTED_SYMBOLS = ["CssRuleView", "_ElementStyle", "_editableField", "_getInplaceEditorForSpan"]; /** * Our model looks like this: @@ -694,22 +695,65 @@ TextProperty.prototype = { function CssRuleView(aDoc, aStore) { this.doc = aDoc; this.store = aStore; this.element = this.doc.createElementNS(XUL_NS, "vbox"); this.element.setAttribute("tabindex", "0"); this.element.classList.add("ruleview"); this.element.flex = 1; + this._selectionMode = false; + + this._boundMouseDown = this._onMouseDown.bind(this); + this.element.addEventListener("mousedown", + this._boundMouseDown); + this._boundMouseUp = this._onMouseUp.bind(this); + this.element.addEventListener("mouseup", + this._boundMouseUp); + this._boundMouseMove = this._onMouseMove.bind(this); + + this._boundCopy = this._onCopy.bind(this); + this.element.addEventListener("copy", this._boundCopy); + + this._createContextMenu(); } CssRuleView.prototype = { // The element that we're inspecting. _viewedElement: null, + destroy: function CssRuleView_destroy() + { + this.clear(); + + this.element.removeEventListener("copy", this._boundCopy); + this._copyItem.removeEventListener("command", this._boundCopy); + delete this._boundCopy; + + this._ruleItem.removeEventListener("command", this._boundCopyRule); + delete this._boundCopyRule; + + this._declarationItem.removeEventListener("command", this._boundCopyDeclaration); + delete this._boundCopyDeclaration; + + this._propertyItem.removeEventListener("command", this._boundCopyProperty); + delete this._boundCopyProperty; + + this._propertyValueItem.removeEventListener("command", this._boundCopyPropertyValue); + delete this._boundCopyPropertyValue; + + this._contextMenu.removeEventListener("popupshowing", this._boundMenuUpdate); + delete this._boundMenuUpdate; + delete this._contextMenu; + + if (this.element.parentNode) { + this.element.parentNode.removeChild(this.element); + } + }, + /** * Update the highlighted element. * * @param {nsIDOMElement} aElement * The node whose style rules we'll inspect. */ highlight: function CssRuleView_highlight(aElement) { @@ -757,17 +801,17 @@ CssRuleView.prototype = { /** * Update the rules for the currently highlighted element. */ nodeChanged: function CssRuleView_nodeChanged() { this._clearRules(); this._elementStyle.populate(); this._createEditors(); - }, + }, /** * Clear the rules. */ _clearRules: function CssRuleView_clearRules() { while (this.element.hasChildNodes()) { this.element.removeChild(this.element.lastChild); @@ -808,16 +852,272 @@ CssRuleView.prototype = { { for each (let rule in this._elementStyle.rules) { // Don't hold a reference to this editor beyond the one held // by the node. let editor = new RuleEditor(this, rule); this.element.appendChild(editor.element); } }, + + /** + * Add a context menu to the rule view. + */ + _createContextMenu: function CssRuleView_createContextMenu() + { + let popupSet = this.doc.createElement("popupset"); + this.doc.documentElement.appendChild(popupSet); + + let menu = this.doc.createElement("menupopup"); + menu.id = "rule-view-context-menu"; + + this._boundMenuUpdate = this._onMenuUpdate.bind(this); + menu.addEventListener("popupshowing", this._boundMenuUpdate); + + // Copy selection + this._copyItem = createMenuItem(menu, { + label: "rule.contextmenu.copyselection", + accesskey: "rule.contextmenu.copyselection.accesskey", + command: this._boundCopy + }); + + // Copy rule + this._boundCopyRule = this._onCopyRule.bind(this); + this._ruleItem = createMenuItem(menu, { + label: "rule.contextmenu.copyrule", + accesskey: "rule.contextmenu.copyrule.accesskey", + command: this._boundCopyRule + }); + + // Copy declaration + this._boundCopyDeclaration = this._onCopyDeclaration.bind(this); + this._declarationItem = createMenuItem(menu, { + label: "rule.contextmenu.copydeclaration", + accesskey: "rule.contextmenu.copydeclaration.accesskey", + command: this._boundCopyDeclaration + }); + + this._boundCopyProperty = this._onCopyProperty.bind(this); + this._propertyItem = createMenuItem(menu, { + label: "rule.contextmenu.copyproperty", + accesskey: "rule.contextmenu.copyproperty.accesskey", + command: this._boundCopyProperty + }); + + this._boundCopyPropertyValue = this._onCopyPropertyValue.bind(this); + this._propertyValueItem = createMenuItem(menu,{ + label: "rule.contextmenu.copypropertyvalue", + accesskey: "rule.contextmenu.copypropertyvalue.accesskey", + command: this._boundCopyPropertyValue + }); + + popupSet.appendChild(menu); + this.element.setAttribute("context", menu.id); + + this._contextMenu = menu; + }, + + /** + * Update the rule view's context menu by disabling irrelevant menuitems and + * enabling relevant ones. + * + * @param aEvent The event object + */ + _onMenuUpdate: function CssRuleView_onMenuUpdate(aEvent) + { + // Copy selection. + let disable = this.doc.defaultView.getSelection().isCollapsed; + this._copyItem.disabled = disable; + + // Copy property, copy property name & copy property value. + let node = this.doc.popupNode; + if (!node.classList.contains("ruleview-property") && + !node.classList.contains("ruleview-computed")) { + while (node = node.parentElement) { + if (node.classList.contains("ruleview-property") || + node.classList.contains("ruleview-computed")) { + break; + } + } + } + let disablePropertyItems = !node || (node && + !node.classList.contains("ruleview-property") && + !node.classList.contains("ruleview-computed")); + + this._declarationItem.disabled = disablePropertyItems; + this._propertyItem.disabled = disablePropertyItems; + this._propertyValueItem.disabled = disablePropertyItems; + + dump("Done updating menu!\n"); + }, + + _onMouseDown: function CssRuleView_onMouseDown() + { + this.element.addEventListener("mousemove", this._boundMouseMove); + }, + + _onMouseUp: function CssRuleView_onMouseUp() + { + this.element.removeEventListener("mousemove", this._boundMouseMove); + this._selectionMode = false; + }, + + _onMouseMove: function CssRuleView_onMouseMove() + { + this._selectionMode = true; + }, + + /** + * Copy selected text from the rule view. + * + * @param aEvent The event object + */ + _onCopy: function CssRuleView_onCopy(aEvent) + { + let win = this.doc.defaultView; + let text = win.getSelection().toString(); + + // Remove any double newlines. + text = text.replace(/(\r?\n)\r?\n/g, "$1"); + + // Remove "inline" + let inline = _strings.GetStringFromName("rule.sourceInline"); + let rx = new RegExp("^" + inline + "\\r?\\n?", "g"); + text = text.replace(rx, ""); + + // Remove file:line + text = text.replace(/[\w\.]+:\d+(\r?\n)/g, "$1"); + + // Remove inherited from: line + let inheritedFrom = _strings. + GetStringFromName("rule.inheritedSource"); + inheritedFrom = inheritedFrom.replace(/\s%S\s\(%S\)/g, ""); + rx = new RegExp("(\r?\n)" + inheritedFrom + ".*", "g"); + text = text.replace(rx, "$1"); + + clipboardHelper.copyString(text); + + if (aEvent) { + aEvent.preventDefault(); + } + }, + + /** + * Copy a rule from the rule view. + * + * @param aEvent The event object + */ + _onCopyRule: function CssRuleView_onCopyRule(aEvent) + { + let node = this.doc.popupNode; + if (node.className != "ruleview-code") { + if (node.className == "ruleview-rule-source") { + node = node.nextElementSibling; + } else { + while (node = node.parentElement) { + if (node.className == "ruleview-code") { + break; + } + } + } + } + + if (node.className == "ruleview-code") { + // We need to strip expanded properties from the node because we use + // node.textContent below, which also gets text from hidden nodes. The + // simplest way to do this is to clone the node and remove them from the + // clone. + node = node.cloneNode(); + let computed = node.querySelector(".ruleview-computedlist"); + if (computed) { + computed.parentNode.removeChild(computed); + } + } + + let text = node.textContent; + + // Format the rule + if (osString == "WINNT") { + text = text.replace(/{/g, "{\r\n "); + text = text.replace(/;/g, ";\r\n "); + text = text.replace(/\s*}/g, "\r\n}"); + } else { + text = text.replace(/{/g, "{\n "); + text = text.replace(/;/g, ";\n "); + text = text.replace(/\s*}/g, "\n}"); + } + + clipboardHelper.copyString(text); + }, + + /** + * Copy a declaration from the rule view. + * + * @param aEvent The event object + */ + _onCopyDeclaration: function CssRuleView_onCopyDeclaration(aEvent) + { + let node = this.doc.popupNode; + if (!node.classList.contains("ruleview-property") && + !node.classList.contains("ruleview-computed")) { + while (node = node.parentElement) { + if (node.classList.contains("ruleview-property") || + node.classList.contains("ruleview-computed")) { + break; + } + } + } + + // We need to strip expanded properties from the node because we use + // node.textContent below, which also gets text from hidden nodes. The + // simplest way to do this is to clone the node and remove them from the + // clone. + node = node.cloneNode(); + let computed = node.querySelector(".ruleview-computedlist"); + if (computed) { + computed.parentNode.removeChild(computed); + } + clipboardHelper.copyString(node.textContent); + }, + + /** + * Copy a property name from the rule view. + * + * @param aEvent The event object + */ + _onCopyProperty: function CssRuleView_onCopyProperty(aEvent) + { + let node = this.doc.popupNode; + + if (!node.classList.contains("ruleview-propertyname")) { + node = node.querySelector(".ruleview-propertyname"); + } + + if (node) { + clipboardHelper.copyString(node.textContent); + } + }, + + /** + * Copy a property value from the rule view. + * + * @param aEvent The event object + */ + _onCopyPropertyValue: function CssRuleView_onCopyPropertyValue(aEvent) + { + let node = this.doc.popupNode; + + if (!node.classList.contains("ruleview-propertyvalue")) { + node = node.querySelector(".ruleview-propertyvalue"); + } + + if (node) { + clipboardHelper.copyString(node.textContent); + } + } }; /** * Create a RuleEditor. * * @param CssRuleView aRuleView * The CssRuleView containg the document holding this rule editor and the * _selectionMode flag. @@ -1564,16 +1864,28 @@ function createChild(aParent, aTag, aAtt elt.setAttribute(attr, aAttributes[attr]); } } } aParent.appendChild(elt); return elt; } +function createMenuItem(aMenu, aAttributes) +{ + let item = aMenu.ownerDocument.createElementNS(XUL_NS, "menuitem"); + item.setAttribute("label", _strings.GetStringFromName(aAttributes.label)); + item.setAttribute("accesskey", _strings.GetStringFromName(aAttributes.accesskey)); + item.addEventListener("command", aAttributes.command); + + aMenu.appendChild(item); + + return item; +} + /** * Append a text node to an element. */ function appendText(aParent, aText) { aParent.appendChild(aParent.ownerDocument.createTextNode(aText)); } @@ -1593,8 +1905,23 @@ function copyTextStyles(aFrom, aTo) /** * Trigger a focus change similar to pressing tab/shift-tab. */ function moveFocus(aWin, aDirection) { let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager); fm.moveFocus(aWin, null, aDirection, 0); } + +XPCOMUtils.defineLazyGetter(this, "clipboardHelper", function() { + return Cc["@mozilla.org/widget/clipboardhelper;1"]. + getService(Ci.nsIClipboardHelper); +}); + +XPCOMUtils.defineLazyGetter(this, "_strings", function() { + return Services.strings.createBundle( + "chrome://browser/locale/devtools/styleinspector.properties"); +}); + +XPCOMUtils.defineLazyGetter(this, "osString", function() { + return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; +}); +
--- a/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_bug_703643_context_menu_copy.js @@ -65,17 +65,17 @@ function inspectorUIOpen() } function testClip() { Services.obs.removeObserver(testClip, InspectorUI.INSPECTOR_NOTIFICATIONS.RULEVIEWREADY, false); executeSoon(function() { - info("Checking that InspectorUI.ruleViewCopyRule() returns " + + info("Checking that _onCopyRule() returns " + "the correct clipboard value"); let expectedPattern = "element {[\\r\\n]+" + " margin: 10em;[\\r\\n]+" + " font-size: 14pt;[\\r\\n]+" + " font-family: helvetica,sans-serif;[\\r\\n]+" + " color: rgb\\(170, 170, 170\\);[\\r\\n]+" + "}[\\r\\n]*"; info("Expected pattern: " + expectedPattern); @@ -101,86 +101,86 @@ function checkCopyRule() { is(propName, "font-family", "checking property name"); is(propValue, "helvetica,sans-serif", "checking property value"); // We need the context menu to open in the correct place in order for // popupNode to be propertly set. EventUtils.synthesizeMouse(prop, 1, 1, { type: "contextmenu", button: 2 }, ruleView.contentWindow); - InspectorUI.ruleViewCopyRule(); + InspectorUI.ruleView._boundCopyRule(); } function checkCopyProperty() { - info("Checking that InspectorUI.cssRuleViewBoundCopyDeclaration() returns " + + info("Checking that _onCopyDeclaration() returns " + "the correct clipboard value"); let expectedPattern = "font-family: helvetica,sans-serif;"; info("Expected pattern: " + expectedPattern); SimpleTest.waitForClipboard(function IUI_boundCopyPropCheck() { return checkClipboardData(expectedPattern); }, - InspectorUI.cssRuleViewBoundCopyDeclaration, + InspectorUI.ruleView._boundCopyDeclaration, checkCopyPropertyName, checkCopyPropertyName); } function checkCopyPropertyName() { - info("Checking that InspectorUI.cssRuleViewBoundCopyProperty() returns " + + info("Checking that _onCopyProperty() returns " + "the correct clipboard value"); let expectedPattern = "font-family"; info("Expected pattern: " + expectedPattern); SimpleTest.waitForClipboard(function IUI_boundCopyPropNameCheck() { return checkClipboardData(expectedPattern); }, - InspectorUI.cssRuleViewBoundCopyProperty, + InspectorUI.ruleView._boundCopyProperty, checkCopyPropertyValue, checkCopyPropertyValue); } function checkCopyPropertyValue() { - info("Checking that InspectorUI.cssRuleViewBoundCopyPropertyValue() " + + info("Checking that _onCopyPropertyValue() " + " returns the correct clipboard value"); let expectedPattern = "helvetica,sans-serif"; info("Expected pattern: " + expectedPattern); SimpleTest.waitForClipboard(function IUI_boundCopyPropValueCheck() { return checkClipboardData(expectedPattern); }, - InspectorUI.cssRuleViewBoundCopyPropertyValue, + InspectorUI.ruleView._boundCopyPropertyValue, checkCopySelection, checkCopySelection); } function checkCopySelection() { let ruleView = document.querySelector("#devtools-sidebar-iframe-ruleview"); let contentDoc = ruleView.contentDocument; let props = contentDoc.querySelectorAll(".ruleview-property"); let range = document.createRange(); range.setStart(props[0], 0); range.setEnd(props[4], 8); ruleView.contentWindow.getSelection().addRange(range); - info("Checking that InspectorUI.cssRuleViewBoundCopy() returns the correct" + + info("Checking that _onCopy() returns the correct" + "clipboard value"); let expectedPattern = " margin: 10em;[\\r\\n]+" + " font-size: 14pt;[\\r\\n]+" + " font-family: helvetica,sans-serif;[\\r\\n]+" + " color: rgb\\(170, 170, 170\\);[\\r\\n]+" + "}[\\r\\n]+" + "html {[\\r\\n]+" + " color: rgb\\(0, 0, 0\\);[\\r\\n]*"; info("Expected pattern: " + expectedPattern); SimpleTest.waitForClipboard(function IUI_boundCopyCheck() { return checkClipboardData(expectedPattern); - },InspectorUI.cssRuleViewBoundCopy, finishup, finishup); + },InspectorUI.ruleView._boundCopy, finishup, finishup); } function checkClipboardData(aExpectedPattern) { let actual = SpecialPowers.getClipboardData("text/unicode"); let expectedRegExp = new RegExp(aExpectedPattern, "g"); return expectedRegExp.test(actual); }
--- a/browser/locales/en-US/chrome/browser/browser.properties +++ b/browser/locales/en-US/chrome/browser/browser.properties @@ -110,16 +110,19 @@ crashedpluginsMessage.title=The %S plugi crashedpluginsMessage.reloadButton.label=Reload page crashedpluginsMessage.reloadButton.accesskey=R crashedpluginsMessage.submitButton.label=Submit a crash report crashedpluginsMessage.submitButton.accesskey=S crashedpluginsMessage.learnMore=Learn More… carbonFailurePluginsMessage.message=This page asks to use a plugin that can only run in 32-bit mode carbonFailurePluginsMessage.restartButton.label=Restart in 32-bit mode carbonFailurePluginsMessage.restartButton.accesskey=R +activatePluginsMessage.message=Would you like to activate the plugins on this page? +activatePluginsMessage.label=Activate plugins +activatePluginsMessage.accesskey=A # Sanitize # LOCALIZATION NOTE (sanitizeDialog2.everything.title): When "Time range to # clear" is set to "Everything", the Clear Recent History dialog's title is # changed to this. See UI mockup and comment 11 at bug 480169 --> sanitizeDialog2.everything.title=Clear All History sanitizeButtonOK=Clear Now # LOCALIZATION NOTE (sanitizeEverythingWarning2): Warning that appears when
--- a/browser/themes/gnomestripe/browser.css +++ b/browser/themes/gnomestripe/browser.css @@ -1186,17 +1186,18 @@ toolbar[iconsize="small"] #feed-button { list-style-image: url(chrome://browser/skin/Geolocation-64.png); } .popup-notification-icon[popupid="xpinstall-disabled"], .popup-notification-icon[popupid="addon-progress"], .popup-notification-icon[popupid="addon-install-cancelled"], .popup-notification-icon[popupid="addon-install-blocked"], .popup-notification-icon[popupid="addon-install-failed"], -.popup-notification-icon[popupid="addon-install-complete"] { +.popup-notification-icon[popupid="addon-install-complete"], +.popup-notification-icon[popupid="click-to-play-plugins"] { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png); width: 32px; height: 32px; } .addon-progress-description { width: 350px; max-width: 350px;
--- a/browser/themes/pinstripe/browser.css +++ b/browser/themes/pinstripe/browser.css @@ -2373,17 +2373,18 @@ toolbarbutton.chevron > .toolbarbutton-m list-style-image: url(chrome://browser/skin/Geolocation-64.png); } .popup-notification-icon[popupid="xpinstall-disabled"], .popup-notification-icon[popupid="addon-progress"], .popup-notification-icon[popupid="addon-install-cancelled"], .popup-notification-icon[popupid="addon-install-blocked"], .popup-notification-icon[popupid="addon-install-failed"], -.popup-notification-icon[popupid="addon-install-complete"] { +.popup-notification-icon[popupid="addon-install-complete"], +.popup-notification-icon[popupid="click-to-play-plugins"] { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png); width: 32px; height: 32px; } .addon-progress-description { width: 350px; max-width: 350px;
--- a/browser/themes/winstripe/browser.css +++ b/browser/themes/winstripe/browser.css @@ -2244,17 +2244,18 @@ toolbarbutton.bookmark-item[dragover="tr list-style-image: url(chrome://browser/skin/Geolocation-64.png); } .popup-notification-icon[popupid="xpinstall-disabled"], .popup-notification-icon[popupid="addon-progress"], .popup-notification-icon[popupid="addon-install-cancelled"], .popup-notification-icon[popupid="addon-install-blocked"], .popup-notification-icon[popupid="addon-install-failed"], -.popup-notification-icon[popupid="addon-install-complete"] { +.popup-notification-icon[popupid="addon-install-complete"], +.popup-notification-icon[popupid="click-to-play-plugins"] { list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png); width: 32px; height: 32px; } .addon-progress-description { width: 350px; max-width: 350px;
deleted file mode 100644 --- a/build/autoconf/freetype2.m4 +++ /dev/null @@ -1,137 +0,0 @@ -# Configure paths for FreeType2 -# Marcelo Magallon 2001-10-26, based on gtk.m4 by Owen Taylor - -dnl AM_CHECK_FT2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) -dnl Test for FreeType2, and define FT2_CFLAGS and FT2_LIBS -dnl -AC_DEFUN([AC_CHECK_FT2], -[dnl -dnl Get the cflags and libraries from the freetype-config script -dnl -AC_ARG_WITH(freetype-prefix, -[ --with-ft-prefix=PFX Prefix where FreeType is installed (optional)], - ft_config_prefix="$withval", ft_config_prefix="") -AC_ARG_WITH(freetype-exec-prefix, -[ --with-ft-exec-prefix=PFX - Exec prefix where FreeType is installed (optional)], - ft_config_exec_prefix="$withval", ft_config_exec_prefix="") -AC_ARG_ENABLE(freetypetest, -[ --disable-freetypetest - Do not try to compile and run a test FreeType program], - [], enable_fttest=yes) - -if test x$ft_config_exec_prefix != x ; then - ft_config_args="$ft_config_args --exec-prefix=$ft_config_exec_prefix" - if test x${FT2_CONFIG+set} != xset ; then - FT2_CONFIG=$ft_config_exec_prefix/bin/freetype-config - fi -fi -if test x$ft_config_prefix != x ; then - ft_config_args="$ft_config_args --prefix=$ft_config_prefix" - if test x${FT2_CONFIG+set} != xset ; then - FT2_CONFIG=$ft_config_prefix/bin/freetype-config - fi -fi -AC_PATH_PROG(FT2_CONFIG, freetype-config, no) - -min_ft_version=ifelse([$1], ,6.1.0,$1) -AC_MSG_CHECKING(for FreeType - version >= $min_ft_version) -no_ft="" -if test "$FT2_CONFIG" = "no" ; then - no_ft=yes -else - FT2_CFLAGS=`$FT2_CONFIG $ft_config_args --cflags` - FT2_LIBS=`$FT2_CONFIG $ft_config_args --libs` - ft_config_major_version=`$FT2_CONFIG $ft_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - ft_config_minor_version=`$FT2_CONFIG $ft_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - ft_config_micro_version=`$FT2_CONFIG $ft_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - ft_min_major_version=`echo $min_ft_version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - ft_min_minor_version=`echo $min_ft_version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - ft_min_micro_version=`echo $min_ft_version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_fttest" = "xyes" ; then - ft_config_is_lt=no - if test $ft_config_major_version -lt $ft_min_major_version ; then - ft_config_is_lt=yes - else - if test $ft_config_major_version -eq $ft_min_major_version ; then - if test $ft_config_minor_version -lt $ft_min_minor_version ; then - ft_config_is_lt=yes - else - if test $ft_config_minor_version -eq $ft_min_minor_version ; then - if test $ft_config_micro_version -lt $ft_min_micro_version ; then - ft_config_is_lt=yes - fi - fi - fi - fi - fi - if test "x$ft_config_is_lt" = "xyes" ; then - ifelse([$3], , :, [$3]) - AC_MSG_RESULT(no) - else - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $FT2_CFLAGS" - LIBS="$FT2_LIBS $LIBS" -dnl -dnl Sanity checks for the results of freetype-config to some extent -dnl - AC_TRY_RUN([ -#include <ft2build.h> -#include FT_FREETYPE_H -#include <stdio.h> -#include <stdlib.h> - -int -main() -{ - FT_Library library; - FT_Error error; - - error = FT_Init_FreeType(&library); - - if (error) - return 1; - else - { - FT_Done_FreeType(library); - return 0; - } -} -],, no_ft=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi # test $ft_config_version -lt $ft_min_version - fi # test "x$enable_fttest" = "xyes" -fi # test "$FT2_CONFIG" = "no" -if test "x$ft_config_is_lt" != "xyes" ; then - if test "x$no_ft" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$FT2_CONFIG" = "no" ; then - echo "*** The freetype-config script installed by FreeType 2 could not be found." - echo "*** If FreeType 2 was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the FT2_CONFIG environment variable to the" - echo "*** full path to freetype-config." - else - echo "*** The FreeType test program failed to run. If your system uses" - echo "*** shared libraries and they are installed outside the normal" - echo "*** system library path, make sure the variable LD_LIBRARY_PATH" - echo "*** (or whatever is appropiate for your system) is correctly set." - fi - FT2_CFLAGS="" - FT2_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(FT2_CFLAGS) - AC_SUBST(FT2_LIBS) -fi -])
--- a/build/macosx/universal/flight.mk +++ b/build/macosx/universal/flight.mk @@ -62,17 +62,16 @@ INSTALLER_DIR = camino/installer MOZ_PKG_APPNAME = camino APPNAME = Camino.app BUILDCONFIG_BASE = Contents/MacOS/chrome else # } { MOZ_PKG_APPNAME = $(MOZ_APP_NAME) APPNAME = $(MOZ_MACBUNDLE_NAME) INSTALLER_DIR = $(MOZ_BUILD_APP)/installer ifeq ($(MOZ_BUILD_APP),xulrunner) # { -INSTALLER_DIR = xulrunner/installer/mac APPNAME = XUL.framework APP_CONTENTS = Versions/Current endif # } xulrunner BUILDCONFIG_BASE = $(APP_CONTENTS)/chrome endif # } !camino ifeq ($(MOZ_CHROME_FILE_FORMAT),jar) BUILDCONFIG = $(BUILDCONFIG_BASE)/toolkit.jar
--- a/build/mobile/devicemanagerADB.py +++ b/build/mobile/devicemanagerADB.py @@ -2,36 +2,44 @@ import subprocess from devicemanager import DeviceManager, DMError, _pop_last_line import re import os import sys import tempfile class DeviceManagerADB(DeviceManager): - def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = None): + def __init__(self, host=None, port=20701, retrylimit=5, packageName='fennec', + adbPath='adb', deviceSerial=None): self.host = host self.port = port self.retrylimit = retrylimit self.retries = 0 self._sock = None self.useRunAs = False self.haveRoot = False self.useDDCopy = False self.useZip = False self.packageName = None self.tempDir = None - if packageName: - self.packageName = packageName - else: + # the path to adb, or 'adb' to assume that it's on the PATH + self.adbPath = adbPath + + # The serial number of the device to use with adb, used in cases + # where multiple devices are being managed by the same adb instance. + self.deviceSerial = deviceSerial + + if packageName == 'fennec': if os.getenv('USER'): self.packageName = 'org.mozilla.fennec_' + os.getenv('USER') else: self.packageName = 'org.mozilla.fennec_' + elif packageName: + self.packageName = packageName # verify that we can run the adb command. can't continue otherwise self.verifyADB() # try to connect to the device over tcp/ip if we have a hostname if self.host: self.connectRemoteADB() @@ -91,17 +99,21 @@ class DeviceManagerADB(DeviceManager): # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout - proc = subprocess.Popen(["adb", "shell", cmdline], + args=[self.adbPath] + if self.deviceSerial: + args.extend(['-s', self.deviceSerial]) + args.extend(["shell", cmdline]) + proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: @@ -144,17 +156,19 @@ class DeviceManagerADB(DeviceManager): return False # external function # returns: # success: directory name # failure: None def mkDir(self, name): try: - self.checkCmdAs(["shell", "mkdir", name]) + result = self.runCmdAs(["shell", "mkdir", name]).stdout.read() + if 'read-only file system' in result.lower(): + return None self.chmodDir(name) return name except: return None # make directory structure on the device # external function # returns: @@ -518,20 +532,24 @@ class DeviceManagerADB(DeviceManager): # success: path for device root # failure: None def getDeviceRoot(self): # /mnt/sdcard/tests is preferred to /data/local/tests, but this can be # over-ridden by creating /data/local/tests testRoot = "/data/local/tests" if (self.dirExists(testRoot)): return testRoot + root = "/mnt/sdcard" - if (not self.dirExists(root)): - root = "/data/local" - testRoot = root + "/tests" + if self.dirExists(root): + testRoot = root + "/tests" + if self.mkDir(testRoot): + return testRoot + + testRoot = "/data/local/tests" if (not self.dirExists(testRoot)): self.mkDir(testRoot) return testRoot # Gets the temporary directory we are using on this device # base on our device root, ensuring also that it exists. # # internal function @@ -666,36 +684,42 @@ class DeviceManagerADB(DeviceManager): if (directive == "systime" or directive == "all"): ret["systime"] = self.runCmd(["shell", "date"]).stdout.read() print ret return ret def runCmd(self, args): # If we are not root but have run-as, and we're trying to execute # a shell command then using run-as is the best we can do + finalArgs = [self.adbPath] + if self.deviceSerial: + finalArgs.extend(['-s', self.deviceSerial]) if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"): args.insert(1, "run-as") args.insert(2, self.packageName) - args.insert(0, "adb") - return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + finalArgs.extend(args) + return subprocess.Popen(finalArgs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def runCmdAs(self, args): if self.useRunAs: args.insert(1, "run-as") args.insert(2, self.packageName) return self.runCmd(args) def checkCmd(self, args): # If we are not root but have run-as, and we're trying to execute # a shell command then using run-as is the best we can do + finalArgs = [self.adbPath] + if self.deviceSerial: + finalArgs.extend(['-s', self.deviceSerial]) if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"): args.insert(1, "run-as") args.insert(2, self.packageName) - args.insert(0, "adb") - return subprocess.check_call(args) + finalArgs.extend(args) + return subprocess.check_call(finalArgs) def checkCmdAs(self, args): if (self.useRunAs): args.insert(1, "run-as") args.insert(2, self.packageName) return self.checkCmd(args) def chmodDir(self, remoteDir): @@ -710,24 +734,45 @@ class DeviceManagerADB(DeviceManager): self.checkCmdAs(["shell", "chmod", "777", remoteDir]) print "chmod " + remoteDir else: self.checkCmdAs(["shell", "chmod", "777", remoteDir.strip()]) print "chmod " + remoteDir.strip() def verifyADB(self): # Check to see if adb itself can be executed. + if self.adbPath != 'adb': + if not os.access(self.adbPath, os.X_OK): + raise DMError("invalid adb path, or adb not executable: %s", self.adbPath) + try: self.checkCmd(["version"]) except os.error, err: raise DMError("unable to execute ADB (%s): ensure Android SDK is installed and adb is in your $PATH" % err) except subprocess.CalledProcessError: raise DMError("unable to execute ADB: ensure Android SDK is installed and adb is in your $PATH") def verifyDevice(self): + # If there is a device serial number, see if adb is connected to it + if self.deviceSerial: + deviceStatus = None + proc = subprocess.Popen([self.adbPath, "devices"], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + for line in proc.stdout: + m = re.match('(.+)?\s+(.+)$', line) + if m: + if self.deviceSerial == m.group(1): + deviceStatus = m.group(2) + if deviceStatus == None: + raise DMError("device not found: %s" % self.deviceSerial) + elif deviceStatus != "device": + raise DMError("bad status for device %s: %s" % (self.deviceSerial, + deviceStatus)) + # Check to see if we can connect to device and run a simple command try: self.checkCmd(["shell", "echo"]) except subprocess.CalledProcessError: raise DMError("unable to connect to device: is it plugged in?") def verifyRoot(self): # a test to see if we have root privs
--- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -193,16 +193,54 @@ GetPrincipalDomainOrigin(nsIPrincipal* a } static nsIScriptContext * GetScriptContext(JSContext *cx) { return GetScriptContextFromJSContext(cx); } +// Callbacks for the JS engine to use to push/pop context principals. +static JSBool +PushPrincipalCallback(JSContext *cx, JSPrincipals *principals) +{ + // We should already be in the compartment of the given principal. + MOZ_ASSERT(principals == + JS_GetCompartmentPrincipals((js::GetContextCompartment(cx)))); + + // Get the security manager. + nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager(); + if (!ssm) { + return true; + } + + // Push the principal. + JSStackFrame *fp = NULL; + nsresult rv = ssm->PushContextPrincipal(cx, JS_FrameIterator(cx, &fp), + nsJSPrincipals::get(principals)); + if (NS_FAILED(rv)) { + JS_ReportOutOfMemory(cx); + return false; + } + + return true; +} + +static JSBool +PopPrincipalCallback(JSContext *cx) +{ + nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager(); + if (ssm) { + ssm->PopContextPrincipal(cx); + } + + return true; +} + + inline void SetPendingException(JSContext *cx, const char *aMsg) { JSAutoRequest ar(cx); JS_ReportError(cx, "%s", aMsg); } inline void SetPendingException(JSContext *cx, const PRUnichar *aMsg) { @@ -3386,17 +3424,19 @@ nsresult nsScriptSecurityManager::Init() rv = runtimeService->GetRuntime(&sRuntime); NS_ENSURE_SUCCESS(rv, rv); static const JSSecurityCallbacks securityCallbacks = { CheckObjectAccess, nsJSPrincipals::Subsume, ObjectPrincipalFinder, - ContentSecurityPolicyPermitsJSAction + ContentSecurityPolicyPermitsJSAction, + PushPrincipalCallback, + PopPrincipalCallback }; MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime)); JS_SetSecurityCallbacks(sRuntime, &securityCallbacks); JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy); JS_SetTrustedPrincipals(sRuntime, system);
--- a/client.mk +++ b/client.mk @@ -363,18 +363,17 @@ ifdef MOZ_PREFLIGHT for mkfile in $(MOZ_PREFLIGHT); do \ $(MAKE) -f $(TOPSRCDIR)/$$mkfile preflight TOPSRCDIR=$(TOPSRCDIR) OBJDIR=$(OBJDIR) MOZ_OBJDIR=$(MOZ_OBJDIR); \ done endif #################################### # Build it -realbuild:: $(OBJDIR)/Makefile $(OBJDIR)/config.status - @$(PYTHON) $(TOPSRCDIR)/js/src/config/check-sync-dirs.py $(TOPSRCDIR)/js/src/config $(TOPSRCDIR)/config +realbuild:: $(OBJDIR)/Makefile $(OBJDIR)/config.status check-sync-dirs-config $(MOZ_MAKE) #################################### # Other targets # Pass these target onto the real build system $(OBJDIR_TARGETS):: $(OBJDIR)/Makefile $(OBJDIR)/config.status $(MOZ_MAKE) $@ @@ -422,16 +421,22 @@ cleansrcdir: else \ echo "Removing object files from srcdir..."; \ rm -fr `find . -type d \( -name .deps -print -o -name CVS \ -o -exec test ! -d {}/CVS \; \) -prune \ -o \( -name '*.[ao]' -o -name '*.so' \) -type f -print`; \ build/autoconf/clean-config.sh; \ fi; +## Sanity check $X and js/src/$X are in sync +.PHONY: check-sync-dirs +check-sync-dirs: check-sync-dirs-build check-sync-dirs-config +check-sync-dirs-%: + @$(PYTHON) $(TOPSRCDIR)/js/src/config/check-sync-dirs.py $(TOPSRCDIR)/js/src/$* $(TOPSRCDIR)/$* + echo-variable-%: @echo $($*) # This makefile doesn't support parallel execution. It does pass # MOZ_MAKE_FLAGS to sub-make processes, so they will correctly execute # in parallel. .NOTPARALLEL:
--- a/config/expandlibs_gen.py +++ b/config/expandlibs_gen.py @@ -42,16 +42,21 @@ import sys import os import expandlibs_config as conf from expandlibs import LibDescriptor, isObject def generate(args): desc = LibDescriptor() for arg in args: if isObject(arg): - desc['OBJS'].append(os.path.abspath(arg)) - elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX and \ - (os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX)): - desc['LIBS'].append(os.path.abspath(arg)) + if os.path.exists(arg): + desc['OBJS'].append(os.path.abspath(arg)) + else: + raise Exception("File not found: %s" % arg) + elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX: + if os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX): + desc['LIBS'].append(os.path.abspath(arg)) + else: + raise Exception("File not found: %s" % arg) return desc if __name__ == '__main__': print generate(sys.argv[1:])
--- a/config/tests/unit-expandlibs.py +++ b/config/tests/unit-expandlibs.py @@ -140,16 +140,19 @@ class TestExpandLibsGen(TestCaseWithTmpD [Lib('a'), Obj('b'), Lib('c'), Obj('d'), Obj('e'), Lib('f')]] self.touch(files[:-1]) self.touch([files[-1] + config.LIBS_DESC_SUFFIX]) desc = generate(files) self.assertEqual(desc['OBJS'], [self.tmpfile(Obj(s)) for s in ['b', 'd', 'e']]) self.assertEqual(desc['LIBS'], [self.tmpfile(Lib(s)) for s in ['a', 'c', 'f']]) + self.assertRaises(Exception, generate, files + [self.tmpfile(Obj('z'))]) + self.assertRaises(Exception, generate, files + [self.tmpfile(Lib('y'))]) + class TestExpandInit(TestCaseWithTmpDir): def init(self): ''' Initializes test environment for library expansion tests''' super(TestExpandInit, self).init() # Create 2 fake libraries, each containing 3 objects, and the second # including the first one and another library. os.mkdir(self.tmpfile('libx')) os.mkdir(self.tmpfile('liby'))
--- a/configure.in +++ b/configure.in @@ -3375,17 +3375,17 @@ else [XSS_LIBS="-lXss $XEXT_LIBS $XLIBS" AC_DEFINE(HAVE_LIBXSS)],, $XEXT_LIBS $XLIBS)) LDFLAGS="$_SAVE_LDFLAGS" dnl ======================================================== dnl = Check for freetype2 and its functionality dnl ======================================================== - AC_CHECK_FT2(6.1.0, [_HAVE_FREETYPE2=1], [_HAVE_FREETYPE2=]) + PKG_CHECK_MODULES(FT2, freetype2 >= 6.1.0, _HAVE_FREETYPE2=1, _HAVE_FREETYPE2=) if test "$_HAVE_FREETYPE2"; then _SAVE_LIBS="$LIBS" _SAVE_CFLAGS="$CFLAGS" LIBS="$LIBS $FT2_LIBS" CFLAGS="$CFLAGS $FT2_CFLAGS" AC_CACHE_CHECK(for FT_Bitmap_Size.y_ppem, @@ -7209,23 +7209,16 @@ else rm crtdll.obj export DLLFLAGS ;; *) AC_MSG_ERROR([--enable-jemalloc not supported on ${target}]) ;; esac - - if test "$OS_ARCH" != "WINNT"; then - dnl NB: this must be kept in sync with jemalloc.h - AC_DEFINE(HAVE_JEMALLOC_VALLOC) - fi - AC_DEFINE(HAVE_JEMALLOC_POSIX_MEMALIGN) - AC_DEFINE(HAVE_JEMALLOC_MEMALIGN) fi # MOZ_MEMORY AC_SUBST(MOZ_MEMORY) AC_SUBST(MOZ_GLUE_LDFLAGS) AC_SUBST(MOZ_GLUE_PROGRAM_LDFLAGS) AC_SUBST(WIN32_CRT_LIBS) dnl Need to set this for make because NSS doesn't have configure AC_SUBST(DLLFLAGS)
--- a/content/base/public/nsIContent.h +++ b/content/base/public/nsIContent.h @@ -795,19 +795,24 @@ public: /** * Get the inline style rule, if any, for this content node */ virtual mozilla::css::StyleRule* GetInlineStyleRule() = 0; /** * Set the inline style rule for this node. This will send an - * appropriate AttributeChanged notification if aNotify is true. + * appropriate AttributeChanged notification if aNotify is true. If + * a serialized form of aStyleRule is available, a pointer to it + * should be passed in aSerialized. Otherwise, aSerialized should + * be null. */ - NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify) = 0; + NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, + const nsAString* aSerialized, + bool aNotify) = 0; /** * Is the attribute named stored in the mapped attributes? * * // XXXbz we use this method in HasAttributeDependentStyle, so svg * returns true here even though it stores nothing in the mapped * attributes. */
--- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -1637,17 +1637,17 @@ public: // only appear at the top of the DOM tree, we have a specialized measurement // function which returns multiple sizes. virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const; // DocSizeOfIncludingThis doesn't need to be overridden by sub-classes // because nsIDocument inherits from nsINode; see the comment above the // declaration of nsINode::SizeOfIncludingThis. virtual void DocSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const; - PRBool MayHaveDOMMutationObservers() + bool MayHaveDOMMutationObservers() { return mMayHaveDOMMutationObservers; } void SetMayHaveDOMMutationObservers() { mMayHaveDOMMutationObservers = true; }
--- a/content/base/src/nsDOMMutationObserver.cpp +++ b/content/base/src/nsDOMMutationObserver.cpp @@ -380,16 +380,22 @@ nsMutationReceiver::ContentRemoved(nsIDo m->mPreviousSibling = aPreviousSibling; m->mNextSibling = parent->GetChildAt(aIndexInContainer); } // We need to schedule always, so that after microtask mTransientReceivers // can be cleared correctly. Observer()->ScheduleForRun(); } +void nsMutationReceiver::NodeWillBeDestroyed(const nsINode *aNode) +{ + NS_ASSERTION(!mParent, "Shouldn't have mParent here!"); + Disconnect(true); +} + // Observer NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMMutationObserver) DOMCI_DATA(MozMutationObserver, nsDOMMutationObserver) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMMutationObserver) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozMutationObserver)
--- a/content/base/src/nsDOMMutationObserver.h +++ b/content/base/src/nsDOMMutationObserver.h @@ -260,44 +260,22 @@ public: void Disconnect(bool aRemoveFromObserver); NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMUTATION_OBSERVER_IID) NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(nsMutationReceiver) - virtual void AttributeWillChange(nsIDocument* aDocument, - mozilla::dom::Element* aElement, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aModType); - virtual void CharacterDataWillChange(nsIDocument *aDocument, - nsIContent* aContent, - CharacterDataChangeInfo* aInfo); - virtual void ContentAppended(nsIDocument *aDocument, - nsIContent* aContainer, - nsIContent* aFirstNewContent, - PRInt32 aNewIndexInContainer); - virtual void ContentInserted(nsIDocument *aDocument, - nsIContent* aContainer, - nsIContent* aChild, - PRInt32 aIndexInContainer); - virtual void ContentRemoved(nsIDocument *aDocument, - nsIContent* aContainer, - nsIContent* aChild, - PRInt32 aIndexInContainer, - nsIContent* aPreviousSibling); - - virtual void NodeWillBeDestroyed(const nsINode *aNode) - { - NS_ASSERTION(!mParent, "Shouldn't have mParent here!"); - Disconnect(true); - } - + NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE + NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE + NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED + NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED + NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED }; NS_DEFINE_STATIC_IID_ACCESSOR(nsMutationReceiver, NS_MUTATION_OBSERVER_IID) class nsDOMMutationObserver : public nsIDOMMozMutationObserver, public nsIJSNativeInitializer { public:
--- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3148,18 +3148,20 @@ nsDocument::TryChannelCharset(nsIChannel if(kCharsetFromChannel <= aCharsetSource) { return true; } if (aChannel) { nsCAutoString charsetVal; nsresult rv = aChannel->GetContentCharset(charsetVal); if (NS_SUCCEEDED(rv)) { - rv = nsCharsetAlias::GetPreferred(charsetVal, aCharset); + nsCAutoString preferred; + rv = nsCharsetAlias::GetPreferred(charsetVal, preferred); if(NS_SUCCEEDED(rv)) { + aCharset = preferred; aCharsetSource = kCharsetFromChannel; return true; } else if (aExecutor && !charsetVal.IsEmpty()) { aExecutor->ComplainAboutBogusProtocolCharset(this); } } } return false;
--- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -975,16 +975,17 @@ nsGenericDOMDataNode::SetSMILOverrideSty css::StyleRule* nsGenericDOMDataNode::GetInlineStyleRule() { return nsnull; } NS_IMETHODIMP nsGenericDOMDataNode::SetInlineStyleRule(css::StyleRule* aStyleRule, + const nsAString* aSerialized, bool aNotify) { NS_NOTREACHED("How come we're setting inline style on a non-element?"); return NS_ERROR_UNEXPECTED; } NS_IMETHODIMP_(bool) nsGenericDOMDataNode::IsAttributeMapped(const nsIAtom* aAttribute) const
--- a/content/base/src/nsGenericDOMDataNode.h +++ b/content/base/src/nsGenericDOMDataNode.h @@ -243,17 +243,18 @@ public: virtual nsIContent *GetBindingParent() const; virtual bool IsNodeOfType(PRUint32 aFlags) const; virtual bool IsLink(nsIURI** aURI) const; virtual nsIAtom* DoGetID() const; virtual const nsAttrValue* DoGetClasses() const; NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker); virtual mozilla::css::StyleRule* GetInlineStyleRule(); - NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify); + NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, + const nsAString* aSerialized, bool aNotify); NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const; virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, PRInt32 aModType) const; virtual nsIAtom *GetClassAttributeName() const; virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const { *aResult = CloneDataNode(aNodeInfo, true);
--- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -3604,16 +3604,17 @@ nsGenericElement::SetSMILOverrideStyleRu css::StyleRule* nsGenericElement::GetInlineStyleRule() { return nsnull; } NS_IMETHODIMP nsGenericElement::SetInlineStyleRule(css::StyleRule* aStyleRule, + const nsAString* aSerialized, bool aNotify) { NS_NOTYETIMPLEMENTED("nsGenericElement::SetInlineStyleRule"); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP_(bool) nsGenericElement::IsAttributeMapped(const nsIAtom* aAttribute) const
--- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -363,17 +363,19 @@ public: virtual void DumpContent(FILE* out, PRInt32 aIndent, bool aDumpAll) const; void List(FILE* out, PRInt32 aIndent, const nsCString& aPrefix) const; void ListAttributes(FILE* out) const; #endif virtual const nsAttrValue* DoGetClasses() const; NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker); virtual mozilla::css::StyleRule* GetInlineStyleRule(); - NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify); + NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, + const nsAString* aSerialized, + bool aNotify); NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const; virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute, PRInt32 aModType) const; /* * Attribute Mapping Helpers */ struct MappedAttributeEntry { @@ -1041,16 +1043,35 @@ nsresult DOMCI_DATA(_interface, _class) \ nsXPCClassInfo* _class::GetClassInfo() \ { \ return static_cast<nsXPCClassInfo*>( \ NS_GetDOMClassInfoInstance(eDOMClassInfo_##_interface##_id)); \ } /** + * A macro to implement the getter and setter for a given string + * valued content property. The method uses the generic GetAttr and + * SetAttr methods. We use the 5-argument form of SetAttr, because + * some consumers only implement that one, hiding superclass + * 4-argument forms. + */ +#define NS_IMPL_STRING_ATTR(_class, _method, _atom) \ + NS_IMETHODIMP \ + _class::Get##_method(nsAString& aValue) \ + { \ + return GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue); \ + } \ + NS_IMETHODIMP \ + _class::Set##_method(const nsAString& aValue) \ + { \ + return SetAttr(kNameSpaceID_None, nsGkAtoms::_atom, nsnull, aValue, true); \ + } + +/** * Tearoff class to implement nsITouchEventReceiver */ class nsTouchEventReceiverTearoff : public nsITouchEventReceiver { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_FORWARD_NSITOUCHEVENTRECEIVER(mElement->)
--- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -2032,16 +2032,17 @@ GK_ATOM(containerBusy, "container-busy") GK_ATOM(containerLive, "container-live") GK_ATOM(containerLiveRole, "container-live-role") GK_ATOM(containerRelevant, "container-relevant") GK_ATOM(cycles, "cycles") GK_ATOM(datatable, "datatable") GK_ATOM(droppable, "droppable") GK_ATOM(eventFromInput, "event-from-input") GK_ATOM(InlineBlockFrame, "InlineBlockFrame") +GK_ATOM(inlinevalue, "inline") GK_ATOM(invalid, "invalid") GK_ATOM(item, "item") GK_ATOM(itemset, "itemset") GK_ATOM(lineNumber, "line-number") GK_ATOM(linkedPanel, "linkedpanel") GK_ATOM(live, "live") GK_ATOM(marginBottom, "margin-bottom") GK_ATOM(marginLeft, "margin-left")
--- a/content/base/src/nsStyledElement.cpp +++ b/content/base/src/nsStyledElement.cpp @@ -158,16 +158,17 @@ nsStyledElementNotElementCSSInlineStyle: } return nsGenericElement::AfterSetAttr(aNamespaceID, aAttribute, aValue, aNotify); } NS_IMETHODIMP nsStyledElementNotElementCSSInlineStyle::SetInlineStyleRule(css::StyleRule* aStyleRule, + const nsAString* aSerialized, bool aNotify) { SetMayHaveStyle(); bool modification = false; nsAttrValue oldValue; bool hasListeners = aNotify && nsContentUtils::HasMutationListeners(this, @@ -188,17 +189,17 @@ nsStyledElementNotElementCSSInlineStyle: if (modification) { oldValue.SetTo(oldValueStr); } } else if (aNotify && IsInDoc()) { modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style); } - nsAttrValue attrValue(aStyleRule, nsnull); + nsAttrValue attrValue(aStyleRule, aSerialized); // XXXbz do we ever end up with ADDITION here? I doubt it. PRUint8 modType = modification ? static_cast<PRUint8>(nsIDOMMutationEvent::MODIFICATION) : static_cast<PRUint8>(nsIDOMMutationEvent::ADDITION); return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nsnull, oldValue, attrValue, modType, hasListeners,
--- a/content/base/src/nsStyledElement.h +++ b/content/base/src/nsStyledElement.h @@ -69,17 +69,19 @@ protected: public: // nsIContent interface methods virtual nsIAtom* GetClassAttributeName() const; virtual nsIAtom* GetIDAttributeName() const; virtual nsIAtom* DoGetID() const; virtual const nsAttrValue* DoGetClasses() const; virtual mozilla::css::StyleRule* GetInlineStyleRule(); - NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify); + NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, + const nsAString* aSerialized, + bool aNotify); virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, bool aNotify); virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, const nsAttrValue* aValue, bool aNotify); nsIDOMCSSStyleDeclaration* GetStyle(nsresult* retval);
new file mode 100644 --- /dev/null +++ b/content/base/test/unit/test_bug737966.js @@ -0,0 +1,20 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/* If charset parameter is invalid, the encoding should be detected as UTF-8 */ + +function run_test() +{ + let body = '<?xml version="1.0"><html>%c3%80</html>'; + let result = '<?xml version="1.0"><html>\u00c0</html>'; + + let xhr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1']. + createInstance(Components.interfaces.nsIXMLHttpRequest); + xhr.open('GET', + 'data:text/xml;charset=abc,' + body, + false); + xhr.send(null); + + do_check_eq(xhr.responseText, result); +}
--- a/content/base/test/unit/xpcshell.ini +++ b/content/base/test/unit/xpcshell.ini @@ -1,11 +1,12 @@ [DEFAULT] head = head_utilities.js tail = [test_bug553888.js] [test_bug558431.js] +[test_bug737966.js] [test_csputils.js] [test_error_codes.js] [test_thirdpartyutil.js] [test_xhr_standalone.js] [test_xmlserializer.js]
--- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -3117,28 +3117,30 @@ NS_IMETHODIMP WebGLContext::Hint(WebGLenum target, WebGLenum mode) { if (!IsContextStable()) return NS_OK; bool isValid = false; switch (target) { + case LOCAL_GL_GENERATE_MIPMAP_HINT: + isValid = true; + break; case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT: if (mEnabledExtensions[WebGL_OES_standard_derivatives]) isValid = true; break; } - if (isValid) { - gl->fHint(target, mode); - return NS_OK; - } - - return ErrorInvalidEnum("hint: invalid hint"); + if (!isValid) + return ErrorInvalidEnum("hint: invalid hint"); + + gl->fHint(target, mode); + return NS_OK; } NS_IMETHODIMP WebGLContext::IsBuffer(nsIWebGLBuffer *bobj, WebGLboolean *retval) { if (!IsContextStable()) { *retval = false;
--- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -891,17 +891,18 @@ NS_METHOD nsDOMEvent::DuplicatePrivateDa newEvent = new nsMozTouchEvent(false, msg, nsnull, static_cast<nsMozTouchEvent*>(mEvent)->streamId); NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY); isInputEvent = true; break; } case NS_TOUCH_EVENT: { - newEvent = new nsTouchEvent(false, msg, nsnull); + nsTouchEvent *oldTouchEvent = static_cast<nsTouchEvent*>(mEvent); + newEvent = new nsTouchEvent(false, oldTouchEvent); NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY); isInputEvent = true; break; } default: { NS_WARNING("Unknown event type!!!"); return NS_ERROR_FAILURE;
--- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -285,26 +285,19 @@ nsEventListenerManager::AddEventListener if (window) { // If aType is NS_MUTATION_SUBTREEMODIFIED, we need to listen all // mutations. nsContentUtils::HasMutationListeners relies on this. window->SetMutationListeners((aType == NS_MUTATION_SUBTREEMODIFIED) ? kAllMutationBits : MutationBitForEventType(aType)); } } else if (aTypeAtom == nsGkAtoms::ondeviceorientation) { - nsPIDOMWindow* window = GetInnerWindowForTarget(); - if (window) - window->EnableDeviceSensor(SENSOR_ORIENTATION); + EnableDevice(NS_DEVICE_ORIENTATION); } else if (aTypeAtom == nsGkAtoms::ondevicemotion) { - nsPIDOMWindow* window = GetInnerWindowForTarget(); - if (window) { - window->EnableDeviceSensor(SENSOR_ACCELERATION); - window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION); - window->EnableDeviceSensor(SENSOR_GYROSCOPE); - } + EnableDevice(NS_DEVICE_MOTION); } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) || (aTypeAtom == nsGkAtoms::ontouchstart || aTypeAtom == nsGkAtoms::ontouchend || aTypeAtom == nsGkAtoms::ontouchmove || aTypeAtom == nsGkAtoms::ontouchenter || aTypeAtom == nsGkAtoms::ontouchleave || aTypeAtom == nsGkAtoms::ontouchcancel)) { mMayHaveTouchEventListener = true; @@ -336,22 +329,50 @@ nsEventListenerManager::IsDeviceType(PRU return true; default: break; } return false; } void -nsEventListenerManager::DisableDevice(PRUint32 aType) +nsEventListenerManager::EnableDevice(PRUint32 aType) { - nsPIDOMWindow* window = GetInnerWindowForTarget(); + nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget); if (!window) { return; } + + NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window"); + + switch (aType) { + case NS_DEVICE_ORIENTATION: + window->EnableDeviceSensor(SENSOR_ORIENTATION); + break; + case NS_DEVICE_MOTION: + window->EnableDeviceSensor(SENSOR_ACCELERATION); + window->EnableDeviceSensor(SENSOR_LINEAR_ACCELERATION); + window->EnableDeviceSensor(SENSOR_GYROSCOPE); + break; + default: + NS_WARNING("Enabling an unknown device sensor."); + break; + } +} + +void +nsEventListenerManager::DisableDevice(PRUint32 aType) +{ + nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mTarget); + if (!window) { + return; + } + + NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window"); + switch (aType) { case NS_DEVICE_ORIENTATION: window->DisableDeviceSensor(SENSOR_ORIENTATION); break; case NS_DEVICE_MOTION: window->DisableDeviceSensor(SENSOR_ACCELERATION); window->DisableDeviceSensor(SENSOR_LINEAR_ACCELERATION); window->DisableDeviceSensor(SENSOR_GYROSCOPE); @@ -372,38 +393,39 @@ nsEventListenerManager::RemoveEventListe return; } nsListenerStruct* ls; aFlags &= ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED; PRUint32 count = mListeners.Length(); PRUint32 typeCount = 0; + bool deviceType = IsDeviceType(aType); for (PRUint32 i = 0; i < count; ++i) { ls = &mListeners.ElementAt(i); if (EVENT_TYPE_EQUALS(ls, aType, aUserType)) { ++typeCount; if (ls->mListener == aListener && (ls->mFlags & ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED) == aFlags) { nsRefPtr<nsEventListenerManager> kungFuDeathGrip = this; mListeners.RemoveElementAt(i); --count; mNoListenerForEvent = NS_EVENT_TYPE_NULL; mNoListenerForEventAtom = nsnull; - if (!IsDeviceType(aType)) { + if (deviceType) { return; } --typeCount; } } } - if (typeCount == 0) { + if (deviceType && typeCount == 0) { DisableDevice(aType); } } static inline bool ListenerCanHandle(nsListenerStruct* aLs, nsEvent* aEvent) { // This is slightly different from EVENT_TYPE_EQUALS in that it returns
--- a/content/events/src/nsEventListenerManager.h +++ b/content/events/src/nsEventListenerManager.h @@ -279,16 +279,17 @@ protected: nsresult SetJSEventListener(nsIScriptContext *aContext, JSObject* aScopeGlobal, nsIAtom* aName, JSObject *aHandler, bool aPermitUntrustedEvents, nsListenerStruct **aListenerStruct); bool IsDeviceType(PRUint32 aType); + void EnableDevice(PRUint32 aType); void DisableDevice(PRUint32 aType); public: /** * Set the "inline" event listener for aEventName to |v|. This * might actually remove the event listener, depending on the value * of |v|. */
--- a/content/events/test/Makefile.in +++ b/content/events/test/Makefile.in @@ -109,16 +109,17 @@ include $(topsrcdir)/config/rules.mk test_bug667919-1.html \ test_bug667919-2.html \ test_bug667612.html \ empty.js \ test_bug689564.html \ test_bug698929.html \ test_eventctors.html \ test_bug635465.html \ + test_bug741666.html \ $(NULL) #bug 585630 ifneq (mobile,$(MOZ_BUILD_APP)) _TEST_FILES += \ test_dragstart.html \ $(NULL) endif
new file mode 100644 --- /dev/null +++ b/content/events/test/test_bug741666.html @@ -0,0 +1,176 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=741666 +--> +<head> + <title>Test for Bug 741666</title> + <script type="text/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=741666">Mozilla Bug 741666</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script class="testbody" type="application/javascript;version=1.8"> + +/** Test for Bug 306008 - Touch events with a reference held should retain their touch lists **/ + +let tests = [], testTarget, parent; + +let touch = { + id: 0, + point: {x: 0, y: 0}, + radius: {x: 0, y: 0}, + rotation: 0, + force: 0.5, + target: null +} + +function nextTest() { + if (tests.length) + SimpleTest.executeSoon(tests.shift()); +} + +function checkEvent(aFakeEvent, aTouches) { + return function(aEvent, aTrusted) { + is(aFakeEvent.ctrlKey, aEvent.ctrlKey, "Correct ctrlKey"); + is(aFakeEvent.altKey, aEvent.altKey, "Correct altKey"); + is(aFakeEvent.shiftKey, aEvent.shiftKey, "Correct shiftKey"); + is(aFakeEvent.metaKey, aEvent.metaKey, "Correct metaKey"); + is(aEvent.isTrusted, aTrusted, "Event is trusted"); + checkTouches(aFakeEvent[aTouches], aEvent[aTouches]); + } +} + +function checkTouches(aTouches1, aTouches2) { + is(aTouches1.length, aTouches2.length, "Correct touches length"); + for (var i = 0; i < aTouches1.length; i++) { + checkTouch(aTouches1[i], aTouches2[i]); + } +} + +function checkTouch(aFakeTouch, aTouch) { + is(aFakeTouch.identifier, aTouch.identifier, "Touch has correct identifier"); + is(aFakeTouch.target, aTouch.target, "Touch has correct target"); + is(aFakeTouch.page.x, aTouch.pageX, "Touch has correct pageX"); + is(aFakeTouch.page.y, aTouch.pageY, "Touch has correct pageY"); + is(aFakeTouch.page.x + Math.round(window.mozInnerScreenX), aTouch.screenX, "Touch has correct screenX"); + is(aFakeTouch.page.y + Math.round(window.mozInnerScreenY), aTouch.screenY, "Touch has correct screenY"); + is(aFakeTouch.page.x, aTouch.clientX, "Touch has correct clientX"); + is(aFakeTouch.page.y, aTouch.clientY, "Touch has correct clientY"); + is(aFakeTouch.radius.x, aTouch.radiusX, "Touch has correct radiusX"); + is(aFakeTouch.radius.y, aTouch.radiusY, "Touch has correct radiusY"); + is(aFakeTouch.rotationAngle, aTouch.rotationAngle, "Touch has correct rotationAngle"); + is(aFakeTouch.force, aTouch.force, "Touch has correct force"); +} + +function sendTouchEvent(windowUtils, aType, aEvent, aModifiers) { + var ids = [], xs=[], ys=[], rxs = [], rys = [], + rotations = [], forces = []; + + for each (var touchType in ["touches", "changedTouches", "targetTouches"]) { + for (var i = 0; i < aEvent[touchType].length; i++) { + if (ids.indexOf(aEvent[touchType][i].identifier) == -1) { + ids.push(aEvent[touchType][i].identifier); + xs.push(aEvent[touchType][i].page.x); + ys.push(aEvent[touchType][i].page.y); + rxs.push(aEvent[touchType][i].radius.x); + rys.push(aEvent[touchType][i].radius.y); + rotations.push(aEvent[touchType][i].rotationAngle); + forces.push(aEvent[touchType][i].force); + } + } + } + return windowUtils.sendTouchEvent(aType, + ids, xs, ys, rxs, rys, + rotations, forces, + ids.length, aModifiers, 0); +} + +function touchEvent(aOptions) { + if (!aOptions) { + aOptions = {}; + } + this.ctrlKey = aOptions.ctrlKey || false; + this.altKey = aOptions.altKey || false; + this.shiftKey = aOptions.shiftKey || false; + this.metaKey = aOptions.metaKey || false; + this.touches = aOptions.touches || []; + this.targetTouches = aOptions.targetTouches || []; + this.changedTouches = aOptions.changedTouches || []; +} + +function testtouch(aOptions) { + if (!aOptions) + aOptions = {}; + this.identifier = aOptions.identifier || 0; + this.target = aOptions.target || 0; + this.page = aOptions.page || {x: 0, y: 0}; + this.radius = aOptions.radius || {x: 0, y: 0}; + this.rotationAngle = aOptions.rotationAngle || 0; + this.force = aOptions.force || 1; +} + +function testPreventDefault(name) { + let cwu = SpecialPowers.getDOMWindowUtils(window); + let target = document.getElementById("testTarget"); + let bcr = target.getBoundingClientRect(); + + let touch1 = new testtouch({ + page: {x: Math.round(bcr.left + bcr.width/2), + y: Math.round(bcr.top + bcr.height/2)}, + target: target + }); + + let event = new touchEvent({ + touches: [touch1], + targetTouches: [touch1], + changedTouches: [touch1] + }); + + // test touchstart event fires correctly + var checkTouches = checkEvent(event, "touches"); + var checkTargetTouches = checkEvent(event, "targetTouches"); + + /* This is the heart of the test. Verify that the touch event + looks correct both in and outside of a setTimeout */ + window.addEventListener("touchstart", function(firedEvent) { + checkTouches(firedEvent, true); + setTimeout(function() { + checkTouches(firedEvent, true); + checkTargetTouches(firedEvent, true); + + event.touches = []; + event.targetTouches = []; + sendTouchEvent(cwu, "touchend", event, 0); + + nextTest(); + }, 0); + }, false); + sendTouchEvent(cwu, "touchstart", event, 0); +} + +function doTest() { + tests.push(testPreventDefault); + + tests.push(function() { + SimpleTest.finish(); + }); + + nextTest(); +} + +SimpleTest.waitForExplicitFinish(); +addLoadEvent(doTest); + +</script> +</pre> +<div id="parent"> + <span id="testTarget" style="padding: 5px; border: 1px solid black;">testTarget</span> +</div> +</body> +</html>
--- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -309,33 +309,35 @@ nsGenericHTMLElement::DOMQueryInterface( nsresult nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst) const { nsresult rv; PRInt32 i, count = GetAttrCount(); for (i = 0; i < count; ++i) { const nsAttrName *name = mAttrsAndChildren.AttrNameAt(i); const nsAttrValue *value = mAttrsAndChildren.AttrAt(i); + + nsAutoString valStr; + value->ToString(valStr); + if (name->Equals(nsGkAtoms::style, kNameSpaceID_None) && value->Type() == nsAttrValue::eCSSStyleRule) { // We can't just set this as a string, because that will fail // to reparse the string into style data until the node is // inserted into the document. Clone the Rule instead. nsRefPtr<mozilla::css::Rule> ruleClone = value->GetCSSStyleRuleValue()->Clone(); nsRefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(ruleClone); NS_ENSURE_TRUE(styleRule, NS_ERROR_UNEXPECTED); - rv = aDst->SetInlineStyleRule(styleRule, false); + rv = aDst->SetInlineStyleRule(styleRule, &valStr, false); NS_ENSURE_SUCCESS(rv, rv); continue; } - nsAutoString valStr; - value->ToString(valStr); rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(), valStr, false); NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; } @@ -2257,23 +2259,16 @@ nsGenericHTMLElement::MapScrollingAttrib } } } } //---------------------------------------------------------------------- nsresult -nsGenericHTMLElement::GetAttrHelper(nsIAtom* aAttr, nsAString& aValue) -{ - GetAttr(kNameSpaceID_None, aAttr, aValue); - return NS_OK; -} - -nsresult nsGenericHTMLElement::SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue) { return SetAttr(kNameSpaceID_None, aAttr, aValue, true); } nsresult nsGenericHTMLElement::SetBoolAttr(nsIAtom* aAttr, bool aValue) {
--- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -604,28 +604,16 @@ protected: virtual nsEventListenerManager* GetEventListenerManagerForAttr(nsIAtom* aAttrName, bool* aDefer); virtual const nsAttrName* InternalGetExistingAttrNameFromQName(const nsAString& aStr) const; /** * Helper method for NS_IMPL_STRING_ATTR macro. - * Gets the value of an attribute, returns empty string if - * attribute isn't set. Only works for attributes in null namespace. - * - * @param aAttr name of attribute. - * @param aDefault default-value to return if attribute isn't set. - * @param aResult result value [out] - * @result always NS_OK - */ - NS_HIDDEN_(nsresult) GetAttrHelper(nsIAtom* aAttr, nsAString& aValue); - - /** - * Helper method for NS_IMPL_STRING_ATTR macro. * Sets the value of an attribute, returns specified default value if the * attribute isn't set. Only works for attributes in null namespace. * * @param aAttr name of attribute. * @param aDefault default-value to return if attribute isn't set. * @param aResult result value [out] */ NS_HIDDEN_(nsresult) SetAttrHelper(nsIAtom* aAttr, const nsAString& aValue); @@ -1002,33 +990,16 @@ protected: // same bit. --bz // Make sure we have enough space for those bits PR_STATIC_ASSERT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32); //---------------------------------------------------------------------- /** - * A macro to implement the getter and setter for a given string - * valued content property. The method uses the generic GetAttr and - * SetAttr methods. - */ -#define NS_IMPL_STRING_ATTR(_class, _method, _atom) \ - NS_IMETHODIMP \ - _class::Get##_method(nsAString& aValue) \ - { \ - return GetAttrHelper(nsGkAtoms::_atom, aValue); \ - } \ - NS_IMETHODIMP \ - _class::Set##_method(const nsAString& aValue) \ - { \ - return SetAttrHelper(nsGkAtoms::_atom, aValue); \ - } - -/** * This macro is similar to NS_IMPL_STRING_ATTR except that the getter method * falls back to an alternative method if the content attribute isn't set. */ #define NS_IMPL_STRING_ATTR_WITH_FALLBACK(_class, _method, _atom, _fallback) \ NS_IMETHODIMP \ _class::Get##_method(nsAString& aValue) \ { \ if (!GetAttr(kNameSpaceID_None, nsGkAtoms::_atom, aValue)) { \
--- a/content/html/content/src/nsHTMLScriptElement.cpp +++ b/content/html/content/src/nsHTMLScriptElement.cpp @@ -238,16 +238,17 @@ nsHTMLScriptElement::SetText(const nsASt NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Charset, charset) NS_IMPL_BOOL_ATTR(nsHTMLScriptElement, Defer, defer) NS_IMPL_URI_ATTR(nsHTMLScriptElement, Src, src) NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Type, type) NS_IMPL_STRING_ATTR(nsHTMLScriptElement, HtmlFor, _for) NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Event, event) +NS_IMPL_STRING_ATTR(nsHTMLScriptElement, CrossOrigin, crossorigin) nsresult nsHTMLScriptElement::GetAsync(bool* aValue) { if (mForceAsync) { *aValue = true; return NS_OK; }
--- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -294,16 +294,18 @@ include $(topsrcdir)/config/rules.mk file_fullscreen-esc-exit-inner.html \ file_fullscreen-rollback.html \ file_fullscreen-svg-element.html \ test_li_attributes_reflection.html \ test_ol_attributes_reflection.html \ test_bug651956.html \ test_bug694503.html \ test_object_plugin_nav.html \ + test_bug742030.html \ + test_bug742549.html \ $(NULL) _BROWSER_TEST_FILES = \ browser_bug649778.js \ file_bug649778.html \ file_bug649778.html^headers^ \ $(NULL)
new file mode 100644 --- /dev/null +++ b/content/html/content/test/test_bug742030.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=742030 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 742030</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=742030">Mozilla Bug 742030</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 742030 **/ +const str = " color: #ff0000 "; +var span = document.createElement("span"); +span.setAttribute("style", str); +is(span.getAttribute("style"), str, "Should have set properly"); +var span2 = span.cloneNode(false); +is(span2.getAttribute("style"), str, "Should have cloned properly"); +</script> +</pre> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/content/html/content/test/test_bug742549.html @@ -0,0 +1,40 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=742549 +--> +<head> + <meta charset="utf-8"> + <title>Test for Bug 742549</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="application/javascript" src="reflect.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=742549">Mozilla Bug 742549</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +<script type="application/javascript"> + +/** Test for Bug 742549 **/ +var els = [ document.createElement("script"), + document.createElementNS("http://www.w3.org/2000/svg", "script") ] + +for (var i = 0; i < els.length; ++i) { + reflectString({ + element: els[i], + attribute: { content: "crossorigin", idl: "crossOrigin" }, + otherValues: [ "anonymous", "use-credentials" ] + }) +} + + + + +</script> +</pre> +</body> +</html>
--- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -3119,32 +3119,16 @@ nsHTMLDocument::ExecCommand(const nsAStr rv = cmdMgr->DoCommand(cmdToDispatch.get(), cmdParams, window); } *_retval = NS_SUCCEEDED(rv); return rv; } -/* TODO: don't let this call do anything if the page is not done loading */ -/* boolean execCommandShowHelp(in DOMString commandID); */ -NS_IMETHODIMP -nsHTMLDocument::ExecCommandShowHelp(const nsAString & commandID, - bool *_retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - *_retval = false; - - // if editing is not on, bail - if (!IsEditingOnAfterFlush()) - return NS_ERROR_FAILURE; - - return NS_ERROR_NOT_IMPLEMENTED; -} - /* boolean queryCommandEnabled(in DOMString commandID); */ NS_IMETHODIMP nsHTMLDocument::QueryCommandEnabled(const nsAString & commandID, bool *_retval) { NS_ENSURE_ARG_POINTER(_retval); *_retval = false; @@ -3301,30 +3285,16 @@ nsHTMLDocument::QueryCommandSupported(co // commandID is supported if it can be converted to a Midas command nsCAutoString cmdToDispatch; if (ConvertToMidasInternalCommand(commandID, cmdToDispatch)) *_retval = true; return NS_OK; } -/* DOMString queryCommandText(in DOMString commandID); */ -NS_IMETHODIMP -nsHTMLDocument::QueryCommandText(const nsAString & commandID, - nsAString & _retval) -{ - _retval.SetLength(0); - - // if editing is not on, bail - if (!IsEditingOnAfterFlush()) - return NS_ERROR_FAILURE; - - return NS_ERROR_NOT_IMPLEMENTED; -} - /* DOMString queryCommandValue(in DOMString commandID); */ NS_IMETHODIMP nsHTMLDocument::QueryCommandValue(const nsAString & commandID, nsAString &_retval) { _retval.SetLength(0); // if editing is not on, bail
--- a/content/html/document/test/Makefile.in +++ b/content/html/document/test/Makefile.in @@ -101,16 +101,17 @@ include $(topsrcdir)/config/rules.mk test_bug497242.xhtml \ test_bug499092.html \ bug499092.xml \ bug499092.html \ test_bug512367.html \ test_bug571981.html \ test_bug677495.html \ test_bug677495-1.html \ + test_bug742261.html \ $(NULL) ifneq (mobile,$(MOZ_BUILD_APP)) _BROWSER_TEST_FILES = \ browser_bug592641.js \ bug592641_img.jpg \ $(NULL) endif
new file mode 100644 --- /dev/null +++ b/content/html/document/test/test_bug742261.html @@ -0,0 +1,14 @@ +<!doctype html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=742261 +--> +<title>Test for Bug 742261</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<link rel="stylesheet" href="/tests/SimpleTest/test.css"/> +<body> +<script> +is(document.execCommandShowHelp, undefined, + "execCommandShowHelp shouldn't exist"); +is(document.queryCommandText, undefined, + "queryCommandText shouldn't exist"); +</script>
--- a/content/media/webm/nsWebMReader.cpp +++ b/content/media/webm/nsWebMReader.cpp @@ -510,17 +510,17 @@ bool nsWebMReader::DecodeAudioPacket(nes NS_WARNING("Int overflow converting WebM audio total_duration"); return false; } CheckedInt64 time = total_duration + tstamp_usecs; if (!time.valid()) { NS_WARNING("Int overflow adding total_duration and tstamp_usecs"); nestegg_free_packet(aPacket); - return PR_FALSE; + return false; }; total_frames += frames; mAudioQueue.Push(new AudioData(aOffset, time.value(), duration.value(), frames, buffer.forget(),
--- a/content/svg/content/src/nsSVGScriptElement.cpp +++ b/content/svg/content/src/nsSVGScriptElement.cpp @@ -172,28 +172,19 @@ nsSVGScriptElement::Clone(nsINodeInfo *a return NS_OK; } //---------------------------------------------------------------------- // nsIDOMSVGScriptElement methods /* attribute DOMString type; */ -NS_IMETHODIMP -nsSVGScriptElement::GetType(nsAString & aType) -{ - GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType); - - return NS_OK; -} -NS_IMETHODIMP -nsSVGScriptElement::SetType(const nsAString & aType) -{ - return SetAttr(kNameSpaceID_None, nsGkAtoms::type, aType, true); -} +NS_IMPL_STRING_ATTR(nsSVGScriptElement, Type, type) +/* attribute DOMString crossOrigin */ +NS_IMPL_STRING_ATTR(nsSVGScriptElement, CrossOrigin, crossorigin) //---------------------------------------------------------------------- // nsIDOMSVGURIReference methods /* readonly attribute nsIDOMSVGAnimatedString href; */ NS_IMETHODIMP nsSVGScriptElement::GetHref(nsIDOMSVGAnimatedString * *aHref) {
--- a/content/xbl/src/nsXBLBinding.cpp +++ b/content/xbl/src/nsXBLBinding.cpp @@ -97,17 +97,17 @@ // Helper classes /***********************************************************************/ // // The JS class for XBLBinding // static void -XBLFinalize(JSContext *cx, JSObject *obj) +XBLFinalize(JSFreeOp *fop, JSObject *obj) { nsXBLDocumentInfo* docInfo = static_cast<nsXBLDocumentInfo*>(::JS_GetPrivate(obj)); NS_RELEASE(docInfo); nsXBLJSClass* c = static_cast<nsXBLJSClass*>(::JS_GetClass(obj)); c->Drop(); }
--- a/content/xbl/src/nsXBLContentSink.cpp +++ b/content/xbl/src/nsXBLContentSink.cpp @@ -901,19 +901,16 @@ nsXBLContentSink::CreateElement(const PR // Note that this needs to match the code in nsXBLPrototypeBinding::ReadContentNode. *aAppendContent = true; nsRefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement(); if (!prototype) return NS_ERROR_OUT_OF_MEMORY; prototype->mNodeInfo = aNodeInfo; - // XXX - we need to do exactly what the XUL content-sink does (eg, - // look for 'type', 'version' etc attributes) - prototype->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT; AddAttributesToXULPrototype(aAtts, aAttsCount, prototype); Element* result; nsresult rv = nsXULElement::Create(prototype, mDocument, false, &result); *aResult = result; return rv; #endif
--- a/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -167,17 +167,17 @@ nsXBLDocGlobalObject_checkAccess(JSConte translated = nsIXPCSecurityManager::ACCESS_GET_PROPERTY; } return nsXBLDocGlobalObject:: doCheckAccess(cx, obj, id, translated); } static void -nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj) +nsXBLDocGlobalObject_finalize(JSFreeOp *fop, JSObject *obj) { nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj); nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis)); if (sgo) sgo->OnFinalize(obj);
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -1874,17 +1874,16 @@ nsXBLPrototypeBinding::ReadContentNode(n #ifdef MOZ_XUL if (namespaceID == kNameSpaceID_XUL) { nsIURI* documentURI = aDocument->GetDocumentURI(); nsRefPtr<nsXULPrototypeElement> prototype = new nsXULPrototypeElement(); NS_ENSURE_TRUE(prototype, NS_ERROR_OUT_OF_MEMORY); prototype->mNodeInfo = nodeInfo; - prototype->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT; nsCOMPtr<Element> result; nsresult rv = nsXULElement::Create(prototype, aDocument, false, getter_AddRefs(result)); NS_ENSURE_SUCCESS(rv, rv); content = result; nsXULPrototypeAttribute* attrs = nsnull;
--- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -409,18 +409,16 @@ nsresult nsXULElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const { *aResult = nsnull; // If we have a prototype, so will our clone. nsRefPtr<nsXULElement> element; if (mPrototype) { element = nsXULElement::Create(mPrototype, aNodeInfo, true); - NS_ASSERTION(nsIProgrammingLanguage::JAVASCRIPT == mPrototype->mScriptTypeID, - "Didn't get the default language from proto?"); } else { nsCOMPtr<nsINodeInfo> ni = aNodeInfo; element = new nsXULElement(ni.forget()); } if (!element) { return NS_ERROR_OUT_OF_MEMORY; @@ -1088,29 +1086,22 @@ nsXULElement::AfterSetAttr(PRInt32 aName { if (aNamespaceID == kNameSpaceID_None) { // XXX UnsetAttr handles more attributes than we do. See bug 233642. // Add popup and event listeners. We can't call AddListenerFor since // the attribute isn't set yet. MaybeAddPopupListener(aName); if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL) && aValue) { - // If mPrototype->mScriptTypeID != nsIProgrammingLanguage::JAVASCRIPT, it means - // we are resolving an overlay with a different default script - // language. We can't defer compilation of those handlers as - // we will have lost the script language (storing it on each - // nsXULPrototypeAttribute is expensive!) - bool defer = mPrototype == nsnull || - mPrototype->mScriptTypeID == nsIProgrammingLanguage::JAVASCRIPT; if (aValue->Type() == nsAttrValue::eString) { - AddScriptEventListener(aName, aValue->GetStringValue(), defer); + AddScriptEventListener(aName, aValue->GetStringValue(), true); } else { nsAutoString body; aValue->ToString(body); - AddScriptEventListener(aName, body, defer); + AddScriptEventListener(aName, body, true); } } // Hide chrome if needed if (mNodeInfo->Equals(nsGkAtoms::window) && aValue) { if (aName == nsGkAtoms::hidechrome) { HideWindowChrome( aValue->Equals(NS_LITERAL_STRING("true"), eCaseMatters)); @@ -2501,21 +2492,16 @@ nsXULElement::RecompileScriptEventListen } nsAutoString value; GetAttr(kNameSpaceID_None, attr, value); AddScriptEventListener(attr, value, true); } if (mPrototype) { - // If we have a prototype, the node we are binding to should - // have the same script-type - otherwise we will compile the - // event handlers incorrectly. - NS_ASSERTION(mPrototype->mScriptTypeID == nsIProgrammingLanguage::JAVASCRIPT, - "Prototype and node confused about default language?"); count = mPrototype->mNumAttributes; for (i = 0; i < count; ++i) { const nsAttrName &name = mPrototype->mAttributes[i].mName; // Eventlistenener-attributes are always in the null namespace if (!name.IsAtom()) { continue; @@ -2574,17 +2560,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(nsXULPrototypeNode) if (tmp->mType == nsXULPrototypeNode::eType_Element) { nsXULPrototypeElement *elem = static_cast<nsXULPrototypeElement*>(tmp); if (elem->mHoldsScriptObject) { PRUint32 i; for (i = 0; i < elem->mNumAttributes; ++i) { JSObject* handler = elem->mAttributes[i].mEventHandler; - NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(elem->mScriptTypeID, + NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(nsIProgrammingLanguage::JAVASCRIPT, handler, "mAttributes[i].mEventHandler") } } } else if (tmp->mType == nsXULPrototypeNode::eType_Script) { nsXULPrototypeScript *script = static_cast<nsXULPrototypeScript*>(tmp); @@ -2617,19 +2603,16 @@ nsXULPrototypeElement::Serialize(nsIObje nsIScriptGlobalObject* aGlobal, const nsCOMArray<nsINodeInfo> *aNodeInfos) { nsresult rv; // Write basic prototype data rv = aStream->Write32(mType); - // Write script language - rv |= aStream->Write32(mScriptTypeID); - // Write Node Info PRInt32 index = aNodeInfos->IndexOf(mNodeInfo); NS_ASSERTION(index >= 0, "unknown nsINodeInfo index"); rv |= aStream->Write32(index); // Write Attributes rv |= aStream->Write32(mNumAttributes); @@ -2700,21 +2683,16 @@ nsresult nsXULPrototypeElement::Deserialize(nsIObjectInputStream* aStream, nsIScriptGlobalObject* aGlobal, nsIURI* aDocumentURI, const nsCOMArray<nsINodeInfo> *aNodeInfos) { NS_PRECONDITION(aNodeInfos, "missing nodeinfo array"); nsresult rv; - // Read script language - PRUint32 scriptId = 0; - rv = aStream->Read32(&scriptId); - mScriptTypeID = scriptId; - // Read Node Info PRUint32 number; rv |= aStream->Read32(&number); mNodeInfo = aNodeInfos->SafeObjectAt(number); if (!mNodeInfo) return NS_ERROR_UNEXPECTED; // Read Attributes
--- a/content/xul/content/src/nsXULElement.h +++ b/content/xul/content/src/nsXULElement.h @@ -243,18 +243,17 @@ class nsXULPrototypeElement : public nsX public: nsXULPrototypeElement() : nsXULPrototypeNode(eType_Element), mNumAttributes(0), mAttributes(nsnull), mHasIdAttribute(false), mHasClassAttribute(false), mHasStyleAttribute(false), - mHoldsScriptObject(false), - mScriptTypeID(nsIProgrammingLanguage::UNKNOWN) + mHoldsScriptObject(false) { } virtual ~nsXULPrototypeElement() { Unlink(); } @@ -292,21 +291,16 @@ public: PRUint32 mNumAttributes; nsXULPrototypeAttribute* mAttributes; // [OWNER] bool mHasIdAttribute:1; bool mHasClassAttribute:1; bool mHasStyleAttribute:1; bool mHoldsScriptObject:1; - // The language ID can not be set on a per-node basis, but is tracked - // so that the language ID from the originating root can be used - // (eg, when a node from an overlay ends up in our document, that node - // must use its original script language, not our document's default. - PRUint16 mScriptTypeID; }; class nsXULDocument; class nsXULPrototypeScript : public nsXULPrototypeNode { public: nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, PRUint32 version);
--- a/content/xul/document/src/nsXULContentSink.cpp +++ b/content/xul/document/src/nsXULContentSink.cpp @@ -176,17 +176,17 @@ XULContentSinkImpl::ContextStack::GetTop nsresult rv = NS_OK; nsRefPtr<nsXULPrototypeNode> node; rv = GetTopNode(node); if (NS_FAILED(rv)) return rv; switch (node->mType) { case nsXULPrototypeNode::eType_Element: { nsXULPrototypeElement *parent = reinterpret_cast<nsXULPrototypeElement*>(node.get()); - *aScriptType = parent->mScriptTypeID; + *aScriptType = nsIProgrammingLanguage::JAVASCRIPT; break; } case nsXULPrototypeNode::eType_Script: { nsXULPrototypeScript *parent = reinterpret_cast<nsXULPrototypeScript*>(node.get()); *aScriptType = parent->mScriptObject.mLangID; break; } @@ -782,65 +782,16 @@ XULContentSinkImpl::ReportError(const PR rv = HandleEndElement(parsererror.get()); NS_ENSURE_SUCCESS(rv,rv); return rv; } nsresult -XULContentSinkImpl::SetElementScriptType(nsXULPrototypeElement* element, - const PRUnichar** aAttributes, - const PRUint32 aAttrLen) -{ - // First check if the attributes specify an explicit script type. - nsresult rv = NS_OK; - PRUint32 i; - bool found = false; - for (i=0;i<aAttrLen;i++) { - const nsDependentString key(aAttributes[i*2]); - if (key.EqualsLiteral("script-type")) { - const nsDependentString value(aAttributes[i*2+1]); - if (!value.IsEmpty()) { - nsCOMPtr<nsIScriptRuntime> runtime; - rv = NS_GetScriptRuntime(value, getter_AddRefs(runtime)); - if (NS_SUCCEEDED(rv)) - element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT; - else { - // probably just a bad language name (typo, etc) - NS_WARNING("Failed to load the node's script language!"); - // Leave the default language as unknown - we don't want js - // trying to execute this stuff. - NS_ASSERTION(element->mScriptTypeID == nsIProgrammingLanguage::UNKNOWN, - "Default script type should be unknown"); - } - found = true; - break; - } - } - } - // If not specified, look at the context stack and use the element - // there. - if (!found) { - if (mContextStack.Depth() == 0) { - // This is the root element - default to JS - element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT; - } else { - // Ask the top-node for its script type (which has already - // had this function called for it - so no need to recurse - // until we find it) - PRUint32 scriptId = 0; - rv = mContextStack.GetTopNodeScriptType(&scriptId); - element->mScriptTypeID = scriptId; - } - } - return rv; -} - -nsresult XULContentSinkImpl::OpenRoot(const PRUnichar** aAttributes, const PRUint32 aAttrLen, nsINodeInfo *aNodeInfo) { NS_ASSERTION(mState == eInProlog, "how'd we get here?"); if (mState != eInProlog) return NS_ERROR_UNEXPECTED; @@ -868,20 +819,16 @@ XULContentSinkImpl::OpenRoot(const PRUni NS_ConvertUTF16toUTF8(anodeC).get(), -1)); // XXX pass in line number } #endif return rv; } - // Set the correct script-type for the element. - rv = SetElementScriptType(element, aAttributes, aAttrLen); - if (NS_FAILED(rv)) return rv; - // Push the element onto the context stack, so that child // containers will hook up to us as their parent. rv = mContextStack.Push(element, mState); if (NS_FAILED(rv)) { element->Release(); return rv; } @@ -931,36 +878,29 @@ XULContentSinkImpl::OpenTag(const PRUnic // Add the attributes rv = AddAttributes(aAttributes, aAttrLen, element); if (NS_FAILED(rv)) return rv; children->AppendElement(element); if (aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XHTML) || aNodeInfo->Equals(nsGkAtoms::script, kNameSpaceID_XUL)) { - // Do scripty things now. Set a script language for the element, - // even though it is ignored (the nsPrototypeScriptElement - // has its own script-type). - element->mScriptTypeID = nsIProgrammingLanguage::JAVASCRIPT; + // Do scripty things now rv = OpenScript(aAttributes, aLineNumber); NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(mState == eInScript || mState == eInDocumentElement, "Unexpected state"); if (mState == eInScript) { // OpenScript has pushed the nsPrototypeScriptElement onto the // stack, so we're done. return NS_OK; } } - // Set the correct script-type for the element. - rv = SetElementScriptType(element, aAttributes, aAttrLen); - if (NS_FAILED(rv)) return rv; - // Push the element onto the context stack, so that child // containers will hook up to us as their parent. rv = mContextStack.Push(element, mState); if (NS_FAILED(rv)) return rv; mState = eInDocumentElement; return NS_OK; }
--- a/content/xul/document/src/nsXULContentSink.h +++ b/content/xul/document/src/nsXULContentSink.h @@ -112,20 +112,16 @@ protected: // eInDocumentElement then we didn't create a prototype script (e.g. the // script had an unknown type), and the caller should create a prototype // element. nsresult OpenScript(const PRUnichar** aAttributes, const PRUint32 aLineNumber); static bool IsDataInBuffer(PRUnichar* aBuffer, PRInt32 aLength); - nsresult SetElementScriptType(nsXULPrototypeElement* element, - const PRUnichar** aAttributes, - const PRUint32 aAttrLen); - // Text management nsresult FlushText(bool aCreateTextNode = true); nsresult AddText(const PRUnichar* aText, PRInt32 aLength); nsRefPtr<nsNodeInfoManager> mNodeInfoManager; nsresult NormalizeAttributeString(const PRUnichar *aExpatName,
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -115,17 +115,17 @@ protected: }; nsIPrincipal* nsXULPrototypeDocument::gSystemPrincipal; nsXULPDGlobalObject* nsXULPrototypeDocument::gSystemGlobal; PRUint32 nsXULPrototypeDocument::gRefCnt; void -nsXULPDGlobalObject_finalize(JSContext *cx, JSObject *obj) +nsXULPDGlobalObject_finalize(JSFreeOp *fop, JSObject *obj) { nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj); nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis)); if (sgo) { sgo->OnFinalize(obj); }
--- a/dom/base/BrowserElementAPI.js +++ b/dom/base/BrowserElementAPI.js @@ -127,24 +127,37 @@ BrowserElementAPI.prototype = { * <iframe mozbrowser>. */ _initBrowserWindow: function BA_initBrowserWindow(win, isTopLevel) { // XPCNativeWrapper.unwrap gets us the object that content sees; this is // the object object that we must define properties on. Otherwise, the // properties will be visible only to chrome! var unwrappedWin = XPCNativeWrapper.unwrap(win); - Object.defineProperty(unwrappedWin, 'top', { + // This property should exist only on the x-ray wrapped object, not on the + // unwrapped object, so we define it on |win|, not |unwrappedWin|. + Object.defineProperty(win, 'browserFrameTop', { get: function() { if (isTopLevel) { return win; } - // Call the mozbrowser-aware |top| method we presumably defined on our - // parent. - return XPCNativeWrapper.unwrap(win.parent).top; + + if ('browserFrameTop' in win.parent) { + return win.parent.browserFrameTop; + } + + // This shouldn't happen, but let's at least throw a semi-meaningful + // error message if it does. + throw new Error('Internal error in window.browserFrameTop.'); + } + }); + + Object.defineProperty(unwrappedWin, 'top', { + get: function() { + return win.browserFrameTop; } }); Object.defineProperty(unwrappedWin, 'parent', { get: function() { if (isTopLevel) { return win; }
--- a/dom/base/DOMRequest.cpp +++ b/dom/base/DOMRequest.cpp @@ -126,17 +126,17 @@ DOMRequest::FireEvent(const nsAString& a } nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull); nsresult rv = event->InitEvent(aType, false, false); if (NS_FAILED(rv)) { return; } - rv = event->SetTrusted(PR_TRUE); + rv = event->SetTrusted(true); if (NS_FAILED(rv)) { return; } bool dummy; DispatchEvent(event, &dummy); }
--- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1351,18 +1351,16 @@ static nsDOMClassInfoData sClassInfoData NS_DEFINE_CLASSINFO_DATA(Storage, nsStorage2SH, DOM_DEFAULT_SCRIPTABLE_FLAGS | nsIXPCScriptable::WANT_NEWRESOLVE | nsIXPCScriptable::WANT_GETPROPERTY | nsIXPCScriptable::WANT_SETPROPERTY | nsIXPCScriptable::WANT_DELPROPERTY | nsIXPCScriptable::DONT_ENUM_STATIC_PROPS | nsIXPCScriptable::WANT_NEWENUMERATE) - NS_DEFINE_CLASSINFO_DATA(StorageList, nsStorageListSH, - ARRAY_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(StorageItem, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(StorageEvent, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(StorageEventObsolete, nsDOMGenericSH, DOM_DEFAULT_SCRIPTABLE_FLAGS) NS_DEFINE_CLASSINFO_DATA(DOMParser, nsDOMGenericSH, @@ -3916,20 +3914,16 @@ nsDOMClassInfo::Init() DOM_CLASSINFO_MAP_BEGIN(StorageObsolete, nsIDOMStorageObsolete) DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageObsolete) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(Storage, nsIDOMStorage) DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorage) DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(StorageList, nsIDOMStorageList) - DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageList) - DOM_CLASSINFO_MAP_END - DOM_CLASSINFO_MAP_BEGIN(StorageItem, nsIDOMStorageItem) DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageItem) DOM_CLASSINFO_MAP_ENTRY(nsIDOMToString) DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_BEGIN(StorageEvent, nsIDOMStorageEvent) DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageEvent) DOM_CLASSINFO_EVENT_MAP_ENTRIES @@ -4794,17 +4788,17 @@ nsDOMClassInfo::Convert(nsIXPConnectWrap bool *_retval) { NS_WARNING("nsDOMClassInfo::Convert Don't call me!"); return NS_ERROR_UNEXPECTED; } NS_IMETHODIMP -nsDOMClassInfo::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx, +nsDOMClassInfo::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop, JSObject *obj) { NS_WARNING("nsDOMClassInfo::Finalize Don't call me!"); return NS_ERROR_UNEXPECTED; } NS_IMETHODIMP @@ -7398,17 +7392,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp *objp = obj; } } return NS_OK; } NS_IMETHODIMP -nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx, +nsWindowSH::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop, JSObject *obj) { nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper)); NS_ENSURE_TRUE(sgo, NS_ERROR_UNEXPECTED); sgo->OnFinalize(obj); return NS_OK; @@ -8935,17 +8929,17 @@ nsHTMLDocumentSH::DocumentAllNewResolve( return ok; } // Finalize hook used by document related JS objects, but also by // sGlobalScopePolluterClass! void -nsHTMLDocumentSH::ReleaseDocument(JSContext *cx, JSObject *obj) +nsHTMLDocumentSH::ReleaseDocument(JSFreeOp *fop, JSObject *obj) { nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(obj); NS_IF_RELEASE(doc); } JSBool nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp) @@ -10625,28 +10619,16 @@ nsStorage2SH::NewEnumerate(nsIXPConnectW "Bad call from the JS engine"); delete keys; *statep = JSVAL_NULL; return NS_OK; } -// StorageList scriptable helper - -nsISupports* -nsStorageListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName, - nsWrapperCache **aCache, nsresult *aResult) -{ - nsDOMStorageList* storagelist = static_cast<nsDOMStorageList*>(aNative); - - return storagelist->GetNamedItem(aName, aResult); -} - - // nsIDOMEventListener::HandleEvent() 'this' converter helper NS_INTERFACE_MAP_BEGIN(nsEventListenerThisTranslator) NS_INTERFACE_MAP_ENTRY(nsIXPCFunctionThisTranslator) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END @@ -10735,17 +10717,17 @@ nsDOMConstructorSH::NewResolve(nsIXPConn NS_ENSURE_SUCCESS(rv, rv); // Now re-lookup the ID to see if we should report back that we resolved the // looked-for constant. Note that we don't have to worry about infinitely // recurring back here because the Xray wrapper's holder object doesn't call // NewResolve hooks. JSBool found; if (!JS_HasPropertyById(cx, nativePropsObj, id, &found)) { - *_retval = PR_FALSE; + *_retval = false; return NS_OK; } if (found) { *objp = obj; } return NS_OK; }
--- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -411,17 +411,17 @@ public: #endif NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsid id, jsval *vp, bool *_retval); NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, bool *_retval); NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj, jsid id, PRUint32 flags, JSObject **objp, bool *_retval); - NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx, + NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop, JSObject *obj); NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, JSObject * *_retval); static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSObject **objp); static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSObject *obj, @@ -793,17 +793,17 @@ protected: nsDocument *doc, nsContentList **nodeList); public: static JSBool DocumentAllGetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp); static JSBool DocumentAllNewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSObject **objp); - static void ReleaseDocument(JSContext *cx, JSObject *obj); + static void ReleaseDocument(JSFreeOp *fop, JSObject *obj); static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp); static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp); static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSObject **objp); static JSBool DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, @@ -1422,46 +1422,16 @@ protected: public: static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) { return new nsStorage2SH(aData); } }; -class nsStorageListSH : public nsNamedArraySH -{ -protected: - nsStorageListSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData) - { - } - - virtual ~nsStorageListSH() - { - } - - virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex, - nsWrapperCache **aCache, nsresult *aResult) - { - return nsnull; - } - // Override nsNamedArraySH::GetNamedItem() - virtual nsISupports* GetNamedItem(nsISupports *aNative, - const nsAString& aName, - nsWrapperCache **cache, - nsresult *aResult); - -public: - static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) - { - return new nsStorageListSH(aData); - } -}; - - // Event handler 'this' translator class, this is called by XPConnect // when a "function interface" (nsIDOMEventListener) is called, this // class extracts 'this' fomr the first argument to the called // function (nsIDOMEventListener::HandleEvent(in nsIDOMEvent)), this // class will pass back nsIDOMEvent::currentTarget to be used as // 'this'. class nsEventListenerThisTranslator : public nsIXPCFunctionThisTranslator