Merge m-c into s-c
@ -41,6 +41,9 @@
|
||||
#include "nsAccessible.h"
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsBindingManager.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccIterator
|
||||
@ -129,17 +132,21 @@ RelatedAccIterator::Next()
|
||||
|
||||
// Return related accessible for the given attribute and if the provider
|
||||
// content is in the same binding in the case of XBL usage.
|
||||
if (provider->mRelAttr == mRelAttr &&
|
||||
(!mBindingParent ||
|
||||
mBindingParent == provider->mContent->GetBindingParent())) {
|
||||
nsAccessible* related = mDocument->GetAccessible(provider->mContent);
|
||||
if (related)
|
||||
return related;
|
||||
if (provider->mRelAttr == mRelAttr) {
|
||||
nsIContent* bindingParent = provider->mContent->GetBindingParent();
|
||||
bool inScope = mBindingParent == bindingParent ||
|
||||
mBindingParent == provider->mContent;
|
||||
|
||||
// If the document content is pointed by relation then return the document
|
||||
// itself.
|
||||
if (provider->mContent == mDocument->GetContent())
|
||||
return mDocument;
|
||||
if (inScope) {
|
||||
nsAccessible* related = mDocument->GetAccessible(provider->mContent);
|
||||
if (related)
|
||||
return related;
|
||||
|
||||
// If the document content is pointed by relation then return the document
|
||||
// itself.
|
||||
if (provider->mContent == mDocument->GetContent())
|
||||
return mDocument;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,18 +278,10 @@ XULDescriptionIterator::Next()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) :
|
||||
mCurrIdx(0)
|
||||
mCurrIdx(0), mContent(aContent)
|
||||
{
|
||||
if (!aContent->IsInDoc() ||
|
||||
!aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs))
|
||||
return;
|
||||
|
||||
if (aContent->IsInAnonymousSubtree()) {
|
||||
mXBLDocument = do_QueryInterface(aContent->OwnerDoc());
|
||||
mBindingParent = do_QueryInterface(aContent->GetBindingParent());
|
||||
} else {
|
||||
mDocument = aContent->OwnerDoc();
|
||||
}
|
||||
if (mContent->IsInDoc())
|
||||
mContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs);
|
||||
}
|
||||
|
||||
const nsDependentSubstring
|
||||
@ -324,20 +323,45 @@ IDRefsIterator::NextElem()
|
||||
nsIContent*
|
||||
IDRefsIterator::GetElem(const nsDependentSubstring& aID)
|
||||
{
|
||||
if (mXBLDocument) {
|
||||
// If content is anonymous subtree then use "anonid" attribute to get
|
||||
// elements, otherwise search elements in DOM by ID attribute.
|
||||
|
||||
nsCOMPtr<nsIDOMElement> refElm;
|
||||
mXBLDocument->GetAnonymousElementByAttribute(mBindingParent,
|
||||
NS_LITERAL_STRING("anonid"),
|
||||
aID,
|
||||
getter_AddRefs(refElm));
|
||||
nsCOMPtr<nsIContent> refContent = do_QueryInterface(refElm);
|
||||
return refContent;
|
||||
// Get elements in DOM tree by ID attribute if this is an explicit content.
|
||||
// In case of bound element check its anonymous subtree.
|
||||
if (!mContent->IsInAnonymousSubtree()) {
|
||||
dom::Element* refElm = mContent->OwnerDoc()->GetElementById(aID);
|
||||
if (refElm || !mContent->OwnerDoc()->BindingManager()->GetBinding(mContent))
|
||||
return refElm;
|
||||
}
|
||||
|
||||
return mDocument->GetElementById(aID);
|
||||
// If content is in anonymous subtree or an element having anonymous subtree
|
||||
// then use "anonid" attribute to get elements in anonymous subtree.
|
||||
nsCOMPtr<nsIDOMElement> refDOMElm;
|
||||
nsCOMPtr<nsIDOMDocumentXBL> xblDocument =
|
||||
do_QueryInterface(mContent->OwnerDoc());
|
||||
|
||||
// Check inside the binding the element is contained in.
|
||||
nsIContent* bindingParent = mContent->GetBindingParent();
|
||||
if (bindingParent) {
|
||||
nsCOMPtr<nsIDOMElement> bindingParentElm = do_QueryInterface(bindingParent);
|
||||
xblDocument->GetAnonymousElementByAttribute(bindingParentElm,
|
||||
NS_LITERAL_STRING("anonid"),
|
||||
aID,
|
||||
getter_AddRefs(refDOMElm));
|
||||
nsCOMPtr<dom::Element> refElm = do_QueryInterface(refDOMElm);
|
||||
if (refElm)
|
||||
return refElm;
|
||||
}
|
||||
|
||||
// Check inside the binding of the element.
|
||||
if (mContent->OwnerDoc()->BindingManager()->GetBinding(mContent)) {
|
||||
nsCOMPtr<nsIDOMElement> elm = do_QueryInterface(mContent);
|
||||
xblDocument->GetAnonymousElementByAttribute(elm,
|
||||
NS_LITERAL_STRING("anonid"),
|
||||
aID,
|
||||
getter_AddRefs(refDOMElm));
|
||||
nsCOMPtr<dom::Element> refElm = do_QueryInterface(refDOMElm);
|
||||
return refElm;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
|
@ -291,11 +291,8 @@ private:
|
||||
IDRefsIterator operator = (const IDRefsIterator&);
|
||||
|
||||
nsString mIDs;
|
||||
nsIContent* mContent;
|
||||
nsAString::index_type mCurrIdx;
|
||||
|
||||
nsIDocument* mDocument;
|
||||
nsCOMPtr<nsIDOMDocumentXBL> mXBLDocument;
|
||||
nsCOMPtr<nsIDOMElement> mBindingParent;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -117,8 +117,10 @@ NotificationController::Shutdown()
|
||||
|
||||
// Shutdown handling child documents.
|
||||
PRInt32 childDocCount = mHangingChildDocuments.Length();
|
||||
for (PRInt32 idx = childDocCount - 1; idx >= 0; idx--)
|
||||
mHangingChildDocuments[idx]->Shutdown();
|
||||
for (PRInt32 idx = childDocCount - 1; idx >= 0; idx--) {
|
||||
if (!mHangingChildDocuments[idx]->IsDefunct())
|
||||
mHangingChildDocuments[idx]->Shutdown();
|
||||
}
|
||||
|
||||
mHangingChildDocuments.Clear();
|
||||
|
||||
@ -259,6 +261,8 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
PRUint32 hangingDocCnt = mHangingChildDocuments.Length();
|
||||
for (PRUint32 idx = 0; idx < hangingDocCnt; idx++) {
|
||||
nsDocAccessible* childDoc = mHangingChildDocuments[idx];
|
||||
if (childDoc->IsDefunct())
|
||||
continue;
|
||||
|
||||
nsIContent* ownerContent = mDocument->GetDocumentNode()->
|
||||
FindContentForSubDocument(childDoc->GetDocumentNode());
|
||||
|
@ -98,7 +98,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
states::READONLY
|
||||
kNoReqStates,
|
||||
eReadonlyUntilEditable
|
||||
},
|
||||
{
|
||||
"button",
|
||||
@ -168,7 +169,8 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] =
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eNoLiveAttr,
|
||||
states::READONLY
|
||||
kNoReqStates,
|
||||
eReadonlyUntilEditable
|
||||
},
|
||||
{
|
||||
"grid",
|
||||
@ -661,7 +663,10 @@ nsStateMapEntry nsARIAMap::gWAIStateMap[] = {
|
||||
|
||||
// eARIASelectable
|
||||
nsStateMapEntry(&nsGkAtoms::aria_selected, kBoolType,
|
||||
states::SELECTABLE, states::SELECTED, 0, true)
|
||||
states::SELECTABLE, states::SELECTED, 0, true),
|
||||
|
||||
// eReadonlyUntilEditable
|
||||
nsStateMapEntry(states::READONLY, states::EDITABLE)
|
||||
};
|
||||
|
||||
/**
|
||||
@ -742,6 +747,23 @@ nsStateMapEntry::nsStateMapEntry() :
|
||||
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,
|
||||
@ -757,7 +779,8 @@ nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName, eStateValueType aType,
|
||||
mValue3(nsnull),
|
||||
mState3(0),
|
||||
mDefaultState(aTrueState),
|
||||
mDefinedIfAbsent(aDefinedIfAbsent)
|
||||
mDefinedIfAbsent(aDefinedIfAbsent),
|
||||
mExcludingState(0)
|
||||
{
|
||||
if (aType == kMixedType) {
|
||||
mValue2 = "mixed";
|
||||
@ -773,7 +796,7 @@ nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName,
|
||||
mValue1(aValue1), mState1(aState1),
|
||||
mValue2(aValue2), mState2(aState2),
|
||||
mValue3(aValue3), mState3(aState3),
|
||||
mDefaultState(0), mDefinedIfAbsent(false)
|
||||
mDefaultState(0), mDefinedIfAbsent(false), mExcludingState(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -786,7 +809,7 @@ nsStateMapEntry::nsStateMapEntry(nsIAtom** aAttrName,
|
||||
mValue1(aValue1), mState1(aState1),
|
||||
mValue2(aValue2), mState2(aState2),
|
||||
mValue3(aValue3), mState3(aState3),
|
||||
mDefaultState(0), mDefinedIfAbsent(true)
|
||||
mDefaultState(0), mDefinedIfAbsent(true), mExcludingState(0)
|
||||
{
|
||||
if (aDefaultStateRule == eUseFirstState)
|
||||
mDefaultState = aState1;
|
||||
@ -802,6 +825,15 @@ nsStateMapEntry::MapToStates(nsIContent* aContent, PRUint64* aState,
|
||||
|
||||
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.
|
||||
|
@ -187,7 +187,8 @@ enum eStateMapEntryID
|
||||
eARIAReadonly,
|
||||
eARIAReadonlyOrEditable,
|
||||
eARIARequired,
|
||||
eARIASelectable
|
||||
eARIASelectable,
|
||||
eReadonlyUntilEditable
|
||||
};
|
||||
|
||||
class nsStateMapEntry
|
||||
@ -198,6 +199,12 @@ public:
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -260,6 +267,9 @@ private:
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -322,20 +322,6 @@ nsAccUtils::GetSelectableContainer(nsAccessible* aAccessible, PRUint64 aState)
|
||||
return parent;
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccUtils::GetMultiSelectableContainer(nsINode* aNode)
|
||||
{
|
||||
nsAccessible* accessible = GetAccService()->GetAccessible(aNode, nsnull);
|
||||
if (accessible) {
|
||||
nsAccessible* container = GetSelectableContainer(accessible,
|
||||
accessible->State());
|
||||
if (container && container->State() & states::MULTISELECTABLE)
|
||||
return container;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsAccUtils::IsARIASelected(nsAccessible *aAccessible)
|
||||
{
|
||||
|
@ -196,11 +196,6 @@ public:
|
||||
static nsAccessible* GetSelectableContainer(nsAccessible* aAccessible,
|
||||
PRUint64 aState);
|
||||
|
||||
/**
|
||||
* Return multi selectable container for the given item.
|
||||
*/
|
||||
static nsAccessible *GetMultiSelectableContainer(nsINode *aNode);
|
||||
|
||||
/**
|
||||
* Return true if the DOM node of given accessible has aria-selected="true"
|
||||
* attribute.
|
||||
|
@ -298,23 +298,24 @@ already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLImageAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
{
|
||||
nsAutoString mapElmName;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, mapElmName);
|
||||
nsCOMPtr<nsIDOMHTMLMapElement> mapElm;
|
||||
if (nsIDocument* document = aContent->GetCurrentDoc()) {
|
||||
mapElm = do_QueryInterface(document->FindImageMap(mapElmName));
|
||||
}
|
||||
|
||||
nsAccessible* accessible = mapElm ?
|
||||
new nsHTMLImageMapAccessible(aContent,
|
||||
nsAccUtils::GetDocAccessibleFor(aPresShell),
|
||||
mapElm) :
|
||||
new nsHTMLImageAccessibleWrap(aContent,
|
||||
nsAccessible* accessible =
|
||||
new nsHTMLImageAccessibleWrap(aContent,
|
||||
nsAccUtils::GetDocAccessibleFor(aPresShell));
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLImageMapAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
{
|
||||
nsAccessible* accessible =
|
||||
new nsHTMLImageMapAccessible(aContent,
|
||||
nsAccUtils::GetDocAccessibleFor(aPresShell));
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLGroupboxAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell)
|
||||
@ -611,6 +612,28 @@ nsAccessibilityService::UpdateListBullet(nsIPresShell* aPresShell,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::UpdateImageMap(nsImageFrame* aImageFrame)
|
||||
{
|
||||
nsIPresShell* presShell = aImageFrame->PresContext()->PresShell();
|
||||
nsDocAccessible* document = GetDocAccessible(presShell->GetDocument());
|
||||
if (document) {
|
||||
nsAccessible* accessible =
|
||||
document->GetAccessible(aImageFrame->GetContent());
|
||||
if (accessible) {
|
||||
nsHTMLImageMapAccessible* imageMap = accessible->AsImageMap();
|
||||
if (imageMap) {
|
||||
imageMap->UpdateChildAreas();
|
||||
return;
|
||||
}
|
||||
|
||||
// If image map was initialized after we created an accessible (that'll
|
||||
// be an image accessible) then recreate it.
|
||||
RecreateAccessible(presShell, aImageFrame->GetContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
||||
{
|
||||
|
@ -48,6 +48,8 @@
|
||||
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsImageFrame;
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
@ -109,6 +111,8 @@ public:
|
||||
CreateHTMLHRAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLImageAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
already_AddRefed<nsAccessible>
|
||||
CreateHTMLImageMapAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
@ -155,6 +159,11 @@ public:
|
||||
nsIContent* aHTMLListItemContent,
|
||||
bool aHasBullet);
|
||||
|
||||
/**
|
||||
* Update the image map.
|
||||
*/
|
||||
void UpdateImageMap(nsImageFrame* aImageFrame);
|
||||
|
||||
virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
|
||||
|
||||
virtual void PresShellDestroyed(nsIPresShell* aPresShell);
|
||||
|
@ -1042,47 +1042,42 @@ nsIFrame* nsAccessible::GetBoundsFrame()
|
||||
return GetFrame();
|
||||
}
|
||||
|
||||
/* void removeSelection (); */
|
||||
NS_IMETHODIMP nsAccessible::SetSelected(bool aSelect)
|
||||
{
|
||||
// Add or remove selection
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (State() & states::SELECTABLE) {
|
||||
nsAccessible* multiSelect =
|
||||
nsAccUtils::GetMultiSelectableContainer(mContent);
|
||||
if (!multiSelect) {
|
||||
return aSelect ? TakeFocus() : NS_ERROR_FAILURE;
|
||||
nsAccessible* select = nsAccUtils::GetSelectableContainer(this, State());
|
||||
if (select) {
|
||||
if (select->State() & states::MULTISELECTABLE) {
|
||||
if (mRoleMapEntry) {
|
||||
if (aSelect) {
|
||||
return mContent->SetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected,
|
||||
NS_LITERAL_STRING("true"), true);
|
||||
}
|
||||
return mContent->UnsetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected, true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mRoleMapEntry) {
|
||||
if (aSelect) {
|
||||
return mContent->SetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected,
|
||||
NS_LITERAL_STRING("true"), true);
|
||||
}
|
||||
return mContent->UnsetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::aria_selected, true);
|
||||
}
|
||||
return aSelect ? TakeFocus() : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void takeSelection (); */
|
||||
NS_IMETHODIMP nsAccessible::TakeSelection()
|
||||
{
|
||||
// Select only this item
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (State() & states::SELECTABLE) {
|
||||
nsAccessible* multiSelect =
|
||||
nsAccUtils::GetMultiSelectableContainer(mContent);
|
||||
if (multiSelect)
|
||||
multiSelect->ClearSelection();
|
||||
|
||||
nsAccessible* select = nsAccUtils::GetSelectableContainer(this, State());
|
||||
if (select) {
|
||||
if (select->State() & states::MULTISELECTABLE)
|
||||
select->ClearSelection();
|
||||
return SetSelected(true);
|
||||
}
|
||||
|
||||
@ -1617,11 +1612,7 @@ nsAccessible::State()
|
||||
state |= states::HORIZONTAL;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are editable, force readonly bit off
|
||||
if (state & states::EDITABLE)
|
||||
state &= ~states::READONLY;
|
||||
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -1668,7 +1659,6 @@ nsAccessible::ApplyARIAState(PRUint64* aState)
|
||||
if (!mRoleMapEntry)
|
||||
return;
|
||||
|
||||
// Note: the readonly bitflag will be overridden later if content is editable
|
||||
*aState |= mRoleMapEntry->state;
|
||||
if (nsStateMapEntry::MapToStates(mContent, aState,
|
||||
mRoleMapEntry->attributeMap1) &&
|
||||
@ -1677,7 +1667,6 @@ nsAccessible::ApplyARIAState(PRUint64* aState)
|
||||
nsStateMapEntry::MapToStates(mContent, aState,
|
||||
mRoleMapEntry->attributeMap3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Not implemented by this class
|
||||
|
@ -62,6 +62,7 @@ class KeyBinding;
|
||||
class nsAccessible;
|
||||
class nsHyperTextAccessible;
|
||||
class nsHTMLImageAccessible;
|
||||
class nsHTMLImageMapAccessible;
|
||||
class nsHTMLLIAccessible;
|
||||
struct nsRoleMapEntry;
|
||||
class Relation;
|
||||
@ -454,10 +455,13 @@ public:
|
||||
|
||||
inline bool IsHTMLListItem() const { return mFlags & eHTMLListItemAccessible; }
|
||||
nsHTMLLIAccessible* AsHTMLListItem();
|
||||
|
||||
|
||||
inline bool IsImageAccessible() const { return mFlags & eImageAccessible; }
|
||||
nsHTMLImageAccessible* AsImage();
|
||||
|
||||
bool IsImageMapAccessible() const { return mFlags & eImageMapAccessible; }
|
||||
nsHTMLImageMapAccessible* AsImageMap();
|
||||
|
||||
inline bool IsListControl() const { return mFlags & eListControlAccessible; }
|
||||
|
||||
inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
|
||||
@ -689,11 +693,12 @@ protected:
|
||||
eHTMLFileInputAccessible = 1 << 8,
|
||||
eHTMLListItemAccessible = 1 << 9,
|
||||
eImageAccessible = 1 << 10,
|
||||
eListControlAccessible = 1 << 11,
|
||||
eMenuButtonAccessible = 1 << 12,
|
||||
eMenuPopupAccessible = 1 << 13,
|
||||
eRootAccessible = 1 << 14,
|
||||
eTextLeafAccessible = 1 << 15
|
||||
eImageMapAccessible = 1 << 11,
|
||||
eListControlAccessible = 1 << 12,
|
||||
eMenuButtonAccessible = 1 << 13,
|
||||
eMenuPopupAccessible = 1 << 14,
|
||||
eRootAccessible = 1 << 15,
|
||||
eTextLeafAccessible = 1 << 16
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -52,15 +52,16 @@
|
||||
#include "nsImageMap.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLImageMapAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLImageMapAccessible::
|
||||
nsHTMLImageMapAccessible(nsIContent* aContent, nsDocAccessible* aDoc,
|
||||
nsIDOMHTMLMapElement* aMapElm) :
|
||||
nsHTMLImageAccessibleWrap(aContent, aDoc), mMapElement(aMapElm)
|
||||
nsHTMLImageMapAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
|
||||
nsHTMLImageAccessibleWrap(aContent, aDoc)
|
||||
{
|
||||
mFlags |= eImageMapAccessible;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -104,39 +105,75 @@ nsHTMLImageMapAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLImageMapAccessible: nsAccessible protected
|
||||
// nsHTMLImageMapAccessible: public
|
||||
|
||||
void
|
||||
nsHTMLImageMapAccessible::CacheChildren()
|
||||
void
|
||||
nsHTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
||||
{
|
||||
if (!mMapElement)
|
||||
nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
|
||||
// If image map is not initialized yet then we trigger one time more later.
|
||||
nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
|
||||
if (!imageMapObj)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLCollection> mapAreas;
|
||||
mMapElement->GetAreas(getter_AddRefs(mapAreas));
|
||||
if (!mapAreas)
|
||||
return;
|
||||
bool doReorderEvent = false;
|
||||
|
||||
nsDocAccessible* document = Document();
|
||||
// Remove areas that are not a valid part of the image map anymore.
|
||||
for (PRInt32 childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
|
||||
nsAccessible* area = mChildren.ElementAt(childIdx);
|
||||
if (area->GetContent()->GetPrimaryFrame())
|
||||
continue;
|
||||
|
||||
PRUint32 areaCount = 0;
|
||||
mapAreas->GetLength(&areaCount);
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccEvent> event = new AccHideEvent(area, area->GetContent());
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
|
||||
for (PRUint32 areaIdx = 0; areaIdx < areaCount; areaIdx++) {
|
||||
nsCOMPtr<nsIDOMNode> areaNode;
|
||||
mapAreas->Item(areaIdx, getter_AddRefs(areaNode));
|
||||
if (!areaNode)
|
||||
return;
|
||||
RemoveChild(area);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> areaContent(do_QueryInterface(areaNode));
|
||||
nsRefPtr<nsAccessible> area =
|
||||
new nsHTMLAreaAccessible(areaContent, mDoc);
|
||||
// Insert new areas into the tree.
|
||||
PRUint32 areaElmCount = imageMapObj->AreaCount();
|
||||
for (PRUint32 idx = 0; idx < areaElmCount; idx++) {
|
||||
nsIContent* areaContent = imageMapObj->GetAreaAt(idx);
|
||||
|
||||
if (!document->BindToDocument(area, nsAccUtils::GetRoleMapEntry(areaContent)) ||
|
||||
!AppendChild(area)) {
|
||||
return;
|
||||
nsAccessible* area = mChildren.SafeElementAt(idx);
|
||||
if (!area || area->GetContent() != areaContent) {
|
||||
nsRefPtr<nsAccessible> area = new nsHTMLAreaAccessible(areaContent, mDoc);
|
||||
if (!mDoc->BindToDocument(area, nsAccUtils::GetRoleMapEntry(areaContent)))
|
||||
break;
|
||||
|
||||
if (!InsertChildAt(idx, area)) {
|
||||
mDoc->UnbindFromDocument(area);
|
||||
break;
|
||||
}
|
||||
|
||||
if (aDoFireEvents) {
|
||||
nsRefPtr<AccEvent> event = new AccShowEvent(area, areaContent);
|
||||
mDoc->FireDelayedAccessibleEvent(event);
|
||||
doReorderEvent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fire reorder event if needed.
|
||||
if (doReorderEvent) {
|
||||
nsRefPtr<AccEvent> reorderEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_REORDER, mContent,
|
||||
eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
|
||||
mDoc->FireDelayedAccessibleEvent(reorderEvent);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLImageMapAccessible: nsAccessible protected
|
||||
|
||||
void
|
||||
nsHTMLImageMapAccessible::CacheChildren()
|
||||
{
|
||||
UpdateChildAreas(false);
|
||||
}
|
||||
|
||||
|
||||
@ -226,6 +263,17 @@ nsHTMLAreaAccessible::GetBounds(PRInt32 *aX, PRInt32 *aY,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLAreaAccessible: nsAccessNode public
|
||||
|
||||
bool
|
||||
nsHTMLAreaAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
// Make HTML area DOM element not accessible. HTML image map accessible
|
||||
// manages its tree itself.
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLAreaAccessible: nsAccessible public
|
||||
|
||||
|
@ -51,8 +51,8 @@
|
||||
class nsHTMLImageMapAccessible : public nsHTMLImageAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsHTMLImageMapAccessible(nsIContent* aContent, nsDocAccessible* aDoc,
|
||||
nsIDOMHTMLMapElement* aMapElm);
|
||||
nsHTMLImageMapAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
|
||||
virtual ~nsHTMLImageMapAccessible() { }
|
||||
|
||||
// nsISupports and cycle collector
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -65,16 +65,27 @@ public:
|
||||
virtual nsAccessible* AnchorAt(PRUint32 aAnchorIndex);
|
||||
virtual already_AddRefed<nsIURI> AnchorURIAt(PRUint32 aAnchorIndex);
|
||||
|
||||
/**
|
||||
* Update area children of the image map.
|
||||
*/
|
||||
void UpdateChildAreas(bool aDoFireEvents = true);
|
||||
|
||||
protected:
|
||||
|
||||
// nsAccessible
|
||||
virtual void CacheChildren();
|
||||
|
||||
private:
|
||||
// Reference on linked map element if any.
|
||||
nsCOMPtr<nsIDOMHTMLMapElement> mMapElement;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible downcasting method
|
||||
|
||||
inline nsHTMLImageMapAccessible*
|
||||
nsAccessible::AsImageMap()
|
||||
{
|
||||
return IsImageMapAccessible() ?
|
||||
static_cast<nsHTMLImageMapAccessible*>(this) : nsnull;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Accessible for image map areas - must be child of image.
|
||||
@ -89,6 +100,9 @@ public:
|
||||
|
||||
NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
|
||||
|
||||
// nsAccessNode
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual void Description(nsString& aDescription);
|
||||
virtual nsresult GetNameInternal(nsAString& aName);
|
||||
|
@ -168,11 +168,8 @@ nsHyperTextAccessible::NativeState()
|
||||
|
||||
nsCOMPtr<nsIEditor> editor = GetEditor();
|
||||
if (editor) {
|
||||
PRUint32 flags;
|
||||
editor->GetFlags(&flags);
|
||||
if (0 == (flags & nsIPlaintextEditor::eEditorReadonlyMask)) {
|
||||
states |= states::EDITABLE;
|
||||
}
|
||||
states |= states::EDITABLE;
|
||||
|
||||
} else if (mContent->Tag() == nsGkAtoms::article) {
|
||||
// We want <article> to behave like a document in terms of readonly state.
|
||||
states |= states::READONLY;
|
||||
|
@ -54,13 +54,6 @@
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
enum {
|
||||
IA2AlphaShift = 24,
|
||||
IA2RedShift = 16,
|
||||
IA2GreenShift = 8,
|
||||
IA2BlueShift = 0
|
||||
};
|
||||
|
||||
// IUnknown
|
||||
|
||||
STDMETHODIMP
|
||||
@ -130,110 +123,40 @@ __try {
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleComponent::get_foreground(IA2Color *aForeground)
|
||||
CAccessibleComponent::get_foreground(IA2Color* aForeground)
|
||||
{
|
||||
__try {
|
||||
return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("color"), aForeground);
|
||||
nsRefPtr<nsAccessible> acc(do_QueryObject(this));
|
||||
if (acc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
nsIFrame* frame = acc->GetFrame();
|
||||
if (frame)
|
||||
*aForeground = frame->GetStyleColor()->mColor;
|
||||
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CAccessibleComponent::get_background(IA2Color *aBackground)
|
||||
CAccessibleComponent::get_background(IA2Color* aBackground)
|
||||
{
|
||||
__try {
|
||||
return GetARGBValueFromCSSProperty(NS_LITERAL_STRING("background-color"),
|
||||
aBackground);
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CAccessibleComponent::GetARGBValueFromCSSProperty(const nsAString& aPropName,
|
||||
IA2Color *aColorValue)
|
||||
{
|
||||
__try {
|
||||
*aColorValue = 0;
|
||||
|
||||
nsRefPtr<nsAccessible> acc(do_QueryObject(this));
|
||||
if (acc->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> styleDecl =
|
||||
nsWinUtils::GetComputedStyleDeclaration(acc->GetContent());
|
||||
NS_ENSURE_STATE(styleDecl);
|
||||
nsIFrame* frame = acc->GetFrame();
|
||||
if (frame)
|
||||
*aBackground = frame->GetStyleBackground()->mBackgroundColor;
|
||||
|
||||
nsCOMPtr<nsIDOMCSSValue> cssGenericValue;
|
||||
styleDecl->GetPropertyCSSValue(aPropName, getter_AddRefs(cssGenericValue));
|
||||
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> cssValue =
|
||||
do_QueryInterface(cssGenericValue);
|
||||
if (!cssValue)
|
||||
return E_FAIL;
|
||||
|
||||
nsCOMPtr<nsIDOMRGBColor> rgbColor;
|
||||
nsresult rv = cssValue->GetRGBColorValue(getter_AddRefs(rgbColor));
|
||||
if (NS_FAILED(rv) || !rgbColor)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
nsCOMPtr<nsIDOMNSRGBAColor> rgbaColor(do_QueryInterface(rgbColor));
|
||||
if (!rgbaColor)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// get alpha
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> alphaValue;
|
||||
rv = rgbaColor->GetAlpha(getter_AddRefs(alphaValue));
|
||||
if (NS_FAILED(rv) || !alphaValue)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
float alpha = 0.0;
|
||||
rv = alphaValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &alpha);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// get red
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> redValue;
|
||||
rv = rgbaColor->GetRed(getter_AddRefs(redValue));
|
||||
if (NS_FAILED(rv) || !redValue)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
float red = 0.0;
|
||||
rv = redValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &red);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// get green
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> greenValue;
|
||||
rv = rgbaColor->GetGreen(getter_AddRefs(greenValue));
|
||||
if (NS_FAILED(rv) || !greenValue)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
float green = 0.0;
|
||||
rv = greenValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &green);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// get blue
|
||||
nsCOMPtr<nsIDOMCSSPrimitiveValue> blueValue;
|
||||
rv = rgbaColor->GetBlue(getter_AddRefs(blueValue));
|
||||
if (NS_FAILED(rv) || !blueValue)
|
||||
return GetHRESULT(rv);
|
||||
|
||||
float blue = 0.0;
|
||||
rv = blueValue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &blue);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
// compose ARGB value
|
||||
*aColorValue = (((IA2Color) blue) << IA2BlueShift) |
|
||||
(((IA2Color) green) << IA2GreenShift) |
|
||||
(((IA2Color) red) << IA2RedShift) |
|
||||
(((IA2Color) (alpha * 0xff)) << IA2AlphaShift);
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
@ -65,14 +65,6 @@ public:
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD QueryInterface(const nsIID& uuid, void** result) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Return ARGB value for CSS property like 'color' or 'background-color'.
|
||||
*/
|
||||
HRESULT GetARGBValueFromCSSProperty(const nsAString& aPropName,
|
||||
IA2Color *aColorValue);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -486,6 +486,21 @@ function testDefunctAccessible(aAcc, aNodeOrId)
|
||||
ok(success, "parent" + msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that image map accessible tree is created.
|
||||
*/
|
||||
function ensureImageMapTree(aID)
|
||||
{
|
||||
// XXX: We send a useless mouse move to the image to force it to setup its
|
||||
// image map, because flushing layout won't do it. Hopefully bug 135040
|
||||
// will make this not suck.
|
||||
synthesizeMouse(getNode(aID), 10, 10, { type: "mousemove" });
|
||||
|
||||
// XXX This may affect a11y more than other code because imagemaps may not
|
||||
// get drawn or have an mouse event over them. Bug 570322 tracks a11y
|
||||
// dealing with this.
|
||||
todo(false, "Need to remove this image map workaround.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert role to human readable string.
|
||||
|
@ -9,6 +9,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
|
||||
|
||||
<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>
|
||||
@ -88,6 +90,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// image map and its link children
|
||||
ensureImageMapTree("imgmap");
|
||||
|
||||
var imageMapHyperlinkAcc = getAccessible("imgmap",
|
||||
[nsIAccessibleHyperLink]);
|
||||
testThis("imgmap", imageMapHyperlinkAcc, ROLE_IMAGE_MAP, 2, "b", true,
|
||||
@ -268,7 +272,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=418368
|
||||
><img width="447" id="imgmap"
|
||||
height="15"
|
||||
usemap="#atoz_map"
|
||||
src="letters.gif"><br>Empty link:<br
|
||||
src="../letters.gif"><br>Empty link:<br
|
||||
><a id="emptyLink" href=""><img src=""></a
|
||||
><br>Link with embedded span<br
|
||||
><a id="LinkWithSpan" href="http://www.heise.de/"><span lang="de">Heise Online</span></a
|
||||
|
@ -9,6 +9,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
|
||||
<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>
|
||||
@ -53,6 +55,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
testThis("InvalidAriaHyperlink", 63, 2, "Invalid link");
|
||||
|
||||
// image map, but not its link children. They are not part of hypertext.
|
||||
ensureImageMapTree("imgmap");
|
||||
testThis("imgmap", 76, 3, "b");
|
||||
|
||||
// empty hyperlink
|
||||
@ -131,7 +134,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
><img width="447" id="imgmap"
|
||||
height="15"
|
||||
usemap="#atoz_map"
|
||||
src="letters.gif"></img><br
|
||||
src="../letters.gif"></img><br
|
||||
>Empty link:<br
|
||||
><a id="emptyLink" href=""><img src=""></img></a><br
|
||||
>Link with embedded span<br
|
||||
|
@ -78,7 +78,7 @@ function testRelation(aIdentifier, aRelType, aRelatedIdentifiers)
|
||||
}
|
||||
}
|
||||
|
||||
ok(isFound, relatedIds[idx] + " is not a target of" + relDescr);
|
||||
ok(isFound, prettyName(relatedIds[idx]) + " is not a target of" + relDescr);
|
||||
}
|
||||
|
||||
// Check if all obtained targets are given related accessibles.
|
||||
|
@ -46,11 +46,13 @@ include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES =\
|
||||
test_bindings.xhtml \
|
||||
test_embeds.xul \
|
||||
test_general.html \
|
||||
test_general.xul \
|
||||
test_tabbrowser.xul \
|
||||
test_tree.xul \
|
||||
test_ui_modalprompt.html \
|
||||
test_update.html \
|
||||
$(NULL)
|
||||
|
||||
|
103
accessible/tests/mochitest/relations/test_bindings.xhtml
Normal file
@ -0,0 +1,103 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<title>Accessible relations for bindings</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<style>
|
||||
.button {
|
||||
-moz-binding: url('#custombutton');
|
||||
}
|
||||
|
||||
.button2 {
|
||||
-moz-binding: url('#custombutton2');
|
||||
}
|
||||
</style>
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl">
|
||||
<binding id="custombutton">
|
||||
<content aria-labelledby="button.label label">
|
||||
<label xmlns="http://www.w3.org/1999/xhtml" anonid="button.label">
|
||||
anon label
|
||||
</label>
|
||||
<button xmlns="http://www.w3.org/1999/xhtml" anonid="button.button"
|
||||
aria-labelledby="button.label label">
|
||||
a button
|
||||
</button>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||
anonid="button.button2" class="button2"
|
||||
aria-labelledby="button.label"></div>
|
||||
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||
anonid="button.button3" class="button2"></div>
|
||||
</content>
|
||||
</binding>
|
||||
<binding id="custombutton2">
|
||||
<content aria-labelledby="button2.label">
|
||||
<label xmlns="http://www.w3.org/1999/xhtml" anonid="button2.label">
|
||||
nested anon label
|
||||
</label>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
||||
|
||||
<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="../relations.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doTests()
|
||||
{
|
||||
var button = document.getElementById("button");
|
||||
var anonLabel = document.
|
||||
getAnonymousElementByAttribute(button, "anonid", "button.label");
|
||||
var anonButton = document.
|
||||
getAnonymousElementByAttribute(button, "anonid", "button.button");
|
||||
var anonButton2 = document.
|
||||
getAnonymousElementByAttribute(button, "anonid", "button.button2");
|
||||
var anonButton3 = document.
|
||||
getAnonymousElementByAttribute(button, "anonid", "button.button3");
|
||||
var anonAnonLabel = document.
|
||||
getAnonymousElementByAttribute(anonButton3, "anonid", "button2.label");
|
||||
|
||||
testRelation("label", RELATION_LABEL_FOR, button);
|
||||
testRelation(anonLabel, RELATION_LABEL_FOR, [button, anonButton, anonButton2]);
|
||||
testRelation(button, RELATION_LABELLED_BY, [anonLabel, "label"]);
|
||||
testRelation(anonButton, RELATION_LABELLED_BY, anonLabel);
|
||||
testRelation(anonButton2, RELATION_LABELLED_BY, anonLabel);
|
||||
testRelation(anonButton3, RELATION_LABELLED_BY, anonAnonLabel);
|
||||
testRelation(anonAnonLabel, RELATION_LABEL_FOR, anonButton3);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTests);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=421242"
|
||||
title="Allow relations in anonymous content for binding parent">
|
||||
Mozilla Bug 421242
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<div id="eventdump"></div>
|
||||
|
||||
<label id="label">explicit label</label>
|
||||
<div id="button" class="button"></div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,95 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Modal prompts</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="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../relations.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../browser.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function showAlert()
|
||||
{
|
||||
this.eventSeq = [
|
||||
{
|
||||
type: EVENT_SHOW,
|
||||
match: function(aEvent)
|
||||
{
|
||||
return aEvent.accessible.role == ROLE_DIALOG;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
this.invoke = function showAlert_invoke()
|
||||
{
|
||||
window.setTimeout(
|
||||
function()
|
||||
{
|
||||
currentTabDocument().defaultView.alert("hello");
|
||||
}, 0);
|
||||
}
|
||||
|
||||
this.check = function showAlert_finalCheck(aEvent)
|
||||
{
|
||||
var dialog = aEvent.accessible.DOMNode;
|
||||
var info = dialog.ui.infoBody;
|
||||
testRelation(info, RELATION_DESCRIPTION_FOR, dialog);
|
||||
testRelation(dialog, RELATION_DESCRIBED_BY, info);
|
||||
}
|
||||
|
||||
this.getID = function showAlert_getID()
|
||||
{
|
||||
return "show alert";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true; // debug
|
||||
|
||||
var gQueue = null;
|
||||
function doTests()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new showAlert());
|
||||
gQueue.onFinish = function()
|
||||
{
|
||||
synthesizeKey("VK_RETURN", {}, browserWindow());
|
||||
closeBrowserWindow();
|
||||
}
|
||||
gQueue.invoke(); // will call SimpleTest.finish()
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
openBrowserWindow(doTests);
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body id="body">
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=661293"
|
||||
title="The tabmodalprompt dialog's prompt label doesn't get the text properly associated for accessibility">
|
||||
Mozilla Bug 661293
|
||||
</a>
|
||||
<br>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -102,15 +102,6 @@ function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
|
||||
"Not focusable " + id + " must be not focused!");
|
||||
}
|
||||
|
||||
// readonly/editable
|
||||
if (state & STATE_READONLY)
|
||||
isState(extraState & EXT_STATE_EDITABLE, 0, true,
|
||||
"Read-only " + id + " cannot be editable!");
|
||||
|
||||
if (extraState & EXT_STATE_EDITABLE)
|
||||
isState(state & STATE_READONLY, 0, true,
|
||||
"Editable " + id + " cannot be readonly!");
|
||||
|
||||
// multiline/singleline
|
||||
if (extraState & EXT_STATE_MULTI_LINE)
|
||||
isState(extraState & EXT_STATE_SINGLE_LINE, 0, true,
|
||||
|
@ -50,13 +50,13 @@ _TEST_FILES =\
|
||||
test_aria_imgmap.html \
|
||||
test_aria_widgetitems.html \
|
||||
test_buttons.html \
|
||||
test_controls.xul \
|
||||
test_doc.html \
|
||||
test_docarticle.html \
|
||||
test_editablebody.html \
|
||||
test_expandable.xul \
|
||||
test_frames.html \
|
||||
test_inputs.html \
|
||||
test_inputs.xul \
|
||||
test_link.html \
|
||||
test_popup.xul \
|
||||
test_selects.html \
|
||||
|
@ -19,21 +19,22 @@
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
//XXX We send a useless mouse move to the image to force it to setup its
|
||||
// image map, because flushing layout won't do it. Hopefully bug 135040
|
||||
// will make this not suck.
|
||||
synthesizeMouse($("imagemap"), 10, 10, { type: "mousemove" });
|
||||
//XXX This may affect a11y more than other code because imagemaps may not
|
||||
// get drawn or have an mouse event over them. Bug 570322 tracks a11y
|
||||
// dealing with this.
|
||||
todo(false, "Need to remove this image map workaround.");
|
||||
ensureImageMapTree("imagemap");
|
||||
|
||||
testStates("t1", 0, EXT_STATE_EDITABLE, STATE_LINKED);
|
||||
testStates("t2", 0, EXT_STATE_EDITABLE, STATE_LINKED);
|
||||
testStates("rb1", (STATE_CHECKABLE | STATE_CHECKED), 0, STATE_LINKED);
|
||||
testStates("rb2", STATE_CHECKABLE, 0, STATE_CHECKED, STATE_LINKED);
|
||||
testStates("cb1", (STATE_CHECKABLE | STATE_CHECKED), 0, STATE_LINKED);
|
||||
testStates("cbox", (STATE_HASPOPUP | STATE_COLLAPSED),
|
||||
var imageMap = getAccessible("imagemap");
|
||||
|
||||
var t1 = imageMap.getChildAt(0);
|
||||
testStates(t1, 0, EXT_STATE_EDITABLE, STATE_LINKED);
|
||||
var t2 = imageMap.getChildAt(1);
|
||||
testStates(t2, 0, EXT_STATE_EDITABLE, STATE_LINKED);
|
||||
var rb1 = imageMap.getChildAt(2);
|
||||
testStates(rb1, (STATE_CHECKABLE | STATE_CHECKED), 0, STATE_LINKED);
|
||||
var rb2 = imageMap.getChildAt(3);
|
||||
testStates(rb2, STATE_CHECKABLE, 0, STATE_CHECKED, STATE_LINKED);
|
||||
var cb1 = imageMap.getChildAt(4);
|
||||
testStates(cb1, (STATE_CHECKABLE | STATE_CHECKED), 0, STATE_LINKED);
|
||||
var cbox = imageMap.getChildAt(5);
|
||||
testStates(cbox, (STATE_HASPOPUP | STATE_COLLAPSED),
|
||||
EXT_STATE_EXPANDABLE, STATE_LINKED);
|
||||
|
||||
SimpleTest.finish();
|
||||
|
@ -19,10 +19,6 @@
|
||||
|
||||
function doTest()
|
||||
{
|
||||
testStates("some-text", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("some-text2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("some-password", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("some-password2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("checkbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("checkbox2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("radio-group", 0, 0, STATE_UNAVAILABLE);
|
||||
@ -55,11 +51,6 @@
|
||||
|
||||
<vbox flex="1">
|
||||
|
||||
<textbox id="some-text"/>
|
||||
<textbox id="some-text2" disabled="true"/>
|
||||
<textbox id="some-password" type="password" maxlength="8"/>
|
||||
<textbox id="some-password2" type="password" maxlength="8" disabled="true"/>
|
||||
|
||||
<checkbox id="checkbox" checked="true" label="Steak"/>
|
||||
<checkbox id="checkbox2" checked="true" label="Salad" disabled="true"/>
|
||||
|
@ -20,7 +20,7 @@
|
||||
testStates(getRootAccessible(), 0, EXT_STATE_ACTIVE);
|
||||
|
||||
// Bug 509696, 607219.
|
||||
testStates(document, STATE_READONLY); // role=""
|
||||
testStates(document, STATE_READONLY, 0); // role=""
|
||||
|
||||
document.body.setAttribute("role","banner"); // no platform mapping
|
||||
testStates(document, STATE_READONLY);
|
||||
@ -32,20 +32,20 @@
|
||||
// Bugs 454997 and 467387
|
||||
testStates(document, STATE_READONLY);
|
||||
testStates("document", STATE_READONLY);
|
||||
testStates("editable_document", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_document", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
|
||||
document.designMode = "on";
|
||||
|
||||
testStates(document, 0, EXT_STATE_EDITABLE);
|
||||
testStates("p", 0, EXT_STATE_EDITABLE);
|
||||
testStates("document", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_document", 0, EXT_STATE_EDITABLE);
|
||||
testStates(document, 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
testStates("p", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
testStates("document", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
testStates("editable_document", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
|
||||
document.designMode = "off";
|
||||
|
||||
testStates(document, STATE_READONLY);
|
||||
testStates("document", STATE_READONLY);
|
||||
testStates("editable_document", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_document", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -20,25 +20,26 @@
|
||||
if (docAcc) {
|
||||
testStates(docAcc, STATE_READONLY);
|
||||
testStates("aria_article", STATE_READONLY);
|
||||
testStates("editable_aria_article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_aria_article", 0, EXT_STATE_EDITABLE,
|
||||
STATE_READONLY);
|
||||
testStates("article", STATE_READONLY);
|
||||
testStates("editable_article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_article", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
|
||||
document.designMode = "on";
|
||||
|
||||
testStates(docAcc, 0, EXT_STATE_EDITABLE);
|
||||
testStates("aria_article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_aria_article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_article", 0, EXT_STATE_EDITABLE);
|
||||
testStates(docAcc, 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
testStates("aria_article", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
testStates("editable_aria_article", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
testStates("article", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
testStates("editable_article", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
|
||||
document.designMode = "off";
|
||||
|
||||
testStates(docAcc, STATE_READONLY);
|
||||
testStates("aria_article", STATE_READONLY);
|
||||
testStates("editable_aria_article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_aria_article", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
testStates("article", STATE_READONLY);
|
||||
testStates("editable_article", 0, EXT_STATE_EDITABLE);
|
||||
testStates("editable_article", 0, EXT_STATE_EDITABLE, STATE_READONLY);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -22,22 +22,32 @@
|
||||
frameDocCheckbox = document.getElementById("frame_doc_checkbox").contentDocument;
|
||||
frameDocTextbox = document.getElementById("frame_doc_textbox").contentDocument;
|
||||
|
||||
testStates(frameDoc, STATE_READONLY, 0, 0, 0, "test1: frameDoc");
|
||||
testStates(frameDocArticle, STATE_READONLY, 0, 0, 0, "test1: frameDocArticle");
|
||||
testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test1: frameDocCheckbox");
|
||||
testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, 0, 0, "test1: frameDocTextbox");
|
||||
testStates(frameDoc, STATE_READONLY, 0, 0, 0,
|
||||
"test1: frameDoc");
|
||||
testStates(frameDocArticle, STATE_READONLY, 0, 0, 0,
|
||||
"test1: frameDocArticle");
|
||||
testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0,
|
||||
"test1: frameDocCheckbox");
|
||||
testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, STATE_READONLY, 0,
|
||||
"test1: frameDocTextbox");
|
||||
|
||||
frameDoc.designMode = "on";
|
||||
testStates(frameDoc, 0, EXT_STATE_EDITABLE, 0, 0, "test2: frameDoc");
|
||||
testStates(frameDocArticle, STATE_READONLY, 0, 0, 0, "test2: frameDocArticle");
|
||||
testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test2: frameDocCheckbox");
|
||||
testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, 0, 0, "test2: frameDocTextbox");
|
||||
testStates(frameDoc, 0, EXT_STATE_EDITABLE, STATE_READONLY, 0,
|
||||
"test2: frameDoc");
|
||||
testStates(frameDocArticle, STATE_READONLY, 0, 0, 0,
|
||||
"test2: frameDocArticle");
|
||||
testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0,
|
||||
"test2: frameDocCheckbox");
|
||||
testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, STATE_READONLY, 0,
|
||||
"test2: frameDocTextbox");
|
||||
|
||||
frameDocArticle.designMode = "on";
|
||||
testStates(frameDocArticle, 0, EXT_STATE_EDITABLE, 0, 0, "test3: frameDocArticle");
|
||||
testStates(frameDocArticle, 0, EXT_STATE_EDITABLE, STATE_READONLY, 0,
|
||||
"test3: frameDocArticle");
|
||||
|
||||
frameDocCheckbox.designMode = "on";
|
||||
testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test4: frameDocCheckbox");
|
||||
testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0,
|
||||
"test4: frameDocCheckbox");
|
||||
|
||||
// Replace iframe document body before the document accessible tree is
|
||||
// created. Check the states are updated for new body.
|
||||
|
@ -16,37 +16,66 @@
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
// 'required' state. Also piggyback 'unavailable' testing here.
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// 'editable' and 'multiline' states.
|
||||
testStates("input", 0, EXT_STATE_EDITABLE, 0, EXT_STATE_MULTI_LINE);
|
||||
testStates("textarea", 0, EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE);
|
||||
|
||||
testStates("input_readonly", 0, EXT_STATE_EDITABLE);
|
||||
testStates("input_disabled", 0, EXT_STATE_EDITABLE);
|
||||
testStates("textarea_readonly", 0, EXT_STATE_EDITABLE);
|
||||
testStates("textarea_disabled", 0, EXT_STATE_EDITABLE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// 'required', 'readonly' and 'unavailable' states.
|
||||
var maybe_required = ["input","search","radio","checkbox","textarea"];
|
||||
var never_required = ["submit","button","reset","image"];
|
||||
|
||||
var i;
|
||||
for (i in maybe_required) {
|
||||
testStates(maybe_required[i], STATE_REQUIRED, 0, STATE_UNAVAILABLE);
|
||||
testStates(maybe_required[i] + "2", 0, 0, STATE_REQUIRED);
|
||||
testStates(maybe_required[i] + "3", STATE_UNAVAILABLE);
|
||||
testStates(maybe_required[i],
|
||||
STATE_FOCUSABLE, 0,
|
||||
STATE_REQUIRED | STATE_READONLY | STATE_UNAVAILABLE);
|
||||
|
||||
testStates(maybe_required[i] + "_required",
|
||||
STATE_FOCUSABLE | STATE_REQUIRED, 0,
|
||||
STATE_UNAVAILABLE | STATE_READONLY);
|
||||
|
||||
var readonlyID = maybe_required[i] + "_readonly";
|
||||
if (document.getElementById(readonlyID)) {
|
||||
testStates(readonlyID,
|
||||
STATE_FOCUSABLE | STATE_READONLY, 0,
|
||||
STATE_UNAVAILABLE | STATE_REQUIRED);
|
||||
}
|
||||
|
||||
testStates(maybe_required[i] + "_disabled",
|
||||
STATE_UNAVAILABLE, 0,
|
||||
STATE_FOCUSABLE | STATE_READONLY | STATE_REQUIRED);
|
||||
}
|
||||
|
||||
for (i in never_required) {
|
||||
testStates(never_required[i], 0, 0, STATE_REQUIRED);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// inherited 'unavailable' state
|
||||
testStates("f", STATE_UNAVAILABLE);
|
||||
testStates("f_input", STATE_UNAVAILABLE);
|
||||
testStates("f_input_disabled", STATE_UNAVAILABLE);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// inherited from file control
|
||||
var fileTextField = getAccessible("file").firstChild;
|
||||
testStates(fileTextField, STATE_UNAVAILABLE | STATE_REQUIRED);
|
||||
var fileBrowseButton = getAccessible("file").lastChild;
|
||||
testStates(fileBrowseButton, STATE_UNAVAILABLE | STATE_REQUIRED);
|
||||
|
||||
/**
|
||||
* maxlength doesn't make the element invalid until bug 613016 and bug 613019
|
||||
* are fixed. Commenting out related lines and adding a todo to make sure
|
||||
* it will be uncommented as soon as possible.
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// 'invalid' state
|
||||
|
||||
// XXX: maxlength doesn't make the element invalid until bug 613016 and
|
||||
// bug 613019 are fixed. Commenting out related lines and adding a todo to
|
||||
// make sure it will be uncommented as soon as possible.
|
||||
var todoInput = document.createElement("input");
|
||||
todoInput.maxLength = '2';
|
||||
todoInput.value = 'foo';
|
||||
@ -71,6 +100,7 @@
|
||||
testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// autocomplete states
|
||||
testStates("autocomplete-default", 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
|
||||
testStates("autocomplete-off", 0, 0, 0, EXT_STATE_SUPPORTS_AUTOCOMPLETION);
|
||||
@ -121,6 +151,11 @@
|
||||
title="File input control should be propogate states to descendants">
|
||||
Mozilla Bug 699017
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=733382"
|
||||
title="Editable state bit should be present on readonly inputs">
|
||||
Mozilla Bug 733382
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
@ -128,21 +163,24 @@
|
||||
|
||||
|
||||
<form>
|
||||
<input id="input" type="input" required>
|
||||
<input id="input2" type="input">
|
||||
<input id="input3" type="input" disabled>
|
||||
<input id="search" type="search" required>
|
||||
<input id="search2" type="search">
|
||||
<input id="search3" type="search" disabled>
|
||||
<input id="radio" type="radio" required>
|
||||
<input id="radio2" type="radio">
|
||||
<input id="radio3" type="radio" disabled>
|
||||
<input id="checkbox" type="checkbox" required>
|
||||
<input id="checkbox2" type="checkbox">
|
||||
<input id="checkbox3" type="checkbox" disabled>
|
||||
<textarea id="textarea" required></textarea>
|
||||
<textarea id="textarea2"></textarea>
|
||||
<textarea id="textarea3" disabled></textarea>
|
||||
<input id="input" type="input">
|
||||
<input id="input_required" type="input" required>
|
||||
<input id="input_readonly" type="input" readonly>
|
||||
<input id="input_disabled" type="input" disabled>
|
||||
<input id="search" type="search">
|
||||
<input id="search_required" type="search" required>
|
||||
<input id="search_readonly" type="search" readonly>
|
||||
<input id="search_disabled" type="search" disabled>
|
||||
<input id="radio" type="radio">
|
||||
<input id="radio_required" type="radio" required>
|
||||
<input id="radio_disabled" type="radio" disabled>
|
||||
<input id="checkbox" type="checkbox">
|
||||
<input id="checkbox_required" type="checkbox" required>
|
||||
<input id="checkbox_disabled" type="checkbox" disabled>
|
||||
<textarea id="textarea"></textarea>
|
||||
<textarea id="textarea_required" required></textarea>
|
||||
<textarea id="textarea_readonly" readonly></textarea>
|
||||
<textarea id="textarea_disabled" disabled></textarea>
|
||||
</form>
|
||||
|
||||
<!-- bogus required usage -->
|
||||
|
@ -23,65 +23,83 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Ordinary textbox
|
||||
testStates("textbox",
|
||||
STATE_FOCUSABLE, EXT_STATE_EDITABLE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE, EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_FOCUSABLE,
|
||||
EXT_STATE_EDITABLE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE,
|
||||
EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
"ordinary textbox");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Password textbox
|
||||
testStates("password",
|
||||
STATE_FOCUSABLE | STATE_PROTECTED, EXT_STATE_EDITABLE,
|
||||
STATE_UNAVAILABLE, EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_FOCUSABLE | STATE_PROTECTED,
|
||||
EXT_STATE_EDITABLE,
|
||||
STATE_UNAVAILABLE,
|
||||
EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
"password textbox");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Textarea
|
||||
testStates("textarea",
|
||||
STATE_FOCUSABLE, EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE, EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_FOCUSABLE,
|
||||
EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE,
|
||||
EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
"multiline textbox");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Readonly textbox
|
||||
testStates("readonly_textbox",
|
||||
STATE_FOCUSABLE | STATE_READONLY, 0,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE, EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_FOCUSABLE | STATE_READONLY,
|
||||
EXT_STATE_EDITABLE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE,
|
||||
EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
"readonly textbox");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Disabled textbox
|
||||
testStates("disabled_textbox",
|
||||
STATE_UNAVAILABLE, 0,
|
||||
STATE_FOCUSABLE | STATE_PROTECTED, EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_UNAVAILABLE,
|
||||
EXT_STATE_EDITABLE,
|
||||
STATE_FOCUSABLE | STATE_PROTECTED,
|
||||
EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
"readonly textbox");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Readonly textarea
|
||||
testStates("readonly_textarea",
|
||||
STATE_FOCUSABLE | STATE_READONLY, EXT_STATE_MULTI_LINE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE, EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_FOCUSABLE | STATE_READONLY,
|
||||
EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE,
|
||||
EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
"readonly multiline textbox");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Disabled textarea
|
||||
testStates("disabled_textarea",
|
||||
STATE_UNAVAILABLE, EXT_STATE_MULTI_LINE,
|
||||
STATE_PROTECTED | STATE_FOCUSABLE, EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_UNAVAILABLE,
|
||||
EXT_STATE_EDITABLE| EXT_STATE_MULTI_LINE,
|
||||
STATE_PROTECTED | STATE_FOCUSABLE,
|
||||
EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
"readonly multiline textbox");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Search textbox without search button, searches as you type and filters
|
||||
// a separate control.
|
||||
testStates("searchbox",
|
||||
STATE_FOCUSABLE, EXT_STATE_EDITABLE | EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE, 0,
|
||||
STATE_FOCUSABLE,
|
||||
EXT_STATE_EDITABLE | EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE,
|
||||
0,
|
||||
"searchbox");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Search textbox with search button, does not support autoCompletion.
|
||||
testStates("searchfield",
|
||||
STATE_FOCUSABLE, EXT_STATE_EDITABLE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE, EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
STATE_FOCUSABLE,
|
||||
EXT_STATE_EDITABLE,
|
||||
STATE_PROTECTED | STATE_UNAVAILABLE,
|
||||
EXT_STATE_SUPPORTS_AUTOCOMPLETION,
|
||||
"searchfield");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
@ -27,9 +27,8 @@ function testAction(aID, aAcc, aNumActions, aActionName, aActionDescription)
|
||||
}
|
||||
}
|
||||
|
||||
function testThis(aID, aName, aValue, aDescription, aRole, aState,
|
||||
aExtraState, aAbsentState, aNumActions, aActionName,
|
||||
aActionDescription)
|
||||
function testThis(aID, aName, aValue, aDescription, aRole,
|
||||
aNumActions, aActionName, aActionDescription)
|
||||
{
|
||||
var acc = getAccessible(aID);
|
||||
if (!acc)
|
||||
@ -40,7 +39,5 @@ function testThis(aID, aName, aValue, aDescription, aRole, aState,
|
||||
is(acc.description, aDescription, "Wrong description for " + aID + "!");
|
||||
testRole(aID, aRole);
|
||||
|
||||
testStates(acc, aState, aExtraState, aAbsentState);
|
||||
|
||||
testAction(aID, acc, aNumActions, aActionName, aActionDescription);
|
||||
}
|
||||
|
@ -30,9 +30,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -44,9 +41,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -58,9 +52,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
"I have some text", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -72,9 +63,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_PASSWORD_TEXT, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -86,9 +74,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -100,9 +85,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -114,9 +96,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
" I also have some text.\n ", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -128,9 +107,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
"You cannot change me.", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE | STATE_READONLY), // state
|
||||
(0), // extState
|
||||
(0), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -142,9 +118,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=442648
|
||||
" You cannot change me, either.\n ", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE | STATE_READONLY), // state
|
||||
(EXT_STATE_MULTI_LINE), // extState
|
||||
(0), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
|
@ -30,9 +30,6 @@
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -44,9 +41,6 @@
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -58,9 +52,6 @@
|
||||
"I have some text", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -72,9 +63,6 @@
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_PASSWORD_TEXT, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -86,9 +74,6 @@
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -100,9 +85,6 @@
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -114,9 +96,6 @@
|
||||
"I also have some text.", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_EDITABLE | EXT_STATE_MULTI_LINE), // extState
|
||||
(STATE_READONLY), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -128,9 +107,6 @@
|
||||
"You cannot change me.", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE | STATE_READONLY), // state
|
||||
(0), // extState
|
||||
(0), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -142,9 +118,6 @@
|
||||
"You cannot change me, either.", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE | STATE_READONLY), // state
|
||||
(EXT_STATE_MULTI_LINE), // extState
|
||||
(0), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -157,9 +130,6 @@
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(EXT_STATE_SUPPORTS_AUTOCOMPLETION), // extState
|
||||
(0), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
@ -171,9 +141,6 @@
|
||||
"", // value
|
||||
"", // description
|
||||
ROLE_ENTRY, // role
|
||||
(STATE_FOCUSABLE), // state
|
||||
(0), // extState
|
||||
(0), // absentState
|
||||
1, // numActions
|
||||
"activate", // ActionName
|
||||
"Activate"); // ActionDescription
|
||||
|
@ -19,14 +19,7 @@
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
//XXX We send a useless mouse move to the image to force it to setup its
|
||||
// image map, because flushing layout won't do it. Hopefully bug 135040
|
||||
// will make this not suck.
|
||||
synthesizeMouse($("imagemap"), 10, 10, { type: "mousemove" });
|
||||
//XXX This may affect a11y more than other code because imagemaps may not
|
||||
// get drawn or have an mouse event over them. Bug 570322 tracks a11y
|
||||
// dealing with this.
|
||||
todo(false, "Need to remove this image map workaround.");
|
||||
ensureImageMapTree("imagemap");
|
||||
|
||||
var accTree = {
|
||||
role: ROLE_IMAGE_MAP,
|
||||
|
@ -54,6 +54,7 @@ _TEST_FILES =\
|
||||
test_doc.html \
|
||||
test_gencontent.html \
|
||||
test_hidden.html \
|
||||
test_imagemap.html \
|
||||
test_list_editabledoc.html \
|
||||
test_list.html \
|
||||
test_menu.xul \
|
||||
|
394
accessible/tests/mochitest/treeupdate/test_imagemap.html
Normal file
@ -0,0 +1,394 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML img map accessible tree update tests</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="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="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function insertArea(aImageMapID, aMapID)
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getInsertedArea(aThisObj)
|
||||
{
|
||||
return aThisObj.imageMap.firstChild;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getInsertedArea, this),
|
||||
new invokerChecker(EVENT_REORDER, this.imageMap)
|
||||
];
|
||||
|
||||
this.invoke = function insertArea_invoke()
|
||||
{
|
||||
var areaElm = document.createElement("area");
|
||||
areaElm.setAttribute("href",
|
||||
"http://www.bbc.co.uk/radio4/atoz/index.shtml#a");
|
||||
areaElm.setAttribute("coords", "0,0,13,14");
|
||||
areaElm.setAttribute("alt", "a");
|
||||
areaElm.setAttribute("shape", "rect");
|
||||
|
||||
this.mapNode.insertBefore(areaElm, this.mapNode.firstChild);
|
||||
}
|
||||
|
||||
this.finalCheck = function insertArea_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ IMAGE_MAP: [
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "a",
|
||||
children: [ ]
|
||||
},
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "b",
|
||||
children: [ ]
|
||||
},
|
||||
] };
|
||||
testAccessibleTree(this.imageMap, accTree);
|
||||
}
|
||||
|
||||
this.getID = function insertArea_getID()
|
||||
{
|
||||
return "insert area element";
|
||||
}
|
||||
}
|
||||
|
||||
function appendArea(aImageMapID, aMapID)
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getAppendedArea(aThisObj)
|
||||
{
|
||||
return aThisObj.imageMap.lastChild;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getAppendedArea, this),
|
||||
new invokerChecker(EVENT_REORDER, this.imageMap)
|
||||
];
|
||||
|
||||
this.invoke = function appendArea_invoke()
|
||||
{
|
||||
var areaElm = document.createElement("area");
|
||||
areaElm.setAttribute("href",
|
||||
"http://www.bbc.co.uk/radio4/atoz/index.shtml#c");
|
||||
areaElm.setAttribute("coords", "34,0,47,14");
|
||||
areaElm.setAttribute("alt", "c");
|
||||
areaElm.setAttribute("shape", "rect");
|
||||
|
||||
this.mapNode.appendChild(areaElm);
|
||||
}
|
||||
|
||||
this.finalCheck = function appendArea_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ IMAGE_MAP: [
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "a",
|
||||
children: [ ]
|
||||
},
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "b",
|
||||
children: [ ]
|
||||
},
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "c",
|
||||
children: [ ]
|
||||
}
|
||||
] };
|
||||
testAccessibleTree(this.imageMap, accTree);
|
||||
}
|
||||
|
||||
this.getID = function appendArea_getID()
|
||||
{
|
||||
return "append area element";
|
||||
}
|
||||
}
|
||||
|
||||
function removeArea(aImageMapID, aMapID)
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.area = null;
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getRemovedArea(aThisObj)
|
||||
{
|
||||
return aThisObj.area;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getRemovedArea, this),
|
||||
new invokerChecker(EVENT_REORDER, this.imageMap)
|
||||
];
|
||||
|
||||
this.invoke = function removeArea_invoke()
|
||||
{
|
||||
this.area = this.imageMap.firstChild;
|
||||
this.mapNode.removeChild(this.mapNode.firstElementChild);
|
||||
}
|
||||
|
||||
this.finalCheck = function removeArea_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ IMAGE_MAP: [
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "b",
|
||||
children: [ ]
|
||||
},
|
||||
{
|
||||
role: ROLE_LINK,
|
||||
name: "c",
|
||||
children: [ ]
|
||||
}
|
||||
] };
|
||||
testAccessibleTree(this.imageMap, accTree);
|
||||
}
|
||||
|
||||
this.getID = function removeArea_getID()
|
||||
{
|
||||
return "remove area element";
|
||||
}
|
||||
}
|
||||
|
||||
function removeNameOnMap(aImageMapContainerID, aImageMapID, aMapID)
|
||||
{
|
||||
this.container = getAccessible(aImageMapContainerID);
|
||||
this.containerNode = this.container.DOMNode;
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.imgNode = this.imageMap.DOMNode;
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.imageMap),
|
||||
new invokerChecker(EVENT_SHOW, this.imgNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function removeNameOnMap_invoke()
|
||||
{
|
||||
this.mapNode.removeAttribute("name");
|
||||
}
|
||||
|
||||
this.finalCheck = function removeNameOnMap_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ SECTION: [
|
||||
{ GRAPHIC: [ ] }
|
||||
] };
|
||||
testAccessibleTree(this.container, accTree);
|
||||
}
|
||||
|
||||
this.getID = function removeNameOnMap_getID()
|
||||
{
|
||||
return "remove @name on map element";
|
||||
}
|
||||
}
|
||||
|
||||
function restoreNameOnMap(aImageMapContainerID, aImageMapID, aMapID)
|
||||
{
|
||||
this.container = getAccessible(aImageMapContainerID);
|
||||
this.containerNode = this.container.DOMNode;
|
||||
this.imageMap = null;
|
||||
this.imgNode = getNode(aImageMapID);
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getImageMap(aThisObj)
|
||||
{
|
||||
return aThisObj.imageMap;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getImageMap, this),
|
||||
new invokerChecker(EVENT_SHOW, this.imgNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function restoreNameOnMap_invoke()
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.mapNode.setAttribute("name", "atoz_map");
|
||||
}
|
||||
|
||||
this.finalCheck = function removeNameOnMap_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ SECTION: [
|
||||
{ IMAGE_MAP: [
|
||||
{ LINK: [ ] },
|
||||
{ LINK: [ ] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(this.container, accTree);
|
||||
}
|
||||
|
||||
this.getID = function removeNameOnMap_getID()
|
||||
{
|
||||
return "restore @name on map element";
|
||||
}
|
||||
}
|
||||
|
||||
function removeMap(aImageMapContainerID, aImageMapID, aMapID)
|
||||
{
|
||||
this.container = getAccessible(aImageMapContainerID);
|
||||
this.containerNode = this.container.DOMNode;
|
||||
this.imageMap = null;
|
||||
this.imgNode = getNode(aImageMapID);
|
||||
this.mapNode = getNode(aMapID);
|
||||
|
||||
function getImageMap(aThisObj)
|
||||
{
|
||||
return aThisObj.imageMap;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getImageMap, this),
|
||||
new invokerChecker(EVENT_SHOW, this.imgNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function removeMap_invoke()
|
||||
{
|
||||
this.imageMap = getAccessible(aImageMapID);
|
||||
this.mapNode.parentNode.removeChild(this.mapNode);
|
||||
}
|
||||
|
||||
this.finalCheck = function removeMap_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ SECTION: [
|
||||
{ GRAPHIC: [ ] }
|
||||
] };
|
||||
testAccessibleTree(this.container, accTree);
|
||||
}
|
||||
|
||||
this.getID = function removeMap_getID()
|
||||
{
|
||||
return "remove map element";
|
||||
}
|
||||
}
|
||||
|
||||
function insertMap(aImageMapContainerID, aImageID)
|
||||
{
|
||||
this.container = getAccessible(aImageMapContainerID);
|
||||
this.containerNode = this.container.DOMNode;
|
||||
this.image = null;
|
||||
this.imgMapNode = getNode(aImageID);
|
||||
|
||||
function getImage(aThisObj)
|
||||
{
|
||||
return aThisObj.image;
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getImage, this),
|
||||
new invokerChecker(EVENT_SHOW, this.imgMapNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function insertMap_invoke()
|
||||
{
|
||||
this.image = getAccessible(aImageID);
|
||||
|
||||
var map = document.createElement("map");
|
||||
map.setAttribute("name", "atoz_map");
|
||||
map.setAttribute("id", "map");
|
||||
|
||||
var area = document.createElement("area")
|
||||
area.setAttribute("href",
|
||||
"http://www.bbc.co.uk/radio4/atoz/index.shtml#b");
|
||||
area.setAttribute("coords", "17,0,30,14");
|
||||
area.setAttribute("alt", "b");
|
||||
area.setAttribute("shape", "rect");
|
||||
|
||||
map.appendChild(area);
|
||||
|
||||
this.containerNode.appendChild(map);
|
||||
|
||||
ensureImageMapTree(aImageID);
|
||||
}
|
||||
|
||||
this.finalCheck = function insertMap_finalCheck()
|
||||
{
|
||||
var accTree =
|
||||
{ SECTION: [
|
||||
{ IMAGE_MAP: [
|
||||
{ LINK: [ ] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(this.container, accTree);
|
||||
}
|
||||
|
||||
this.getID = function insertMap_getID()
|
||||
{
|
||||
return "insert map element";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new insertArea("imgmap", "map"));
|
||||
gQueue.push(new appendArea("imgmap", "map"));
|
||||
gQueue.push(new removeArea("imgmap", "map"));
|
||||
gQueue.push(new removeNameOnMap("container", "imgmap", "map"));
|
||||
gQueue.push(new restoreNameOnMap("container", "imgmap", "map"));
|
||||
gQueue.push(new removeMap("container", "imgmap", "map"));
|
||||
gQueue.push(new insertMap("container", "imgmap"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Image map accessible tree is not updated when image map is changed"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=732389">
|
||||
Mozilla Bug 732389
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<map name="atoz_map" id="map">
|
||||
<area href="http://www.bbc.co.uk/radio4/atoz/index.shtml#b"
|
||||
coords="17,0,30,14" alt="b" shape="rect">
|
||||
</map>
|
||||
|
||||
<div id="container">
|
||||
<img id="imgmap" width="447" height="15"
|
||||
usemap="#atoz_map"
|
||||
src="../letters.gif">
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -147,7 +147,7 @@ pref("dom.disable_open_during_load", true);
|
||||
pref("privacy.popups.showBrowserMessage", true);
|
||||
|
||||
pref("keyword.enabled", true);
|
||||
pref("keyword.URL", "http://www.google.com/m?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=");
|
||||
pref("keyword.URL", "https://www.google.com/m?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=");
|
||||
|
||||
pref("accessibility.typeaheadfind", false);
|
||||
pref("accessibility.typeaheadfind.timeout", 5000);
|
||||
|
@ -65,7 +65,8 @@ function startupHttpd(baseDir, port) {
|
||||
// XXX never grant 'content-camera' to non-gaia apps
|
||||
function addPermissions(urls) {
|
||||
let permissions = [
|
||||
'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'content-camera', 'webcontacts-manage'
|
||||
'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app',
|
||||
'content-camera', 'webcontacts-manage', 'wifi-manage'
|
||||
];
|
||||
urls.forEach(function(url) {
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
|
21
b2g/config/mozconfigs/linux32/debug
Normal file
@ -0,0 +1,21 @@
|
||||
#GONK_TOOLCHAIN_VERSION=0
|
||||
#export GONK_PRODUCT=generic
|
||||
#gonk="/home/cjones/mozilla/gonk-toolchain-$GONK_TOOLCHAIN_VERSION"
|
||||
|
||||
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-b2g
|
||||
|
||||
mk_add_options MOZ_MAKE_FLAGS="-j8"
|
||||
|
||||
ac_add_options --enable-application=b2g
|
||||
|
||||
ac_add_options --target=arm-android-eabi
|
||||
ac_add_options --with-gonk="$gonk"
|
||||
ac_add_options --with-endian=little
|
||||
ac_add_options --disable-elf-hack
|
||||
ac_add_options --enable-debug-symbols
|
||||
ac_add_options --enable-profiling
|
||||
ac_add_options --with-ccache
|
||||
ac_add_options --enable-marionette
|
||||
|
||||
# Enable dump() from JS.
|
||||
export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
|
14
b2g/config/tooltool-manifests/releng.manifest
Normal file
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"size": 195,
|
||||
"digest": "85369693c2362131515014cd4547cd0824225b03e1e52a352a84012e6e8586fa46ad619181167d220c463761865719a1747a83aeee76a5fcc5ab7859c14ef24a",
|
||||
"algorithm": "sha512",
|
||||
"filename": "setup.sh"
|
||||
},
|
||||
{
|
||||
"size": 121344236,
|
||||
"digest": "0bf5cceced8add6142c1c7522890c39554b94848e3f5eb9b92de2a8c6f6af3c0e8ab69ddf7bae39eaab2bcb637233ff02de07b47a1850767d2810a46fb31bf65",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gonk-toolchain-0.tar.bz2"
|
||||
}
|
||||
]
|
@ -38,7 +38,7 @@
|
||||
MOZ_APP_BASENAME=B2G
|
||||
MOZ_APP_VENDOR=Mozilla
|
||||
|
||||
MOZ_APP_VERSION=13.0a1
|
||||
MOZ_APP_VERSION=14.0a1
|
||||
MOZ_APP_UA_NAME=Firefox
|
||||
|
||||
MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
|
||||
|
@ -148,7 +148,7 @@
|
||||
#ifdef MOZ_B2G_RIL
|
||||
@BINPATH@/components/dom_telephony.xpt
|
||||
@BINPATH@/components/dom_wifi.xpt
|
||||
@BINPATH@/components/dom_system_b2g.xpt
|
||||
@BINPATH@/components/dom_system_gonk.xpt
|
||||
#endif
|
||||
@BINPATH@/components/dom_battery.xpt
|
||||
#ifdef MOZ_B2G_BT
|
||||
@ -409,6 +409,8 @@
|
||||
@BINPATH@/components/SmsDatabaseService.js
|
||||
@BINPATH@/components/nsWifiWorker.js
|
||||
@BINPATH@/components/nsWifiWorker.manifest
|
||||
@BINPATH@/components/nsDOMWifiManager.js
|
||||
@BINPATH@/components/nsDOMWifiManager.manifest
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/components/libalerts.dylib
|
||||
|
@ -39,8 +39,13 @@
|
||||
|
||||
#filter substitution
|
||||
|
||||
# SYNTAX HINTS: dashes are delimiters. Use underscores instead.
|
||||
# The first character after a period must be alphabetic.
|
||||
#
|
||||
# SYNTAX HINTS:
|
||||
#
|
||||
# - Dashes are delimiters; use underscores instead.
|
||||
# - The first character after a period must be alphabetic.
|
||||
# - Computed values (e.g. 50 * 1024) don't work.
|
||||
#
|
||||
|
||||
#ifdef XP_UNIX
|
||||
#ifndef XP_MACOSX
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 4.4 KiB |
@ -1,384 +0,0 @@
|
||||
%if 0
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is aboutHome.xhtml.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (original author)
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Stephen Horlander <shorlander@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* 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 ***** */
|
||||
%endif
|
||||
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
background: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#brandStart {
|
||||
text-align: center;
|
||||
height: 19%;
|
||||
max-height: 256px;
|
||||
min-height: 92px;
|
||||
}
|
||||
|
||||
#brandStartSpacer {
|
||||
height: 6.5%;
|
||||
}
|
||||
|
||||
#brandStartLogo {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#searchContainer {
|
||||
height: 15%;
|
||||
min-height: 90px;
|
||||
}
|
||||
|
||||
#searchContainer::before {
|
||||
content: " ";
|
||||
display: block;
|
||||
height: 23%;
|
||||
}
|
||||
|
||||
#searchForm {
|
||||
display: table;
|
||||
width: 100%;
|
||||
max-width: 1830px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@media all and (max-height: 700px) {
|
||||
#searchContainer { height: 20% }
|
||||
}
|
||||
|
||||
@media all and (max-height: 500px) {
|
||||
#searchContainer { height: 25% }
|
||||
}
|
||||
|
||||
@media all and (max-height: 370px) {
|
||||
#searchContainer { height: 30% }
|
||||
}
|
||||
|
||||
#searchLogoContainer {
|
||||
display: table-cell;
|
||||
width: 30%;
|
||||
text-align: end;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
#searchEngineLogo {
|
||||
-moz-margin-end: 2.5%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#searchInputContainer {
|
||||
display: table-cell;
|
||||
width: 38%;
|
||||
max-width: 700px;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
#searchText {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
padding: 3px 6px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid rgb(150,150,150);
|
||||
border-top-color: rgb(100,100,100);
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,0.5);
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#searchButtons {
|
||||
display: table-cell;
|
||||
width: 31%;
|
||||
-moz-padding-start: 13px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
@media all and (max-width: 470px) {
|
||||
#searchLogoContainer { width: 10% }
|
||||
#searchButtons { width: 11% }
|
||||
#searchInputContainer { width: 40% }
|
||||
}
|
||||
|
||||
@media all and (min-width: 470px) and (max-width: 600px) {
|
||||
#searchLogoContainer { width: 15% }
|
||||
#searchButtons { width: 16%; white-space: nowrap }
|
||||
#searchInputContainer { width: 45% }
|
||||
}
|
||||
|
||||
@media all and (min-width: 600px) and (max-width: 850px) {
|
||||
#searchLogoContainer { width: 20% }
|
||||
#searchButtons { width: 21%; white-space: nowrap }
|
||||
#searchInputContainer { width: 49% }
|
||||
}
|
||||
|
||||
#searchSubmit {
|
||||
background: -moz-linear-gradient(#f1f1f1, #dfdfdf);
|
||||
padding: 4px 8px;
|
||||
height: 32px;
|
||||
border: 1px solid #ccc;
|
||||
border-top-color: #ccc;
|
||||
border-bottom-color: #999;
|
||||
-moz-border-start-color: #afafaf;
|
||||
-moz-border-end-color: #999;
|
||||
box-shadow: 1px 1px 0 #e7e7e7,
|
||||
0 1px 0 #fcfcfc inset,
|
||||
0 -1px 0 #d7d7d7 inset;
|
||||
font-size: 1em;
|
||||
color: #000;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
body[dir=rtl] #searchSubmit {
|
||||
box-shadow: -1px 1px 0 #e7e7e7,
|
||||
0 1px 0 #fcfcfc inset,
|
||||
0 -1px 0 #d7d7d7 inset;
|
||||
}
|
||||
|
||||
#searchSubmit:active {
|
||||
background: -moz-linear-gradient(#c5c5c5, #c5c5c5);
|
||||
box-shadow: 1px 1px 0 #e7e7e7;
|
||||
}
|
||||
|
||||
body[dir=rtl] #searchSubmit:active {
|
||||
box-shadow: -1px 1px 0 #e7e7e7;
|
||||
}
|
||||
|
||||
#contentContainer {
|
||||
height: 30%;
|
||||
background-image: -moz-radial-gradient(center top, ellipse farthest-side, rgba(16,83,130,.5), rgba(16,83,130,0) 75%),
|
||||
-moz-radial-gradient(center top, ellipse farthest-side, rgba(180,218,244,.5), rgba(180,218,244,0)),
|
||||
-moz-radial-gradient(center top, ellipse farthest-side, rgba(180,218,244,.3), rgba(180,218,244,0));
|
||||
background-size: 100% 5px,
|
||||
100% 50px,
|
||||
100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@media all and (max-height: 400px) {
|
||||
#contentContainer { height: 20% }
|
||||
}
|
||||
|
||||
#snippetContainer {
|
||||
position: relative;
|
||||
top: -24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#snippets {
|
||||
display: inline-block;
|
||||
padding: 14px;
|
||||
width: 30%;
|
||||
max-width: 600px;
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.8), rgba(255,255,255,.1));
|
||||
background-color: rgb(250,250,250);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,.8) inset,
|
||||
0 -2px 0 rgba(0,0,0,.1) inset,
|
||||
0 0 10px rgba(255,255,255,.5) inset,
|
||||
0 0 0 1px rgba(0,0,0,.1),
|
||||
0 2px 4px rgba(0,0,0,.2);
|
||||
color: rgb(60,60,60);
|
||||
font-size: .85em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#snippets:empty {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
@media all and (max-width: 470px) {
|
||||
#snippets { width: 65% }
|
||||
}
|
||||
|
||||
@media all and (min-width: 470px) and (max-width: 850px) {
|
||||
#snippets { width: 45% }
|
||||
}
|
||||
|
||||
#snippets:hover {
|
||||
background-color: rgb(255,255,255);
|
||||
box-shadow: 0 1px 0 rgba(255,255,255,.8) inset,
|
||||
0 -2px 0 rgba(0,0,0,.1) inset,
|
||||
0 0 10px rgba(255,255,255,.5) inset,
|
||||
0 0 5px rgba(0,0,0,.1),
|
||||
0 0 0 1px rgba(0,0,0,.1),
|
||||
0 2px 4px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
#snippets:hover:active {
|
||||
background-color: rgb(210,210,210);
|
||||
box-shadow: 0 2px 3px rgba(0,0,0,.3) inset,
|
||||
0 1px 0 rgba(255,255,255,.5);
|
||||
}
|
||||
|
||||
#defaultSnippet1,
|
||||
#defaultSnippet2 {
|
||||
display: table-row;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
#defaultSnippet1::before,
|
||||
#defaultSnippet2::before {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
-moz-padding-end: 1em;
|
||||
}
|
||||
|
||||
#defaultSnippet1::before {
|
||||
content: url("chrome://browser/content/aboutHome-snippet1.png");
|
||||
}
|
||||
#defaultSnippet2::before {
|
||||
content: url("chrome://browser/content/aboutHome-snippet2.png");
|
||||
}
|
||||
|
||||
#sessionRestoreContainer {
|
||||
padding-top: 1.5%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media all and (max-height: 500px) {
|
||||
#sessionRestoreContainer {
|
||||
position: relative;
|
||||
top: -15px;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#restorePreviousSession {
|
||||
padding: 10px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 0 1px rgba(9,37,59,0),
|
||||
0 1px 2px rgba(9,37,59,0),
|
||||
0 0 10px rgba(255,255,255,0),
|
||||
0 -3px 0 rgba(180,194,212,0) inset;
|
||||
-moz-transition-property: background-color, box-shadow;
|
||||
-moz-transition-duration: 0.25s;
|
||||
-moz-transition-timing-function: ease-out;
|
||||
background: transparent;
|
||||
color: rgb(50,50,50);
|
||||
font-weight: bold;
|
||||
font-size: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#restorePreviousSession::before {
|
||||
display: inline-block;
|
||||
content: url("chrome://browser/content/aboutHome-restore-icon.png");
|
||||
-moz-margin-end: 10px;
|
||||
vertical-align: middle;
|
||||
height: 66px; /* Needed to avoid a blank space under the image */
|
||||
}
|
||||
|
||||
body[dir=rtl] #restorePreviousSession::before {
|
||||
-moz-transform: scaleX(-1);
|
||||
}
|
||||
|
||||
@media all and (max-height: 500px) {
|
||||
#restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/aboutHome-restore-icon-small.png");
|
||||
height: 41px;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 500px) {
|
||||
#restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/aboutHome-restore-icon-small.png");
|
||||
height: 41px;
|
||||
}
|
||||
}
|
||||
|
||||
#restorePreviousSession:disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#restorePreviousSession:hover {
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.7), rgba(255,255,255,.2));
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 0 1px rgba(9,37,59,.2),
|
||||
0 1px 2px rgba(9,37,59,.2),
|
||||
0 0 10px rgba(255,255,255,.4),
|
||||
0 -3px 0 rgba(180,194,212,.3) inset;
|
||||
}
|
||||
|
||||
#restorePreviousSession:hover:active {
|
||||
background-image: -moz-linear-gradient(rgba(255,255,255,.0), rgba(255,255,255,.2));
|
||||
background-color: rgba(23,75,115,.1);
|
||||
box-shadow: 0 0 0 1px rgba(9,37,59,.2),
|
||||
0 1px 2px rgba(9,37,59,.4) inset,
|
||||
0 1px 5px rgba(9,37,59,.15) inset;
|
||||
}
|
||||
|
||||
#bottomSection {
|
||||
position: absolute;
|
||||
color: rgb(150,150,150);
|
||||
font-size: .8em;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
bottom: 2%;
|
||||
}
|
||||
|
||||
#syncLinksContainer {
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
.sync-link {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
@media all and (max-height: 370px) {
|
||||
#bottomSection {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
362
browser/base/content/abouthome/aboutHome.css
Normal file
@ -0,0 +1,362 @@
|
||||
%if 0
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is aboutHome.xhtml.
|
||||
*
|
||||
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (original author)
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Stephen Horlander <shorlander@mozilla.com>
|
||||
* Frank Yan <fyan@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* 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 ***** */
|
||||
%endif
|
||||
|
||||
html {
|
||||
font: message-box;
|
||||
font-size: 100%;
|
||||
background-color: hsl(0,0%,90%);
|
||||
background-image: url(chrome://browser/content/abouthome/noise.png),
|
||||
-moz-linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.4));
|
||||
background-attachment: fixed;
|
||||
color: #000;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#container {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
color: -moz-nativehyperlinktext;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
#topSection {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#brandLogo {
|
||||
height: 154px;
|
||||
margin: 22px 0 31px;
|
||||
}
|
||||
|
||||
#searchForm,
|
||||
#snippets {
|
||||
width: 470px;
|
||||
}
|
||||
|
||||
#searchForm {
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
#searchLogoContainer {
|
||||
display: -moz-box;
|
||||
-moz-box-align: center;
|
||||
padding-top: 2px;
|
||||
-moz-padding-end: 8px;
|
||||
}
|
||||
|
||||
#searchEngineLogo {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#searchText {
|
||||
-moz-box-flex: 1;
|
||||
padding: 6px 8px;
|
||||
background: hsla(0,0%,100%,.9) padding-box;
|
||||
border: 1px solid;
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset,
|
||||
0 0 2px hsla(210,65%,9%,.1) inset,
|
||||
0 1px 0 hsla(0,0%,100%,.2);
|
||||
border-radius: 2.5px 0 0 2.5px;
|
||||
}
|
||||
|
||||
body[dir=rtl] #searchText {
|
||||
border-radius: 0 2.5px 2.5px 0;
|
||||
}
|
||||
|
||||
#searchText:focus {
|
||||
border-color: hsla(206,100%,60%,.6) hsla(206,76%,52%,.6) hsla(204,100%,40%,.6);
|
||||
}
|
||||
|
||||
#searchSubmit {
|
||||
-moz-margin-start: -1px;
|
||||
background: -moz-linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1)) padding-box;
|
||||
padding: 0 9px;
|
||||
border: 1px solid;
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
-moz-border-start: 1px solid transparent;
|
||||
border-radius: 0 2.5px 2.5px 0;
|
||||
box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
|
||||
0 1px 0 hsla(0,0%,100%,.2);
|
||||
cursor: pointer;
|
||||
-moz-transition-property: background-color, border-color, box-shadow;
|
||||
-moz-transition-duration: 150ms;
|
||||
}
|
||||
|
||||
body[dir=rtl] #searchSubmit {
|
||||
border-radius: 2.5px 0 0 2.5px;
|
||||
}
|
||||
|
||||
#searchText:focus + #searchSubmit,
|
||||
#searchText + #searchSubmit:hover {
|
||||
border-color: #59b5fc #45a3e7 #3294d5;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#searchText:focus + #searchSubmit {
|
||||
background-image: -moz-linear-gradient(#4cb1ff, #1793e5);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.1) inset,
|
||||
0 1px 0 hsla(210,54%,20%,.03);
|
||||
}
|
||||
|
||||
#searchText + #searchSubmit:hover {
|
||||
background-image: -moz-linear-gradient(#66bdff, #0d9eff);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
|
||||
0 0 0 1px hsla(0,0%,100%,.1) inset,
|
||||
0 1px 0 hsla(210,54%,20%,.03),
|
||||
0 0 4px hsla(206,100%,20%,.2);
|
||||
}
|
||||
|
||||
#searchText + #searchSubmit:hover:active {
|
||||
box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset,
|
||||
0 0 1px hsla(211,79%,6%,.2) inset;
|
||||
-moz-transition-duration: 0ms;
|
||||
}
|
||||
|
||||
#defaultSnippet1,
|
||||
#defaultSnippet2 {
|
||||
display: block;
|
||||
min-height: 38px;
|
||||
background: 30px center no-repeat;
|
||||
padding: 6px 0;
|
||||
-moz-padding-start: 79px;
|
||||
}
|
||||
|
||||
body[dir=rtl] #defaultSnippet1,
|
||||
body[dir=rtl] #defaultSnippet2 {
|
||||
background-position: right 30px center;
|
||||
}
|
||||
|
||||
#defaultSnippet1 {
|
||||
background-image: url("chrome://browser/content/abouthome/snippet1.png");
|
||||
}
|
||||
|
||||
#defaultSnippet2 {
|
||||
background-image: url("chrome://browser/content/abouthome/snippet2.png");
|
||||
}
|
||||
|
||||
#snippets {
|
||||
display: inline-block;
|
||||
text-align: start;
|
||||
margin: 12px 0;
|
||||
color: #3c3c3c;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
#launcher {
|
||||
display: -moz-box;
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: center;
|
||||
width: 100%;
|
||||
background-color: hsla(0,0%,0%,.03);
|
||||
border-top: 1px solid hsla(0,0%,0%,.03);
|
||||
box-shadow: 0 1px 2px hsla(0,0%,0%,.02) inset,
|
||||
0 -1px 0 hsla(0,0%,100%,.25);
|
||||
}
|
||||
|
||||
#launcher:not([session]),
|
||||
body[narrow] #launcher[session] {
|
||||
display: block; /* display separator and restore button on separate lines */
|
||||
text-align: center;
|
||||
white-space: nowrap; /* prevent navigational buttons from wrapping */
|
||||
}
|
||||
|
||||
.launchButton {
|
||||
display: -moz-box;
|
||||
-moz-box-orient: vertical;
|
||||
margin: 16px 1px;
|
||||
padding: 14px 6px;
|
||||
min-width: 88px;
|
||||
max-width: 176px;
|
||||
background: transparent padding-box;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2.5px;
|
||||
color: #525c66;
|
||||
font-size: 75%;
|
||||
cursor: pointer;
|
||||
-moz-transition-property: background-color, border-color, box-shadow;
|
||||
-moz-transition-duration: 150ms;
|
||||
}
|
||||
|
||||
body[narrow] #launcher[session] > .launchButton {
|
||||
margin: 4px 1px;
|
||||
max-height: 85px;
|
||||
vertical-align: top;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.launchButton:hover {
|
||||
background-color: hsla(211,79%,6%,.03);
|
||||
border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
|
||||
}
|
||||
|
||||
.launchButton:hover:active {
|
||||
background-image: -moz-linear-gradient(hsla(211,79%,6%,.02), hsla(211,79%,6%,.05));
|
||||
border-color: hsla(210,54%,20%,.2) hsla(210,54%,20%,.23) hsla(210,54%,20%,.25);
|
||||
box-shadow: 0 1px 1px hsla(211,79%,6%,.05) inset,
|
||||
0 0 1px hsla(211,79%,6%,.1) inset;
|
||||
-moz-transition-duration: 0ms;
|
||||
}
|
||||
|
||||
#launcher:not([session]) > #restorePreviousSessionSeparator,
|
||||
#launcher:not([session]) > #restorePreviousSession {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#restorePreviousSessionSeparator {
|
||||
width: 3px;
|
||||
height: 116px;
|
||||
margin: 0 10px;
|
||||
background-image: -moz-linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)),
|
||||
-moz-linear-gradient(hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)),
|
||||
-moz-linear-gradient(hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0));
|
||||
background-position: left top, center, right bottom;
|
||||
background-size: 1px auto;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSessionSeparator {
|
||||
margin: 0 auto;
|
||||
width: 512px;
|
||||
height: 3px;
|
||||
background-image: -moz-linear-gradient(0, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0)),
|
||||
-moz-linear-gradient(0, hsla(211,79%,6%,0), hsla(211,79%,6%,.2), hsla(211,79%,6%,0)),
|
||||
-moz-linear-gradient(0, hsla(0,0%,100%,0), hsla(0,0%,100%,.35), hsla(0,0%,100%,0));
|
||||
background-size: auto 1px;
|
||||
}
|
||||
|
||||
#restorePreviousSession {
|
||||
max-width: none;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSession {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.launchButton::before {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
line-height: 0; /* remove extra vertical space due to non-zero font-size */
|
||||
}
|
||||
|
||||
#bookmarks::before {
|
||||
content: url("chrome://browser/content/abouthome/bookmarks.png");
|
||||
}
|
||||
|
||||
#history::before {
|
||||
content: url("chrome://browser/content/abouthome/history.png");
|
||||
}
|
||||
|
||||
#settings::before {
|
||||
content: url("chrome://browser/content/abouthome/settings.png");
|
||||
}
|
||||
|
||||
#addons::before {
|
||||
content: url("chrome://browser/content/abouthome/addons.png");
|
||||
}
|
||||
|
||||
#downloads::before {
|
||||
content: url("chrome://browser/content/abouthome/downloads.png");
|
||||
}
|
||||
|
||||
#sync::before {
|
||||
content: url("chrome://browser/content/abouthome/sync.png");
|
||||
}
|
||||
|
||||
#restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/abouthome/restore-large.png");
|
||||
display: inline-block; /* display on same line as text label */
|
||||
vertical-align: middle;
|
||||
margin-bottom: 0;
|
||||
-moz-margin-end: 8px;
|
||||
}
|
||||
|
||||
body[dir=rtl] #restorePreviousSession::before {
|
||||
-moz-transform: scaleX(-1);
|
||||
}
|
||||
|
||||
body[narrow] #restorePreviousSession::before {
|
||||
content: url("chrome://browser/content/abouthome/restore.png");
|
||||
}
|
||||
|
||||
#aboutMozilla {
|
||||
display: block;
|
||||
position: relative; /* pin wordmark to edge of document, not of viewport */
|
||||
-moz-box-ordinal-group: 0;
|
||||
opacity: .5;
|
||||
-moz-transition: opacity 150ms;
|
||||
}
|
||||
|
||||
#aboutMozilla:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#aboutMozilla::before {
|
||||
content: url("chrome://browser/content/abouthome/mozilla.png");
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (original author)
|
||||
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||
* Frank Yan <fyan@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -155,6 +156,9 @@ function onLoad(event)
|
||||
document.getElementById("searchText").focus();
|
||||
|
||||
loadSnippets();
|
||||
|
||||
fitToWidth();
|
||||
window.addEventListener("resize", fitToWidth);
|
||||
}
|
||||
|
||||
|
||||
@ -210,13 +214,17 @@ function loadSnippets()
|
||||
let updateURL = localStorage["snippets-update-url"];
|
||||
if (updateURL && (!lastUpdate ||
|
||||
Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS)) {
|
||||
// Try to update from network.
|
||||
let xhr = new XMLHttpRequest();
|
||||
try {
|
||||
xhr.open("GET", updateURL, true);
|
||||
} catch (ex) {
|
||||
showSnippets();
|
||||
return;
|
||||
}
|
||||
// Even if fetching should fail we don't want to spam the server, thus
|
||||
// set the last update time regardless its results. Will retry tomorrow.
|
||||
localStorage["snippets-last-update"] = Date.now();
|
||||
|
||||
// Try to update from network.
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', updateURL, true);
|
||||
xhr.onerror = function (event) {
|
||||
showSnippets();
|
||||
};
|
||||
@ -260,7 +268,7 @@ function showSnippets()
|
||||
let defaultSnippetsElt = document.getElementById("defaultSnippets");
|
||||
let entries = defaultSnippetsElt.querySelectorAll("span");
|
||||
// Choose a random snippet. Assume there is always at least one.
|
||||
let randIndex = Math.round(Math.random() * (entries.length - 1));
|
||||
let randIndex = Math.floor(Math.random() * entries.length);
|
||||
let entry = entries[randIndex];
|
||||
// Inject url in the eventual link.
|
||||
if (DEFAULT_SNIPPETS_URLS[randIndex]) {
|
||||
@ -269,27 +277,17 @@ function showSnippets()
|
||||
// up in the translation.
|
||||
if (links.length == 1) {
|
||||
links[0].href = DEFAULT_SNIPPETS_URLS[randIndex];
|
||||
activateSnippetsButtonClick(entry);
|
||||
}
|
||||
}
|
||||
// Move the default snippet to the snippets element.
|
||||
snippetsElt.appendChild(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches a single link element in aElt and binds its href to the click
|
||||
* action of the snippets button.
|
||||
*
|
||||
* @param aElt
|
||||
* Element to search the link into.
|
||||
*/
|
||||
function activateSnippetsButtonClick(aElt) {
|
||||
let links = aElt.getElementsByTagName("a");
|
||||
if (links.length == 1) {
|
||||
document.getElementById("snippets")
|
||||
.addEventListener("click", function(aEvent) {
|
||||
if (aEvent.target.nodeName != "a")
|
||||
window.location = links[0].href;
|
||||
}, false);
|
||||
function fitToWidth() {
|
||||
if (window.scrollMaxX) {
|
||||
document.body.setAttribute("narrow", "true");
|
||||
} else if (document.body.hasAttribute("narrow")) {
|
||||
document.body.removeAttribute("narrow");
|
||||
fitToWidth();
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
# Marco Bonardo <mak77@bonardo.net> (original author)
|
||||
# Mihai Sucan <mihai.sucan@gmail.com>
|
||||
# Stephen Horlander <shorlander@mozilla.com>
|
||||
# Frank Yan <fyan@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -60,52 +61,48 @@
|
||||
<link rel="icon" type="image/png" id="favicon"
|
||||
href="chrome://branding/content/icon16.png"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/content/aboutHome.css"/>
|
||||
href="chrome://browser/content/abouthome/aboutHome.css"/>
|
||||
|
||||
<script type="text/javascript;version=1.8"
|
||||
src="chrome://browser/content/aboutHome.js"/>
|
||||
src="chrome://browser/content/abouthome/aboutHome.js"/>
|
||||
</head>
|
||||
|
||||
<body dir="&locale.dir;" onload="onLoad(event)">
|
||||
<div id="brandStartSpacer" />
|
||||
<div id="brandStart">
|
||||
<img id="brandStartLogo" src="chrome://branding/content/about-logo.png" alt="" />
|
||||
</div>
|
||||
<div id="container">
|
||||
<div class="spacer"/>
|
||||
<div id="topSection">
|
||||
<img id="brandLogo" src="chrome://branding/content/about-logo.png" alt=""/>
|
||||
|
||||
<div id="searchContainer">
|
||||
<form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)">
|
||||
<div id="searchLogoContainer"><img id="searchEngineLogo" /></div>
|
||||
<div id="searchInputContainer">
|
||||
<input type="text" name="q" value="" id="searchText" maxlength="256" />
|
||||
<div id="searchContainer">
|
||||
<form name="searchForm" id="searchForm" onsubmit="onSearchSubmit(event)">
|
||||
<div id="searchLogoContainer"><img id="searchEngineLogo"/></div>
|
||||
<input type="text" name="q" value="" id="searchText" maxlength="256"/>
|
||||
<input id="searchSubmit" type="submit" value="&abouthome.searchEngineButton.label;"/>
|
||||
</form>
|
||||
</div>
|
||||
<div id="searchButtons">
|
||||
<input id="searchSubmit" type="submit" value="&abouthome.searchEngineButton.label;" />
|
||||
|
||||
<div id="snippetContainer">
|
||||
<div id="defaultSnippets" hidden="true">
|
||||
<span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
|
||||
<span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
|
||||
</div>
|
||||
<div id="snippets"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacer"/>
|
||||
|
||||
<div id="contentContainer">
|
||||
<div id="snippetContainer">
|
||||
<div id="defaultSnippets" hidden="true">
|
||||
<span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
|
||||
<span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
|
||||
</div>
|
||||
<div id="snippets"/>
|
||||
<div id="launcher" session="true">
|
||||
<button class="launchButton" id="bookmarks">&abouthome.bookmarksButton.label;</button>
|
||||
<button class="launchButton" id="history">&abouthome.historyButton.label;</button>
|
||||
<button class="launchButton" id="settings">&abouthome.settingsButton.label;</button>
|
||||
<button class="launchButton" id="addons">&abouthome.addonsButton.label;</button>
|
||||
<button class="launchButton" id="downloads">&abouthome.downloadsButton.label;</button>
|
||||
<button class="launchButton" id="sync">&syncBrand.shortName.label;</button>
|
||||
<div id="restorePreviousSessionSeparator"/>
|
||||
<button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button>
|
||||
</div>
|
||||
|
||||
<div id="sessionRestoreContainer">
|
||||
<button id="restorePreviousSession">&historyRestoreLastSession.label;</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="bottomSection">
|
||||
<div id="aboutMozilla">
|
||||
<a href="http://www.mozilla.com/about/">&abouthome.aboutMozilla;</a>
|
||||
</div>
|
||||
<div id="syncLinksContainer">
|
||||
<a href="javascript:void(0);" class="sync-link" id="setupSyncLink">&abouthome.syncSetup.label;</a>
|
||||
<a href="javascript:void(0);" class="sync-link" id="pairDeviceLink">&abouthome.pairDevice.label;</a>
|
||||
</div>
|
||||
<a id="aboutMozilla" href="http://www.mozilla.com/about/"/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
browser/base/content/abouthome/addons.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
browser/base/content/abouthome/bookmarks.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
browser/base/content/abouthome/downloads.png
Normal file
After Width: | Height: | Size: 898 B |
BIN
browser/base/content/abouthome/history.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
browser/base/content/abouthome/mozilla.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
browser/base/content/abouthome/noise.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
browser/base/content/abouthome/restore-large.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
browser/base/content/abouthome/restore.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
browser/base/content/abouthome/settings.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
BIN
browser/base/content/abouthome/sync.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
@ -324,6 +324,7 @@
|
||||
<key id="showAllHistoryKb" key="&showAllHistoryCmd.commandkey;" command="Browser:ShowAllHistory" modifiers="accel,shift"/>
|
||||
<key keycode="VK_F5" command="Browser:ReloadSkipCache" modifiers="accel"/>
|
||||
<key keycode="VK_F6" command="Browser:FocusNextFrame"/>
|
||||
<key keycode="VK_F6" command="Browser:FocusNextFrame" modifiers="shift"/>
|
||||
<key id="key_fullScreen" keycode="VK_F11" command="View:FullScreen"/>
|
||||
#else
|
||||
<key id="key_fullScreen" key="&fullScreenCmd.macCommandKey;" command="View:FullScreen" modifiers="accel,shift"/>
|
||||
|
@ -175,21 +175,7 @@ let gSyncUI = {
|
||||
this.clearError(title);
|
||||
},
|
||||
|
||||
// Set visibility of "Setup Sync" link
|
||||
showSetupSyncAboutHome: function SUI_showSetupSyncAboutHome(toShow) {
|
||||
let browsers = gBrowser.browsers;
|
||||
for (let i = 0; i < browsers.length; i++) {
|
||||
let b = browsers[i];
|
||||
if ("about:home" == b.currentURI.spec) {
|
||||
b.contentDocument.getElementById("setupSyncLink").hidden = !toShow;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onSetupComplete: function SUI_onSetupComplete() {
|
||||
// Remove "setup sync" link in about:home if it is open.
|
||||
this.showSetupSyncAboutHome(false);
|
||||
|
||||
onLoginFinish();
|
||||
},
|
||||
|
||||
@ -237,8 +223,6 @@ let gSyncUI = {
|
||||
|
||||
onStartOver: function SUI_onStartOver() {
|
||||
this.clearError();
|
||||
// Make "setup sync" link visible in about:home if it is open.
|
||||
this.showSetupSyncAboutHome(true);
|
||||
},
|
||||
|
||||
onQuotaNotice: function onQuotaNotice(subject, data) {
|
||||
|
@ -56,6 +56,7 @@
|
||||
# Patrick Walton <pcwalton@mozilla.com>
|
||||
# Mihai Sucan <mihai.sucan@gmail.com>
|
||||
# Victor Porof <vporof@mozilla.com>
|
||||
# Frank Yan <fyan@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -2706,11 +2707,7 @@ function BrowserOnAboutPageLoad(document) {
|
||||
let ss = Components.classes["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Components.interfaces.nsISessionStore);
|
||||
if (!ss.canRestoreLastSession)
|
||||
document.getElementById("sessionRestoreContainer").hidden = true;
|
||||
// Sync-related links
|
||||
if (Services.prefs.prefHasUserValue("services.sync.username")) {
|
||||
document.getElementById("setupSyncLink").hidden = true;
|
||||
}
|
||||
document.getElementById("launcher").removeAttribute("session");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2718,19 +2715,17 @@ function BrowserOnAboutPageLoad(document) {
|
||||
* Handle command events bubbling up from error page content
|
||||
*/
|
||||
function BrowserOnClick(event) {
|
||||
// Don't trust synthetic events
|
||||
if (!event.isTrusted ||
|
||||
(event.target.localName != "button" &&
|
||||
event.target.className != "sync-link"))
|
||||
if (!event.isTrusted || // Don't trust synthetic events
|
||||
event.button == 2 || event.target.localName != "button")
|
||||
return;
|
||||
|
||||
var ot = event.originalTarget;
|
||||
var errorDoc = ot.ownerDocument;
|
||||
var ownerDoc = ot.ownerDocument;
|
||||
|
||||
// If the event came from an ssl error page, it is probably either the "Add
|
||||
// Exception…" or "Get me out of here!" button
|
||||
if (/^about:certerror/.test(errorDoc.documentURI)) {
|
||||
if (ot == errorDoc.getElementById('exceptionDialogButton')) {
|
||||
if (/^about:certerror/.test(ownerDoc.documentURI)) {
|
||||
if (ot == ownerDoc.getElementById('exceptionDialogButton')) {
|
||||
var params = { exceptionAdded : false, handlePrivateBrowsing : true };
|
||||
|
||||
try {
|
||||
@ -2738,7 +2733,7 @@ function BrowserOnClick(event) {
|
||||
case 2 : // Pre-fetch & pre-populate
|
||||
params.prefetchCert = true;
|
||||
case 1 : // Pre-populate
|
||||
params.location = errorDoc.location.href;
|
||||
params.location = ownerDoc.location.href;
|
||||
}
|
||||
} catch (e) {
|
||||
Components.utils.reportError("Couldn't get ssl_override pref: " + e);
|
||||
@ -2749,22 +2744,22 @@ function BrowserOnClick(event) {
|
||||
|
||||
// If the user added the exception cert, attempt to reload the page
|
||||
if (params.exceptionAdded)
|
||||
errorDoc.location.reload();
|
||||
ownerDoc.location.reload();
|
||||
}
|
||||
else if (ot == errorDoc.getElementById('getMeOutOfHereButton')) {
|
||||
else if (ot == ownerDoc.getElementById('getMeOutOfHereButton')) {
|
||||
getMeOutOfHere();
|
||||
}
|
||||
}
|
||||
else if (/^about:blocked/.test(errorDoc.documentURI)) {
|
||||
else if (/^about:blocked/.test(ownerDoc.documentURI)) {
|
||||
// The event came from a button on a malware/phishing block page
|
||||
// First check whether it's malware or phishing, so that we can
|
||||
// use the right strings/links
|
||||
var isMalware = /e=malwareBlocked/.test(errorDoc.documentURI);
|
||||
var isMalware = /e=malwareBlocked/.test(ownerDoc.documentURI);
|
||||
|
||||
if (ot == errorDoc.getElementById('getMeOutButton')) {
|
||||
if (ot == ownerDoc.getElementById('getMeOutButton')) {
|
||||
getMeOutOfHere();
|
||||
}
|
||||
else if (ot == errorDoc.getElementById('reportButton')) {
|
||||
else if (ot == ownerDoc.getElementById('reportButton')) {
|
||||
// This is the "Why is this site blocked" button. For malware,
|
||||
// we can fetch a site-specific report, for phishing, we redirect
|
||||
// to the generic page describing phishing protection.
|
||||
@ -2774,7 +2769,7 @@ function BrowserOnClick(event) {
|
||||
// append the current url, and go there.
|
||||
try {
|
||||
let reportURL = formatURL("browser.safebrowsing.malware.reportURL", true);
|
||||
reportURL += errorDoc.location.href;
|
||||
reportURL += ownerDoc.location.href;
|
||||
content.location = reportURL;
|
||||
} catch (e) {
|
||||
Components.utils.reportError("Couldn't get malware report URL: " + e);
|
||||
@ -2788,7 +2783,7 @@ function BrowserOnClick(event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ot == errorDoc.getElementById('ignoreWarningButton')) {
|
||||
else if (ot == ownerDoc.getElementById('ignoreWarningButton')) {
|
||||
// Allow users to override and continue through to the site,
|
||||
// but add a notify bar as a reminder, so that they don't lose
|
||||
// track after, e.g., tab switching.
|
||||
@ -2843,23 +2838,31 @@ function BrowserOnClick(event) {
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (/^about:home$/i.test(errorDoc.documentURI)) {
|
||||
if (ot == errorDoc.getElementById("restorePreviousSession")) {
|
||||
else if (/^about:home$/i.test(ownerDoc.documentURI)) {
|
||||
if (ot == ownerDoc.getElementById("restorePreviousSession")) {
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
if (ss.canRestoreLastSession)
|
||||
ss.restoreLastSession();
|
||||
errorDoc.getElementById("sessionRestoreContainer").hidden = true;
|
||||
ownerDoc.getElementById("launcher").removeAttribute("session");
|
||||
}
|
||||
else if (ot == errorDoc.getElementById("pairDeviceLink")) {
|
||||
if (Services.prefs.prefHasUserValue("services.sync.username")) {
|
||||
gSyncUI.openAddDevice();
|
||||
} else {
|
||||
gSyncUI.openSetup("pair");
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("bookmarks")) {
|
||||
PlacesCommandHook.showPlacesOrganizer("AllBookmarks");
|
||||
}
|
||||
else if (ot == errorDoc.getElementById("setupSyncLink")) {
|
||||
gSyncUI.openSetup(null);
|
||||
else if (ot == ownerDoc.getElementById("history")) {
|
||||
PlacesCommandHook.showPlacesOrganizer("History");
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("settings")) {
|
||||
openPreferences();
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("addons")) {
|
||||
BrowserOpenAddonsMgr();
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("downloads")) {
|
||||
BrowserDownloadsUI();
|
||||
}
|
||||
else if (ot == ownerDoc.getElementById("sync")) {
|
||||
openPreferences("paneSync");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4497,8 +4500,13 @@ var XULBrowserWindow = {
|
||||
setOverLink: function (url, anchorElt) {
|
||||
// Encode bidirectional formatting characters.
|
||||
// (RFC 3987 sections 3.2 and 4.1 paragraph 6)
|
||||
this.overLink = url.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
|
||||
encodeURIComponent);
|
||||
url = url.replace(/[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g,
|
||||
encodeURIComponent);
|
||||
|
||||
if (gURLBar && gURLBar._mayTrimURLs /* corresponds to browser.urlbar.trimURLs */)
|
||||
url = trimURL(url);
|
||||
|
||||
this.overLink = url;
|
||||
LinkTargetDisplay.update();
|
||||
},
|
||||
|
||||
@ -5115,6 +5123,7 @@ var TabsProgressListener = {
|
||||
// document URI is not yet the about:-uri of the error page.
|
||||
|
||||
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
|
||||
Components.isSuccessCode(aStatus) &&
|
||||
/^about:/.test(aWebProgress.DOMWindow.document.documentURI)) {
|
||||
aBrowser.addEventListener("click", BrowserOnClick, false);
|
||||
aBrowser.addEventListener("pagehide", function () {
|
||||
|
@ -527,7 +527,7 @@
|
||||
<image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
<image id="webapps-notification-icon" class="webapps-anchor-icon" role="button"/>
|
||||
<image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
|
||||
</box>
|
||||
<!-- Use onclick instead of normal popup= syntax since the popup
|
||||
code fires onmousedown, and hence eats our favicon drag events.
|
||||
|
@ -10,9 +10,6 @@ registerCleanupFunction(function() {
|
||||
try {
|
||||
Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
|
||||
} catch (ex) {}
|
||||
try {
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
} catch (ex) {}
|
||||
});
|
||||
|
||||
let gTests = [
|
||||
@ -112,121 +109,11 @@ let gTests = [
|
||||
ok(snippetsElt, "Found snippets element");
|
||||
is(snippetsElt.getElementsByTagName("span").length, 1,
|
||||
"A default snippet is visible.");
|
||||
|
||||
let storage = getStorage();
|
||||
storage.removeItem("snippets");
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check sync links visibility before and after Sync setup",
|
||||
setup: function ()
|
||||
{
|
||||
try {
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
} catch (ex) {}
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let pairLink = doc.getElementById("pairDeviceLink");
|
||||
let setupLink = doc.getElementById("setupSyncLink");
|
||||
|
||||
ok(pairLink, "Found 'Pair Device' link");
|
||||
ok(setupLink, "Found 'Set Up Sync' link");
|
||||
ok(!pairLink.hidden, "'Pair' link is visible before setup");
|
||||
ok(!setupLink.hidden, "'Set Up' link is visible before setup");
|
||||
|
||||
Services.obs.notifyObservers(null, "weave:service:setup-complete", null);
|
||||
|
||||
executeSoon(function () {
|
||||
setupLink = doc.getElementById("setupSyncLink");
|
||||
ok(setupLink.hidden, "'Set Up' link is hidden after setup");
|
||||
ok(!pairLink.hidden, "'Pair' link is visible after setup");
|
||||
|
||||
executeSoon(runNextTest);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check sync links visibility before and after Sync unlink",
|
||||
setup: function ()
|
||||
{
|
||||
Services.prefs.setCharPref("services.sync.username", "someuser@domain.com");
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
|
||||
let pairLink = doc.getElementById("pairDeviceLink");
|
||||
let setupLink = doc.getElementById("setupSyncLink");
|
||||
|
||||
ok(!pairLink.hidden, "'Pair' link is visible before unlink");
|
||||
ok(setupLink.hidden, "'Set Up' link is hidden before unlink");
|
||||
|
||||
Services.obs.notifyObservers(null, "weave:service:start-over", null);
|
||||
|
||||
executeSoon(function () {
|
||||
setupLink = doc.getElementById("setupSyncLink");
|
||||
ok(!setupLink.hidden, "'Set Up' link is visible after unlink");
|
||||
ok(!pairLink.hidden, "'Pair' link is visible after unlink");
|
||||
executeSoon(runNextTest);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check Pair Device link opens correct dialog with Sync account ",
|
||||
setup: function ()
|
||||
{
|
||||
Services.prefs.setCharPref("services.sync.username", "someuser@domain.com");
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
expectDialogWindow("Sync:AddDevice");
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let button = browser.contentDocument.getElementById("pairDeviceLink");
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, browser.contentWindow);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check Pair Device link opens correct dialog without Sync account",
|
||||
setup: function ()
|
||||
{
|
||||
try {
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
} catch (ex) {}
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
expectDialogWindow("Weave:AccountSetup");
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let button = browser.contentDocument.getElementById("pairDeviceLink");
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, browser.contentWindow);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Check Sync Setup link opens correct dialog (without Sync account)",
|
||||
setup: function ()
|
||||
{
|
||||
try {
|
||||
Services.prefs.clearUserPref("services.sync.username");
|
||||
} catch (ex) {}
|
||||
Services.obs.notifyObservers(null, "weave:service:ready", null);
|
||||
},
|
||||
run: function ()
|
||||
{
|
||||
expectDialogWindow("Weave:AccountSetup");
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
let button = browser.contentDocument.getElementById("setupSyncLink");
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, browser.contentWindow);
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
function test()
|
||||
@ -272,22 +159,6 @@ function runNextTest()
|
||||
}
|
||||
}
|
||||
|
||||
function expectDialogWindow(expectedDialog) {
|
||||
Services.ww.registerNotification(function onWindow(subject, topic) {
|
||||
let win = subject.QueryInterface(Components.interfaces.nsIDOMWindow);
|
||||
win.addEventListener("load", function onLoad() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
let wintype = win.document.documentElement.getAttribute("windowtype");
|
||||
if (topic == "domwindowopened" && wintype == expectedDialog) {
|
||||
Services.ww.unregisterNotification(onWindow);
|
||||
// Clean up dialog.
|
||||
win.close();
|
||||
executeSoon(runNextTest);
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
function getStorage()
|
||||
{
|
||||
let aboutHomeURI = Services.io.newURI("moz-safe-about:home", null, null);
|
||||
|
@ -25,7 +25,7 @@ function runTests() {
|
||||
checkGrid("0,1,2,3,7,8,9,,");
|
||||
|
||||
// we removed a pinned site
|
||||
reset();
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks(",1");
|
||||
|
||||
@ -37,7 +37,7 @@ function runTests() {
|
||||
|
||||
// we remove the last site on the grid (which is pinned) and expect the gap
|
||||
// to be re-filled and the new site to be unpinned
|
||||
reset();
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks(",,,,,,,,8");
|
||||
|
||||
@ -49,7 +49,7 @@ function runTests() {
|
||||
|
||||
// we remove the first site on the grid with the last one pinned. all cells
|
||||
// but the last one should shift to the left and a new site fades in
|
||||
reset();
|
||||
yield restore();
|
||||
setLinks("0,1,2,3,4,5,6,7,8,9");
|
||||
setPinnedLinks(",,,,,,,,8");
|
||||
|
||||
|
@ -2,13 +2,11 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function runTests() {
|
||||
// TODO Bug 735166 - Intermittent timeout in browser_newtab_bug734043.js
|
||||
return;
|
||||
|
||||
setLinks("0,1,2,3,4,5,6,7,8");
|
||||
setPinnedLinks("");
|
||||
|
||||
yield addNewTabPageTab();
|
||||
checkGrid("0,1,2,3,4,5,6,7,8");
|
||||
|
||||
let receivedError = false;
|
||||
let block = cw.document.querySelector(".newtab-control-block");
|
||||
@ -19,10 +17,8 @@ function runTests() {
|
||||
|
||||
cw.addEventListener("error", onError);
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let i = 0; i < 3; i++)
|
||||
EventUtils.synthesizeMouseAtCenter(block, {}, cw);
|
||||
yield executeSoon(TestRunner.next);
|
||||
}
|
||||
|
||||
yield whenPagesUpdated();
|
||||
ok(!receivedError, "we got here without any errors");
|
||||
|
@ -10,8 +10,6 @@ Cu.import("resource:///modules/NewTabUtils.jsm", tmp);
|
||||
let NewTabUtils = tmp.NewTabUtils;
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
reset();
|
||||
|
||||
while (gBrowser.tabs.length > 1)
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
|
||||
@ -57,8 +55,29 @@ let TestRunner = {
|
||||
try {
|
||||
TestRunner._iter.next();
|
||||
} catch (e if e instanceof StopIteration) {
|
||||
finish();
|
||||
TestRunner.finish();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Finishes all tests and cleans up.
|
||||
*/
|
||||
finish: function () {
|
||||
function cleanupAndFinish() {
|
||||
// Restore the old provider.
|
||||
NewTabUtils.links._provider = originalProvider;
|
||||
|
||||
whenPagesUpdated(finish);
|
||||
NewTabUtils.restore();
|
||||
}
|
||||
|
||||
let callbacks = NewTabUtils.links._populateCallbacks;
|
||||
let numCallbacks = callbacks.length;
|
||||
|
||||
if (numCallbacks)
|
||||
callbacks.splice(0, numCallbacks, cleanupAndFinish);
|
||||
else
|
||||
cleanupAndFinish();
|
||||
}
|
||||
};
|
||||
|
||||
@ -106,13 +125,11 @@ function setPinnedLinks(aLinksPattern) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the lists of blocked and pinned links and clears the storage.
|
||||
* Restore the grid state.
|
||||
*/
|
||||
function reset() {
|
||||
NewTabUtils.reset();
|
||||
|
||||
// Restore the old provider to prevent memory leaks.
|
||||
NewTabUtils.links._provider = originalProvider;
|
||||
function restore() {
|
||||
whenPagesUpdated();
|
||||
NewTabUtils.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,11 +286,11 @@ function simulateDrop(aDropTarget, aDragSource) {
|
||||
/**
|
||||
* Resumes testing when all pages have been updated.
|
||||
*/
|
||||
function whenPagesUpdated() {
|
||||
function whenPagesUpdated(aCallback) {
|
||||
let page = {
|
||||
update: function () {
|
||||
NewTabUtils.allPages.unregister(this);
|
||||
executeSoon(TestRunner.next);
|
||||
executeSoon(aCallback || TestRunner.next);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,13 +16,21 @@ browser.jar:
|
||||
* content/browser/aboutDialog.js (content/aboutDialog.js)
|
||||
* content/browser/aboutDialog.css (content/aboutDialog.css)
|
||||
* content/browser/aboutRobots.xhtml (content/aboutRobots.xhtml)
|
||||
* content/browser/aboutHome.xhtml (content/aboutHome.xhtml)
|
||||
* content/browser/aboutHome.js (content/aboutHome.js)
|
||||
* content/browser/aboutHome.css (content/aboutHome.css)
|
||||
content/browser/aboutHome-restore-icon.png (content/aboutHome-restore-icon.png)
|
||||
content/browser/aboutHome-restore-icon-small.png (content/aboutHome-restore-icon-small.png)
|
||||
content/browser/aboutHome-snippet1.png (content/aboutHome-snippet1.png)
|
||||
content/browser/aboutHome-snippet2.png (content/aboutHome-snippet2.png)
|
||||
* content/browser/abouthome/aboutHome.xhtml (content/abouthome/aboutHome.xhtml)
|
||||
* content/browser/abouthome/aboutHome.js (content/abouthome/aboutHome.js)
|
||||
* content/browser/abouthome/aboutHome.css (content/abouthome/aboutHome.css)
|
||||
content/browser/abouthome/snippet1.png (content/abouthome/snippet1.png)
|
||||
content/browser/abouthome/snippet2.png (content/abouthome/snippet2.png)
|
||||
content/browser/abouthome/bookmarks.png (content/abouthome/bookmarks.png)
|
||||
content/browser/abouthome/history.png (content/abouthome/history.png)
|
||||
content/browser/abouthome/settings.png (content/abouthome/settings.png)
|
||||
content/browser/abouthome/addons.png (content/abouthome/addons.png)
|
||||
content/browser/abouthome/downloads.png (content/abouthome/downloads.png)
|
||||
content/browser/abouthome/sync.png (content/abouthome/sync.png)
|
||||
content/browser/abouthome/restore.png (content/abouthome/restore.png)
|
||||
content/browser/abouthome/restore-large.png (content/abouthome/restore-large.png)
|
||||
content/browser/abouthome/mozilla.png (content/abouthome/mozilla.png)
|
||||
content/browser/abouthome/noise.png (content/abouthome/noise.png)
|
||||
content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
|
||||
content/browser/aboutRobots-widget-left.png (content/aboutRobots-widget-left.png)
|
||||
* content/browser/browser.css (content/browser.css)
|
||||
|
@ -102,7 +102,7 @@ static RedirEntry kRedirMap[] = {
|
||||
{ "sync-tabs", "chrome://browser/content/sync/aboutSyncTabs.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#endif
|
||||
{ "home", "chrome://browser/content/aboutHome.xhtml",
|
||||
{ "home", "chrome://browser/content/abouthome/aboutHome.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "newtab", "chrome://browser/content/newtab/newTab.xul",
|
||||
|
@ -56,7 +56,7 @@
|
||||
|
||||
#define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
|
||||
|
||||
#define BOOKMARKS_FILE_NAME NS_LITERAL_STRING("bookmarks.html")
|
||||
#define DEFAULT_BOOKMARKS NS_LITERAL_CSTRING("resource:///defaults/profile/bookmarks.html")
|
||||
|
||||
void SetUnicharPref(const char* aPref, const nsAString& aValue,
|
||||
nsIPrefBranch* aPrefs)
|
||||
@ -164,72 +164,19 @@ GetProfilePath(nsIProfileStartup* aStartup, nsCOMPtr<nsIFile>& aProfileDir)
|
||||
}
|
||||
|
||||
nsresult
|
||||
ImportBookmarksHTML(nsIFile* aBookmarksFile,
|
||||
bool aImportIntoRoot,
|
||||
bool aOverwriteDefaults,
|
||||
const PRUnichar* aImportSourceNameKey)
|
||||
ImportDefaultBookmarks()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPlacesImportExportService> importer =
|
||||
do_GetService(NS_PLACESIMPORTEXPORTSERVICE_CONTRACTID);
|
||||
NS_ENSURE_STATE(importer);
|
||||
|
||||
nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(aBookmarksFile));
|
||||
NS_ENSURE_TRUE(localFile, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIPlacesImportExportService> importer = do_GetService(NS_PLACESIMPORTEXPORTSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIIOService> ioService = mozilla::services::GetIOService();
|
||||
NS_ENSURE_STATE(ioService);
|
||||
nsCOMPtr<nsIURI> bookmarksURI;
|
||||
nsresult rv = ioService->NewURI(DEFAULT_BOOKMARKS, nsnull, nsnull,
|
||||
getter_AddRefs(bookmarksURI));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Import file directly into the bookmarks root folder.
|
||||
if (aImportIntoRoot) {
|
||||
rv = importer->ImportHTMLFromFile(localFile, aOverwriteDefaults);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the source application name.
|
||||
nsCOMPtr<nsIStringBundleService> bundleService =
|
||||
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle(MIGRATION_BUNDLE, getter_AddRefs(bundle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString sourceName;
|
||||
rv = bundle->GetStringFromName(aImportSourceNameKey,
|
||||
getter_Copies(sourceName));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
const PRUnichar* sourceNameStrings[] = { sourceName.get() };
|
||||
nsString importedBookmarksTitle;
|
||||
rv = bundle->FormatStringFromName(NS_LITERAL_STRING("importedBookmarksFolder").get(),
|
||||
sourceNameStrings, 1,
|
||||
getter_Copies(importedBookmarksTitle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get the bookmarks service.
|
||||
nsCOMPtr<nsINavBookmarksService> bms =
|
||||
do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Create an imported bookmarks folder under the bookmarks menu.
|
||||
PRInt64 root;
|
||||
rv = bms->GetBookmarksMenuFolder(&root);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 folder;
|
||||
rv = bms->CreateFolder(root, NS_ConvertUTF16toUTF8(importedBookmarksTitle),
|
||||
nsINavBookmarksService::DEFAULT_INDEX, &folder);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Import the bookmarks into the folder.
|
||||
return importer->ImportHTMLFromFileToFolder(localFile, folder, false);
|
||||
}
|
||||
|
||||
nsresult
|
||||
InitializeBookmarks(nsIFile* aTargetProfile)
|
||||
{
|
||||
nsCOMPtr<nsIFile> bookmarksFile;
|
||||
aTargetProfile->Clone(getter_AddRefs(bookmarksFile));
|
||||
bookmarksFile->Append(BOOKMARKS_FILE_NAME);
|
||||
|
||||
nsresult rv = ImportBookmarksHTML(bookmarksFile, true, true, EmptyString().get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
return importer->ImportHTMLFromURI(bookmarksURI, true);
|
||||
}
|
||||
|
@ -99,18 +99,10 @@ void GetMigrateDataFromArray(MigrationData* aDataArray,
|
||||
// this is already cloned, modify it to your heart's content
|
||||
void GetProfilePath(nsIProfileStartup* aStartup, nsCOMPtr<nsIFile>& aProfileDir);
|
||||
|
||||
// In-place import from aBookmarksFile into a folder in the user's bookmarks.
|
||||
// If the importIntoRoot parameter has a value of true, the bookmarks will be
|
||||
// imported into the bookmarks root folder. Otherwise, they'll be imported into
|
||||
// a new folder with the name "From (STR:aImportSourceNameKey)".
|
||||
// aImportSourceNameKey is a key into migration.properties with the pretty name
|
||||
// of the application.
|
||||
nsresult ImportBookmarksHTML(nsIFile* aBookmarksFile,
|
||||
bool aImportIntoRoot,
|
||||
bool aOverwriteDefaults,
|
||||
const PRUnichar* aImportSourceNameKey);
|
||||
|
||||
nsresult InitializeBookmarks(nsIFile* aTargetProfile);
|
||||
/**
|
||||
* Imports default bookmarks to the profile.
|
||||
*/
|
||||
nsresult ImportDefaultBookmarks();
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1404,11 +1404,10 @@ nsIEProfileMigrator::CopyFavoritesBatched(bool aReplace)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
// Initialize the default bookmarks
|
||||
nsCOMPtr<nsIFile> profile;
|
||||
GetProfilePath(nsnull, profile);
|
||||
rv = InitializeBookmarks(profile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// If importing defaults fails for whatever reason, let the import process
|
||||
// continue.
|
||||
DebugOnly<nsresult> rv = ImportDefaultBookmarks();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "Should be able to import default bookmarks");
|
||||
|
||||
// Locate the Links toolbar folder, we want to replace the Personal Toolbar
|
||||
// content with Favorites in this folder.
|
||||
|
@ -65,6 +65,8 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#define SAFARI_PREFERENCES_FILE_NAME NS_LITERAL_STRING("com.apple.Safari.plist")
|
||||
@ -76,6 +78,8 @@
|
||||
#define SAFARI_HOME_PAGE_PREF "HomePage"
|
||||
#define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// nsSafariProfileMigrator
|
||||
|
||||
@ -977,10 +981,11 @@ nsSafariProfileMigrator::CopyBookmarksBatched(bool aReplace)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIFile> profile;
|
||||
GetProfilePath(nsnull, profile);
|
||||
rv = InitializeBookmarks(profile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// If importing defaults fails for whatever reason, let the import process
|
||||
// continue.
|
||||
DebugOnly<nsresult> rv = ImportDefaultBookmarks();
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv), "Should be able to import default bookmarks");
|
||||
|
||||
// In replace mode we are merging at the top level.
|
||||
folder = bookmarksMenuFolderId;
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
||||
<!-- This is an automatically generated file.
|
||||
It will be read and overwritten.
|
||||
DO NOT EDIT! -->
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
|
||||
<TITLE>Bookmarks</TITLE>
|
||||
<H1>Bookmarks Menu</H1>
|
||||
|
||||
<DL><p>
|
||||
<DT><A HREF="http://example.com/" ADD_DATE="1233157972" LAST_MODIFIED="1233157984">example</A>
|
||||
<DT><H3 ADD_DATE="1233157910" LAST_MODIFIED="1233157972" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar</H3>
|
||||
<DD>Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar
|
||||
<DL><p>
|
||||
<DT><A HREF="http://example.com/" ADD_DATE="1233157972" LAST_MODIFIED="1233157984">example</A>
|
||||
</DL><p>
|
||||
</DL><p>
|
@ -22,7 +22,3 @@ function newMigratorFor(aKey) {
|
||||
let cid = "@mozilla.org/profile/migrator;1?app=browser&type=" + aKey;
|
||||
return Cc[cid].createInstance(Ci.nsIBrowserProfileMigrator);
|
||||
}
|
||||
|
||||
let (bookmarkshtml = do_get_file("bookmarks.html")) {
|
||||
bookmarkshtml.copyTo(gProfD, "bookmarks.html");
|
||||
}
|
||||
|
@ -887,7 +887,7 @@ let AboutHomeUtils = {
|
||||
|
||||
loadSnippetsURL: function AHU_loadSnippetsURL()
|
||||
{
|
||||
const STARTPAGE_VERSION = 1;
|
||||
const STARTPAGE_VERSION = 2;
|
||||
let updateURL = Services.prefs
|
||||
.getCharPref(this.SNIPPETS_URL_PREF)
|
||||
.replace("%STARTPAGE_VERSION%", STARTPAGE_VERSION);
|
||||
|
@ -915,7 +915,7 @@ BrowserGlue.prototype = {
|
||||
Services.prefs.clearUserPref(PREF_TELEMETRY_PROMPTED);
|
||||
Services.prefs.clearUserPref(PREF_TELEMETRY_ENABLED);
|
||||
|
||||
var telemetryPrompt = browserBundle.formatStringFromName("telemetryPrompt", [productName, serverOwner], 2);
|
||||
var telemetryPrompt = browserBundle.formatStringFromName("telemetryOptInPrompt", [productName, serverOwner], 2);
|
||||
|
||||
var buttons = [
|
||||
{
|
||||
|
@ -231,73 +231,8 @@ var tests = [
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "HTML restore into folder: normal restore should succeed",
|
||||
currTopic: NSIOBSERVER_TOPIC_BEGIN,
|
||||
finalTopic: NSIOBSERVER_TOPIC_SUCCESS,
|
||||
data: NSIOBSERVER_DATA_HTML,
|
||||
run: function () {
|
||||
this.file = createFile("bookmarks-test_restoreNotification.html");
|
||||
addBookmarks();
|
||||
importer.exportHTMLToFile(this.file);
|
||||
remove_all_bookmarks();
|
||||
this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder,
|
||||
"test folder",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
print(" Sanity check: createFolder() should have succeeded");
|
||||
do_check_true(this.folderId > 0);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(this.file, this.folderId, false);
|
||||
}
|
||||
catch (e) {
|
||||
do_throw(" Restore should not have failed");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "HTML restore into folder: empty file should succeed",
|
||||
currTopic: NSIOBSERVER_TOPIC_BEGIN,
|
||||
finalTopic: NSIOBSERVER_TOPIC_SUCCESS,
|
||||
data: NSIOBSERVER_DATA_HTML,
|
||||
run: function () {
|
||||
this.file = createFile("bookmarks-test_restoreNotification.init.html");
|
||||
this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder,
|
||||
"test folder",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
print(" Sanity check: createFolder() should have succeeded");
|
||||
do_check_true(this.folderId > 0);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(this.file, this.folderId, false);
|
||||
}
|
||||
catch (e) {
|
||||
do_throw(" Restore should not have failed");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "HTML restore into folder: nonexistent file should fail",
|
||||
currTopic: NSIOBSERVER_TOPIC_BEGIN,
|
||||
finalTopic: NSIOBSERVER_TOPIC_FAILED,
|
||||
data: NSIOBSERVER_DATA_HTML,
|
||||
run: function () {
|
||||
this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
this.file.append("this file doesn't exist because nobody created it");
|
||||
this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder,
|
||||
"test folder",
|
||||
bmsvc.DEFAULT_INDEX);
|
||||
print(" Sanity check: createFolder() should have succeeded");
|
||||
do_check_true(this.folderId > 0);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(this.file, this.folderId, false);
|
||||
do_throw(" Restore should have failed");
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
// nsIObserver that observes bookmarks-restore-begin.
|
||||
|
@ -218,58 +218,6 @@ add_test(function test_emptytitle_export()
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_import_preplaces_to_folder()
|
||||
{
|
||||
// Test importing a pre-Places canonical bookmarks file to a specific folder.
|
||||
// 1. create a new folder
|
||||
// 2. import bookmarks.preplaces.html to that folder
|
||||
// 3. run the test-suite
|
||||
|
||||
let testFolder = PlacesUtils.bookmarks.createFolder(
|
||||
PlacesUtils.bookmarksMenuFolderId, "test-import",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX
|
||||
);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(gBookmarksFileOld, testFolder, false);
|
||||
} catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
|
||||
|
||||
waitForAsyncUpdates(function () {
|
||||
// Import-to-folder creates subfolders for toolbar and unfiled.
|
||||
testImportedBookmarksToFolder(testFolder);
|
||||
|
||||
waitForAsyncUpdates(function () {
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_import_to_folder()
|
||||
{
|
||||
// Test importing a Places canonical bookmarks file to a specific folder.
|
||||
// 1. create a new folder
|
||||
// 2. import bookmarks.exported.html to that folder
|
||||
// 3. run the test-suite
|
||||
|
||||
let testFolder = PlacesUtils.bookmarks.createFolder(
|
||||
PlacesUtils.bookmarksMenuFolderId, "test-import",
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX
|
||||
);
|
||||
try {
|
||||
importer.importHTMLFromFileToFolder(gBookmarksFileNew, testFolder, false);
|
||||
} catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
|
||||
|
||||
waitForAsyncUpdates(function () {
|
||||
// Import-to-folder creates subfolders for toolbar and unfiled.
|
||||
testImportedBookmarksToFolder(testFolder);
|
||||
|
||||
waitForAsyncUpdates(function () {
|
||||
remove_all_bookmarks();
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_import_ontop()
|
||||
{
|
||||
// Test importing the exported bookmarks.html file *on top of* the existing
|
||||
|
@ -2,6 +2,8 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let assertNumberOfTabs = function (num, msg) {
|
||||
is(gBrowser.tabs.length, num, msg);
|
||||
}
|
||||
@ -25,11 +27,13 @@ function test() {
|
||||
assertNumberOfPinnedTabs(2, "both tabs are now pinned");
|
||||
|
||||
// run the test
|
||||
ss.setBrowserState(JSON.stringify({ windows: [{ tabs: [{ url: "about:blank" }] }] }));
|
||||
assertNumberOfTabs(1, "one tab left after setBrowserState()");
|
||||
assertNumberOfPinnedTabs(0, "there are no pinned tabs");
|
||||
is(gBrowser.tabs[0].linkedBrowser, linkedBrowser, "first tab's browser got re-used");
|
||||
|
||||
waitForExplicitFinish();
|
||||
waitForSaveState(finish);
|
||||
waitForBrowserState(
|
||||
{ windows: [{ tabs: [{ url: "about:blank" }] }] },
|
||||
function () {
|
||||
assertNumberOfTabs(1, "one tab left after setBrowserState()");
|
||||
assertNumberOfPinnedTabs(0, "there are no pinned tabs");
|
||||
is(gBrowser.tabs[0].linkedBrowser, linkedBrowser, "first tab's browser got re-used");
|
||||
finish();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -14,10 +14,14 @@ function test() {
|
||||
// window is now in _closedWindows.
|
||||
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
// We speed up the interval between session saves to ensure that the test
|
||||
// runs quickly.
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 2000);
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 4000);
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
});
|
||||
|
||||
// We'll clear all closed windows to make sure our state is clean
|
||||
// forgetClosedWindow doesn't trigger a delayed save
|
||||
@ -97,7 +101,6 @@ function openTab() {
|
||||
}
|
||||
|
||||
function done() {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
gBrowser.removeTab(newTab);
|
||||
// The API still represents the closed window as closed, so we can clear it
|
||||
// with the API, but just to make sure...
|
||||
|
@ -7,9 +7,14 @@ let tabState = {
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 4000);
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
});
|
||||
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
registerCleanupFunction(function () gBrowser.removeTab(tab));
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
@ -26,7 +31,9 @@ function test() {
|
||||
is(entries.length, 1, "tab has one history entry");
|
||||
ok(!entries[0].children, "history entry has no subframes");
|
||||
|
||||
finish();
|
||||
// Make sure that we reset the state.
|
||||
let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
|
||||
waitForBrowserState(blankState, finish);
|
||||
});
|
||||
|
||||
// reload the browser to deprecate the subframes
|
||||
@ -36,8 +43,8 @@ function test() {
|
||||
// create a dynamic subframe
|
||||
let doc = browser.contentDocument;
|
||||
let iframe = doc.createElement("iframe");
|
||||
iframe.setAttribute("src", "about:mozilla");
|
||||
doc.body.appendChild(iframe);
|
||||
iframe.setAttribute("src", "about:mozilla");
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -53,5 +60,5 @@ function whenChildCount(aEntry, aChildCount, aCallback) {
|
||||
if (aEntry.childCount == aChildCount)
|
||||
aCallback();
|
||||
else
|
||||
executeSoon(function () whenChildCount(aEntry, aChildCount, aCallback));
|
||||
setTimeout(function () whenChildCount(aEntry, aChildCount, aCallback), 100);
|
||||
}
|
||||
|
@ -7,9 +7,14 @@ let tabState = {
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 4000);
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||
});
|
||||
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
registerCleanupFunction(function () gBrowser.removeTab(tab));
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
@ -25,7 +30,11 @@ function test() {
|
||||
let sessionHistory = browser.sessionHistory;
|
||||
let entry = sessionHistory.getEntryAtIndex(0, false);
|
||||
|
||||
whenChildCount(entry, 0, finish);
|
||||
whenChildCount(entry, 0, function () {
|
||||
// Make sure that we reset the state.
|
||||
let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
|
||||
waitForBrowserState(blankState, finish);
|
||||
});
|
||||
});
|
||||
|
||||
// reload the browser to deprecate the subframes
|
||||
@ -35,8 +44,8 @@ function test() {
|
||||
// create a dynamic subframe
|
||||
let doc = browser.contentDocument;
|
||||
let iframe = doc.createElement("iframe");
|
||||
iframe.setAttribute("src", "about:mozilla");
|
||||
doc.body.appendChild(iframe);
|
||||
iframe.setAttribute("src", "about:mozilla");
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -52,5 +61,5 @@ function whenChildCount(aEntry, aChildCount, aCallback) {
|
||||
if (aEntry.childCount == aChildCount)
|
||||
aCallback();
|
||||
else
|
||||
executeSoon(function () whenChildCount(aEntry, aChildCount, aCallback));
|
||||
setTimeout(function () whenChildCount(aEntry, aChildCount, aCallback), 100);
|
||||
}
|
||||
|
@ -94,11 +94,21 @@ let WindowMessageHandler = {
|
||||
!webProgress.isLoadingDocument);
|
||||
|
||||
sendAsyncMessage(cx.name, {isLoaded: isLoaded});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: isImageDocument
|
||||
// Checks if the currently active document is an image document or not.
|
||||
isImageDocument: function WMH_isImageDocument(cx) {
|
||||
let isImageDocument = (content.document instanceof Ci.nsIImageDocument);
|
||||
|
||||
sendAsyncMessage(cx.name, {isImageDocument: isImageDocument});
|
||||
}
|
||||
};
|
||||
|
||||
// add message listeners
|
||||
addMessageListener("Panorama:isDocumentLoaded", WindowMessageHandler.isDocumentLoaded);
|
||||
addMessageListener("Panorama:isImageDocument", WindowMessageHandler.isImageDocument);
|
||||
|
||||
// ----------
|
||||
// WebProgressListener
|
||||
|
@ -234,10 +234,12 @@ function GroupItem(listOfEls, options) {
|
||||
.addClass("appTabTray")
|
||||
.appendTo(appTabTrayContainer);
|
||||
|
||||
AllTabs.tabs.forEach(function(xulTab) {
|
||||
let pinnedTabCount = gBrowser._numPinnedTabs;
|
||||
AllTabs.tabs.forEach(function (xulTab, index) {
|
||||
// only adjust tray when it's the last app tab.
|
||||
if (xulTab.pinned)
|
||||
self.addAppTab(xulTab, {dontAdjustTray: true});
|
||||
});
|
||||
this.addAppTab(xulTab, {dontAdjustTray: index + 1 < pinnedTabCount});
|
||||
}, this);
|
||||
|
||||
// ___ Undo Close
|
||||
this.$undoContainer = null;
|
||||
@ -758,7 +760,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
});
|
||||
|
||||
UI.setActive(self);
|
||||
self._sendToSubscribers("groupShown", { groupItemId: self.id });
|
||||
self._sendToSubscribers("groupShown");
|
||||
};
|
||||
|
||||
let $container = iQ(this.container).show();
|
||||
@ -927,7 +929,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
easing: "tabviewBounce",
|
||||
duration: 170,
|
||||
complete: function() {
|
||||
self._sendToSubscribers("groupHidden", { groupItemId: self.id });
|
||||
self._sendToSubscribers("groupHidden");
|
||||
}
|
||||
});
|
||||
}, 50);
|
||||
@ -1052,7 +1054,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this.arrange({animate: !options.immediately});
|
||||
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
this._sendToSubscribers("childAdded",{ groupItemId: this.id, item: item });
|
||||
this._sendToSubscribers("childAdded", { item: item });
|
||||
|
||||
UI.setReorderTabsOnHide(this);
|
||||
} catch(e) {
|
||||
@ -1155,7 +1157,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
}
|
||||
|
||||
this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
|
||||
this._sendToSubscribers("childRemoved", { item: item });
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
@ -1181,36 +1183,46 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Adds the given xul:tab as an app tab in this group's apptab tray
|
||||
//
|
||||
// Parameters:
|
||||
// xulTab - the xul:tab.
|
||||
// options - change how the app tab is added.
|
||||
//
|
||||
// Options:
|
||||
// dontAdjustTray - (boolean) if true, the $appTabTray size is not adjusted,
|
||||
// which means that the adjustAppTabTray() method is not
|
||||
// called.
|
||||
// position - the position of the app tab should be added to.
|
||||
// dontAdjustTray - (boolean) if true, do not adjust the tray.
|
||||
addAppTab: function GroupItem_addAppTab(xulTab, options) {
|
||||
let self = this;
|
||||
GroupItems.getAppTabFavIconUrl(xulTab, function(iconUrl) {
|
||||
let self = this;
|
||||
let $appTab = iQ("<img>")
|
||||
.addClass("appTabIcon")
|
||||
.attr("src", iconUrl)
|
||||
.data("xulTab", xulTab)
|
||||
.mousedown(function GroupItem_addAppTab_onAppTabMousedown(event) {
|
||||
// stop mousedown propagation to disable group dragging on app tabs
|
||||
event.stopPropagation();
|
||||
})
|
||||
.click(function GroupItem_addAppTab_onAppTabClick(event) {
|
||||
if (!Utils.isLeftClick(event))
|
||||
return;
|
||||
|
||||
let iconUrl = GroupItems.getAppTabFavIconUrl(xulTab);
|
||||
let $appTab = iQ("<img>")
|
||||
.addClass("appTabIcon")
|
||||
.attr("src", iconUrl)
|
||||
.data("xulTab", xulTab)
|
||||
.appendTo(this.$appTabTray)
|
||||
.mousedown(function onAppTabMousedown(event) {
|
||||
// stop mousedown propagation to disable group dragging on app tabs
|
||||
event.stopPropagation();
|
||||
})
|
||||
.click(function(event) {
|
||||
if (!Utils.isLeftClick(event))
|
||||
return;
|
||||
UI.setActive(self, { dontSetActiveTabInGroup: true });
|
||||
UI.goToTab(iQ(this).data("xulTab"));
|
||||
});
|
||||
|
||||
UI.setActive(self, { dontSetActiveTabInGroup: true });
|
||||
UI.goToTab(iQ(this).data("xulTab"));
|
||||
});
|
||||
if (options && "position" in options) {
|
||||
let children = this.$appTabTray[0].childNodes;
|
||||
|
||||
// adjust the tray, if needed.
|
||||
if (!options || !options.dontAdjustTray)
|
||||
this.adjustAppTabTray(true);
|
||||
if (options.position >= children.length)
|
||||
$appTab.appendTo(this.$appTabTray);
|
||||
else
|
||||
this.$appTabTray[0].insertBefore($appTab[0], children[options.position]);
|
||||
} else {
|
||||
$appTab.appendTo(this.$appTabTray);
|
||||
}
|
||||
if (!options || !options.dontAdjustTray)
|
||||
this.adjustAppTabTray(true);
|
||||
|
||||
this._sendToSubscribers("appTabIconAdded", { item: $appTab });
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -2078,16 +2090,11 @@ let GroupItems = {
|
||||
if (!xulTab.pinned)
|
||||
return;
|
||||
|
||||
let iconUrl = this.getAppTabFavIconUrl(xulTab);
|
||||
this.groupItems.forEach(function(groupItem) {
|
||||
iQ(".appTabIcon", groupItem.$appTabTray).each(function(icon) {
|
||||
let $icon = iQ(icon);
|
||||
if ($icon.data("xulTab") != xulTab)
|
||||
return true;
|
||||
|
||||
if (iconUrl != $icon.attr("src"))
|
||||
$icon.attr("src", iconUrl);
|
||||
return false;
|
||||
this.getAppTabFavIconUrl(xulTab, function(iconUrl) {
|
||||
iQ(".appTabIcon").each(function GroupItems__updateAppTabIcons_forEach(icon) {
|
||||
let $icon = iQ(icon);
|
||||
if ($icon.data("xulTab") == xulTab && iconUrl != $icon.attr("src"))
|
||||
$icon.attr("src", iconUrl);
|
||||
});
|
||||
});
|
||||
},
|
||||
@ -2095,15 +2102,10 @@ let GroupItems = {
|
||||
// ----------
|
||||
// Function: getAppTabFavIconUrl
|
||||
// Gets the fav icon url for app tab.
|
||||
getAppTabFavIconUrl: function GroupItems_getAppTabFavIconUrl(xulTab) {
|
||||
let iconUrl;
|
||||
|
||||
if (UI.shouldLoadFavIcon(xulTab.linkedBrowser))
|
||||
iconUrl = UI.getFavIconUrlForTab(xulTab);
|
||||
else
|
||||
iconUrl = gFavIconService.defaultFavicon.spec;
|
||||
|
||||
return iconUrl;
|
||||
getAppTabFavIconUrl: function GroupItems_getAppTabFavIconUrl(xulTab, callback) {
|
||||
UI.getFavIconUrlForTab(xulTab, function GroupItems_getAppTabFavIconUrl_getFavIconUrlForTab(iconUrl) {
|
||||
callback(iconUrl || gFavIconService.defaultFavicon.spec);
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -985,20 +985,21 @@ let TabItems = {
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
|
||||
// Even if the page hasn't loaded, display the favicon and title
|
||||
|
||||
// ___ icon
|
||||
if (UI.shouldLoadFavIcon(tab.linkedBrowser)) {
|
||||
let iconUrl = UI.getFavIconUrlForTab(tab);
|
||||
|
||||
if (tabItem.$favImage[0].src != iconUrl)
|
||||
tabItem.$favImage[0].src = iconUrl;
|
||||
|
||||
iQ(tabItem.$fav[0]).show();
|
||||
} else {
|
||||
if (tabItem.$favImage[0].hasAttribute("src"))
|
||||
tabItem.$favImage[0].removeAttribute("src");
|
||||
iQ(tabItem.$fav[0]).hide();
|
||||
}
|
||||
UI.getFavIconUrlForTab(tab, function TabItems__update_getFavIconUrlCallback(iconUrl) {
|
||||
let favImage = tabItem.$favImage[0];
|
||||
let fav = tabItem.$fav;
|
||||
if (iconUrl) {
|
||||
if (favImage.src != iconUrl)
|
||||
favImage.src = iconUrl;
|
||||
fav.show();
|
||||
} else {
|
||||
if (favImage.hasAttribute("src"))
|
||||
favImage.removeAttribute("src");
|
||||
fav.hide();
|
||||
}
|
||||
tabItem._sendToSubscribers("iconUpdated");
|
||||
});
|
||||
|
||||
// ___ label
|
||||
let label = tab.label;
|
||||
|
@ -158,6 +158,7 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug673196.js \
|
||||
browser_tabview_bug673729.js \
|
||||
browser_tabview_bug677310.js \
|
||||
browser_tabview_bug678374.js \
|
||||
browser_tabview_bug679853.js \
|
||||
browser_tabview_bug681599.js \
|
||||
browser_tabview_bug685476.js \
|
||||
@ -192,6 +193,8 @@ _BROWSER_FILES = \
|
||||
search2.html \
|
||||
test_bug600645.html \
|
||||
test_bug644097.html \
|
||||
test_bug678374.html \
|
||||
test_bug678374_icon16.png \
|
||||
$(NULL)
|
||||
|
||||
# browser_tabview_bug597980.js is disabled for leaking, see bug 711907
|
||||
|
@ -4,15 +4,13 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
showTabView(onTabViewWindowLoaded);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
|
||||
// establish initial state
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
@ -36,60 +34,61 @@ function onTabViewWindowLoaded() {
|
||||
is(appTabCount(groupItemOne), 0, "there are no app tab icons");
|
||||
|
||||
// pin the tab, make sure the TabItem goes away and the icon comes on
|
||||
whenAppTabIconAdded(function() {
|
||||
is(groupItemOne._children.length, 0,
|
||||
"the app tab's TabItem was removed from the group");
|
||||
is(appTabCount(groupItemOne), 1, "there's now one app tab icon");
|
||||
|
||||
// create a second group and make sure it gets the icon too
|
||||
box.offset(box.width + 20, 0);
|
||||
let groupItemTwo = new contentWindow.GroupItem([],
|
||||
{ bounds: box, title: "test2" });
|
||||
whenAppTabIconAdded(function() {
|
||||
is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
|
||||
is(appTabCount(groupItemTwo), 1,
|
||||
"there's an app tab icon in the second group");
|
||||
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItemOne);
|
||||
|
||||
// unpin the tab, make sure the icon goes away and the TabItem comes on
|
||||
gBrowser.unpinTab(xulTab);
|
||||
is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
|
||||
is(appTabCount(groupItemOne), 0, "the icon is gone from group one");
|
||||
is(appTabCount(groupItemTwo), 0, "the icon is gone from group two");
|
||||
|
||||
whenAppTabIconAdded(function() {
|
||||
// close the second group
|
||||
groupItemTwo.close();
|
||||
|
||||
// find app tab in group and hit it
|
||||
whenTabViewIsHidden(function() {
|
||||
ok(!TabView.isVisible(),
|
||||
"Tab View is hidden because we clicked on the app tab");
|
||||
|
||||
// delete the app tab and make sure its icon goes away
|
||||
gBrowser.removeTab(xulTab);
|
||||
is(appTabCount(groupItemOne), 0, "closing app tab removes its icon");
|
||||
|
||||
// clean up
|
||||
groupItemOne.close();
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
ok(!TabView.isVisible(), "we finish with Tab View not visible");
|
||||
|
||||
finish();
|
||||
});
|
||||
|
||||
let appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
|
||||
EventUtils.sendMouseEvent({ type: "click" }, appTabIcons[0], contentWindow);
|
||||
});
|
||||
gBrowser.pinTab(xulTab);
|
||||
});
|
||||
});
|
||||
gBrowser.pinTab(xulTab);
|
||||
is(groupItemOne._children.length, 0,
|
||||
"the app tab's TabItem was removed from the group");
|
||||
is(appTabCount(groupItemOne), 1, "there's now one app tab icon");
|
||||
|
||||
// create a second group and make sure it gets the icon too
|
||||
box.offset(box.width + 20, 0);
|
||||
let groupItemTwo = new contentWindow.GroupItem([],
|
||||
{ bounds: box, title: "test2" });
|
||||
is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
|
||||
is(appTabCount(groupItemTwo), 1,
|
||||
"there's an app tab icon in the second group");
|
||||
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItemOne);
|
||||
|
||||
// unpin the tab, make sure the icon goes away and the TabItem comes on
|
||||
gBrowser.unpinTab(xulTab);
|
||||
is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
|
||||
is(appTabCount(groupItemOne), 0, "the icon is gone from group one");
|
||||
is(appTabCount(groupItemTwo), 0, "the icon is gone from group 2");
|
||||
|
||||
// pin the tab again
|
||||
gBrowser.pinTab(xulTab);
|
||||
|
||||
// close the second group
|
||||
groupItemTwo.close();
|
||||
|
||||
// find app tab in group and hit it
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
ok(!TabView.isVisible(),
|
||||
"Tab View is hidden because we clicked on the app tab");
|
||||
|
||||
// delete the app tab and make sure its icon goes away
|
||||
gBrowser.removeTab(xulTab);
|
||||
is(appTabCount(groupItemOne), 0, "closing app tab removes its icon");
|
||||
|
||||
// clean up
|
||||
groupItemOne.close();
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
ok(!TabView.isVisible(), "we finish with Tab View not visible");
|
||||
|
||||
finish();
|
||||
};
|
||||
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
let appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
|
||||
EventUtils.sendMouseEvent({ type: "click" }, appTabIcons[0], contentWindow);
|
||||
}
|
||||
|
||||
function appTabCount(groupItem) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
newWindowWithTabView(onTabViewWindowLoaded);
|
||||
}
|
||||
@ -105,8 +106,8 @@ function onTabViewWindowLoaded(win) {
|
||||
// Close the window and we're done!
|
||||
win.close();
|
||||
finish();
|
||||
}, 6000, false);
|
||||
},1000);
|
||||
}, 10000, false);
|
||||
}, 2000);
|
||||
|
||||
});
|
||||
|
||||
|
@ -53,87 +53,98 @@ function onTabViewShown(win) {
|
||||
"$appTabTray container is not visible");
|
||||
|
||||
// pin the tab, make sure the TabItem goes away and the icon comes on
|
||||
gBrowser.pinTab(xulTabs[0]);
|
||||
is(groupItem._children.length, 0,
|
||||
"the app tab's TabItem was removed from the group");
|
||||
is(appTabCount(groupItem), 1, "there's now one app tab icon");
|
||||
whenAppTabIconAdded(function() {
|
||||
is(groupItem._children.length, 0,
|
||||
"the app tab's TabItem was removed from the group");
|
||||
is(appTabCount(groupItem), 1, "there's now one app tab icon");
|
||||
|
||||
is(tray.css("-moz-column-count"), 1,
|
||||
"$appTabTray column count is 1");
|
||||
isnot(parseInt(trayContainer.css("width")), 0,
|
||||
"$appTabTray container is visible");
|
||||
is(tray.css("-moz-column-count"), 1,
|
||||
"$appTabTray column count is 1");
|
||||
isnot(parseInt(trayContainer.css("width")), 0,
|
||||
"$appTabTray container is visible");
|
||||
|
||||
let iconHeight = iQ(iQ(".appTabIcon", tray)[0]).height();
|
||||
let trayHeight = parseInt(trayContainer.css("height"));
|
||||
let rows = Math.floor(trayHeight / iconHeight);
|
||||
let icons = rows * 2;
|
||||
|
||||
// add enough tabs to have two columns
|
||||
for (let i = 1; i < icons; i++) {
|
||||
xulTabs.push(gBrowser.loadOneTab("about:blank"));
|
||||
gBrowser.pinTab(xulTabs[i]);
|
||||
}
|
||||
let iconHeight = iQ(iQ(".appTabIcon", tray)[0]).height();
|
||||
let trayHeight = parseInt(trayContainer.css("height"));
|
||||
let rows = Math.floor(trayHeight / iconHeight);
|
||||
let icons = rows * 2;
|
||||
|
||||
is(appTabCount(groupItem), icons, "number of app tab icons is correct");
|
||||
function pinnedSomeTabs() {
|
||||
is(appTabCount(groupItem), icons, "number of app tab icons is correct");
|
||||
|
||||
is(tray.css("-moz-column-count"), 2,
|
||||
"$appTabTray column count is 2");
|
||||
is(tray.css("-moz-column-count"), 2,
|
||||
"$appTabTray column count is 2");
|
||||
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
|
||||
// add one more tab
|
||||
xulTabs.push(gBrowser.loadOneTab("about:blank"));
|
||||
gBrowser.pinTab(xulTabs[xulTabs.length-1]);
|
||||
// add one more tab
|
||||
xulTabs.push(gBrowser.loadOneTab("about:blank"));
|
||||
whenAppTabIconAdded(function() {
|
||||
is(tray.css("-moz-column-count"), 3,
|
||||
"$appTabTray column count is 3");
|
||||
|
||||
is(tray.css("-moz-column-count"), 3,
|
||||
"$appTabTray column count is 3");
|
||||
ok(trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container hasClass .appTabTrayContainerTruncated");
|
||||
|
||||
ok(trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container hasClass .appTabTrayContainerTruncated");
|
||||
// remove all but one app tabs
|
||||
for (let i = 1; i < xulTabs.length; i++)
|
||||
gBrowser.removeTab(xulTabs[i]);
|
||||
|
||||
// remove all but one app tabs
|
||||
for (let i = 1; i < xulTabs.length; i++)
|
||||
gBrowser.removeTab(xulTabs[i]);
|
||||
is(tray.css("-moz-column-count"), 1,
|
||||
"$appTabTray column count is 1");
|
||||
|
||||
is(tray.css("-moz-column-count"), 1,
|
||||
"$appTabTray column count is 1");
|
||||
is(appTabCount(groupItem), 1, "there's now one app tab icon");
|
||||
|
||||
is(appTabCount(groupItem), 1, "there's now one app tab icon");
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
|
||||
ok(!trayContainer.hasClass("appTabTrayContainerTruncated"),
|
||||
"$appTabTray container does not have .appTabTrayContainerTruncated");
|
||||
// unpin the last remaining tab
|
||||
gBrowser.unpinTab(xulTabs[0]);
|
||||
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItem);
|
||||
is(parseInt(trayContainer.css("width")), 0,
|
||||
"$appTabTray container is not visible");
|
||||
|
||||
// unpin the last remaining tab
|
||||
gBrowser.unpinTab(xulTabs[0]);
|
||||
// When the tab was pinned, the last active group with an item got the focus.
|
||||
// Therefore, switching the focus back to group item one.
|
||||
contentWindow.UI.setActive(groupItem);
|
||||
|
||||
is(parseInt(trayContainer.css("width")), 0,
|
||||
"$appTabTray container is not visible");
|
||||
is(appTabCount(groupItem), 0, "there are no app tab icons");
|
||||
|
||||
is(appTabCount(groupItem), 0, "there are no app tab icons");
|
||||
is(groupItem._children.length, 1, "the normal tab shows in the group");
|
||||
|
||||
is(groupItem._children.length, 1, "the normal tab shows in the group");
|
||||
gBrowser.removeTab(xulTabs[0]);
|
||||
|
||||
gBrowser.removeTab(xulTabs[0]);
|
||||
// close the group
|
||||
groupItem.close();
|
||||
|
||||
// close the group
|
||||
groupItem.close();
|
||||
hideTabView(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
|
||||
hideTabView(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
win.close();
|
||||
|
||||
win.close();
|
||||
executeSoon(finish);
|
||||
}, win);
|
||||
}, win);
|
||||
win.gBrowser.pinTab(xulTabs[xulTabs.length-1]);
|
||||
};
|
||||
|
||||
executeSoon(finish);
|
||||
// add enough tabs to have two columns
|
||||
let returnCount = 0;
|
||||
for (let i = 1; i < icons; i++) {
|
||||
xulTabs.push(gBrowser.loadOneTab("about:blank"));
|
||||
whenAppTabIconAdded(function() {
|
||||
if (++returnCount == (icons - 1))
|
||||
executeSoon(pinnedSomeTabs);
|
||||
}, win);
|
||||
win.gBrowser.pinTab(xulTabs[i]);
|
||||
}
|
||||
}, win);
|
||||
win.gBrowser.pinTab(xulTabs[0]);
|
||||
}
|
||||
|
||||
function appTabCount(groupItem) {
|
||||
|
@ -10,15 +10,14 @@ function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newTab = gBrowser.addTab();
|
||||
gBrowser.pinTab(newTab);
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
showTabView(function() {
|
||||
whenAppTabIconAdded(onTabPinned);
|
||||
gBrowser.pinTab(newTab);
|
||||
})
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
|
||||
function onTabPinned() {
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"There is one group item on startup");
|
||||
|
@ -29,6 +29,7 @@ function onTabViewWindowLoaded(win) {
|
||||
let datatext = win.gBrowser.loadOneTab("data:text/plain,bug610242", bg);
|
||||
let datahtml = win.gBrowser.loadOneTab("data:text/html,<blink>don't blink!</blink>", bg);
|
||||
let mozilla = win.gBrowser.loadOneTab("about:mozilla", bg);
|
||||
let robots = win.gBrowser.loadOneTab("about:robots", bg);
|
||||
let html = win.gBrowser.loadOneTab("http://example.com", bg);
|
||||
let png = win.gBrowser.loadOneTab("http://mochi.test:8888/browser/browser/base/content/test/moz.png", bg);
|
||||
let svg = win.gBrowser.loadOneTab("http://mochi.test:8888/browser/browser/base/content/test/title_test.svg", bg);
|
||||
@ -46,13 +47,11 @@ function onTabViewWindowLoaded(win) {
|
||||
is(win.gBrowser.tabs.length, 1, "There is only one tab left");
|
||||
is(win.gBrowser.visibleTabs.length, 1, "There is also only one visible tab");
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
win.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
whenTabViewIsHidden(function() {
|
||||
win.close();
|
||||
ok(win.closed, "new window is closed");
|
||||
finish();
|
||||
};
|
||||
win.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
}, win);
|
||||
win.gBrowser.selectedTab = originalTab;
|
||||
|
||||
win.TabView.hide();
|
||||
@ -69,16 +68,33 @@ function onTabViewWindowLoaded(win) {
|
||||
|
||||
afterAllTabsLoaded(function() {
|
||||
afterAllTabItemsUpdated(function() {
|
||||
check(datatext, "datatext", false);
|
||||
check(datahtml, "datahtml", false);
|
||||
check(mozilla, "about:mozilla", true);
|
||||
check(html, "html", true);
|
||||
check(png, "png", false);
|
||||
check(svg, "svg", true);
|
||||
|
||||
// Get rid of the group and its children
|
||||
// The group close will trigger a finish().
|
||||
closeGroupItem(group);
|
||||
}, win);
|
||||
let children = group.getChildren();
|
||||
let len = children.length;
|
||||
let iconUpdateCounter = 0;
|
||||
|
||||
children.forEach(function(tabItem) {
|
||||
tabItem.addSubscriber("iconUpdated", function onIconUpdated() {
|
||||
// the tab is not loaded completely so ignore it.
|
||||
if (tabItem.tab.linkedBrowser.currentURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
tabItem.removeSubscriber("iconUpdated", onIconUpdated);
|
||||
|
||||
if (++iconUpdateCounter == len) {
|
||||
check(datatext, "datatext", false);
|
||||
check(datahtml, "datahtml", false);
|
||||
check(mozilla, "about:mozilla", false);
|
||||
check(robots, "about:robots", true);
|
||||
check(html, "html", true);
|
||||
check(png, "png", false);
|
||||
check(svg, "svg", true);
|
||||
|
||||
// Get rid of the group and its children
|
||||
// The group close will trigger a finish().
|
||||
closeGroupItem(group);
|
||||
}
|
||||
});
|
||||
});
|
||||
}, win);
|
||||
}, win);
|
||||
}
|
||||
|
@ -172,6 +172,7 @@ function test() {
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(2);
|
||||
|
||||
next();
|
||||
}
|
||||
|
@ -11,10 +11,6 @@ function test() {
|
||||
let newTabTwo = gBrowser.addTab();
|
||||
let newTabThree = gBrowser.addTab();
|
||||
|
||||
gBrowser.pinTab(newTabOne);
|
||||
gBrowser.pinTab(newTabTwo);
|
||||
gBrowser.pinTab(newTabThree);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
TabView.hide();
|
||||
while (gBrowser.tabs.length > 1)
|
||||
@ -27,37 +23,47 @@ function test() {
|
||||
|
||||
groupItem = contentWindow.GroupItems.groupItems[0];
|
||||
|
||||
is(xulTabForAppTabIcon(0), newTabOne,
|
||||
"New tab one matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabTwo,
|
||||
"New tab two matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabThree,
|
||||
"New tab three matches the third app tab icon in tabview");
|
||||
whenAppTabIconAdded(function() {
|
||||
whenAppTabIconAdded(function() {
|
||||
whenAppTabIconAdded(function() {
|
||||
|
||||
// move the last tab to the first position
|
||||
gBrowser.moveTabTo(newTabThree, 0);
|
||||
is(xulTabForAppTabIcon(0), newTabThree,
|
||||
"New tab three matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabOne,
|
||||
"New tab one matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabTwo,
|
||||
"New tab two matches the third app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(0), newTabOne,
|
||||
"New tab one matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabTwo,
|
||||
"New tab two matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabThree,
|
||||
"New tab three matches the third app tab icon in tabview");
|
||||
|
||||
// move the first tab to the second position
|
||||
gBrowser.moveTabTo(newTabThree, 1);
|
||||
is(xulTabForAppTabIcon(0), newTabOne,
|
||||
"New tab one matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabThree,
|
||||
"New tab three matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabTwo,
|
||||
"New tab two matches the third app tab icon in tabview");
|
||||
// move the last tab to the first position
|
||||
gBrowser.moveTabTo(newTabThree, 0);
|
||||
is(xulTabForAppTabIcon(0), newTabThree,
|
||||
"New tab three matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabOne,
|
||||
"New tab one matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabTwo,
|
||||
"New tab two matches the third app tab icon in tabview");
|
||||
|
||||
hideTabView(function() {
|
||||
gBrowser.removeTab(newTabOne);
|
||||
gBrowser.removeTab(newTabTwo);
|
||||
gBrowser.removeTab(newTabThree);
|
||||
finish();
|
||||
// move the first tab to the second position
|
||||
gBrowser.moveTabTo(newTabThree, 1);
|
||||
is(xulTabForAppTabIcon(0), newTabOne,
|
||||
"New tab one matches the first app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(1), newTabThree,
|
||||
"New tab three matches the second app tab icon in tabview");
|
||||
is(xulTabForAppTabIcon(2), newTabTwo,
|
||||
"New tab two matches the third app tab icon in tabview");
|
||||
|
||||
hideTabView(function() {
|
||||
gBrowser.removeTab(newTabOne);
|
||||
gBrowser.removeTab(newTabTwo);
|
||||
gBrowser.removeTab(newTabThree);
|
||||
finish();
|
||||
});
|
||||
});
|
||||
gBrowser.pinTab(newTabThree);
|
||||
});
|
||||
gBrowser.pinTab(newTabTwo);
|
||||
});
|
||||
gBrowser.pinTab(newTabOne);
|
||||
});
|
||||
}
|
||||
|
||||
|
45
browser/components/tabview/test/browser_tabview_bug678374.js
Normal file
@ -0,0 +1,45 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const ICON_URL = "moz-anno:favicon:http://example.com/browser/browser/components/tabview/test/test_bug678374_icon16.png";
|
||||
const TEST_URL = "http://example.com/browser/browser/components/tabview/test/test_bug678374.html";
|
||||
|
||||
function test() {
|
||||
Services.prefs.setBoolPref("browser.chrome.favicons", false);
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(function(win) {
|
||||
is(win.gBrowser.tabs.length, 3, "There are 3 tabs")
|
||||
|
||||
let newTabOne = win.gBrowser.tabs[1];
|
||||
let newTabTwo = win.gBrowser.tabs[2];
|
||||
let cw = win.TabView.getContentWindow();
|
||||
let groupItem = cw.GroupItems.groupItems[0];
|
||||
|
||||
// test tab item
|
||||
let newTabItemOne = newTabOne._tabViewTabItem;
|
||||
|
||||
newTabItemOne.addSubscriber("iconUpdated", function onIconUpdated() {
|
||||
newTabItemOne.removeSubscriber("iconUpdated", onIconUpdated);
|
||||
is(newTabItemOne.$favImage[0].src, ICON_URL, "The tab item is showing the right icon.");
|
||||
|
||||
// test pin tab
|
||||
whenAppTabIconAdded(function() {
|
||||
let icon = cw.iQ(".appTabIcon", groupItem.$appTabTray)[0];
|
||||
is(icon.src, ICON_URL, "The app tab is showing the right icon");
|
||||
|
||||
finish();
|
||||
}, win);
|
||||
win.gBrowser.pinTab(newTabTwo);
|
||||
});
|
||||
}, function(win) {
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("browser.chrome.favicons");
|
||||
win.close();
|
||||
});
|
||||
|
||||
win.gBrowser.loadOneTab(TEST_URL);
|
||||
win.gBrowser.loadOneTab(TEST_URL);
|
||||
});
|
||||
}
|
@ -6,19 +6,21 @@ function test() {
|
||||
|
||||
showTabView(function () {
|
||||
let tab = gBrowser.addTab();
|
||||
gBrowser.pinTab(tab);
|
||||
registerCleanupFunction(function () gBrowser.removeTab(tab));
|
||||
|
||||
let cw = TabView.getContentWindow();
|
||||
let body = cw.document.body;
|
||||
let [appTabIcon] = cw.iQ(".appTabTray .appTabIcon");
|
||||
whenAppTabIconAdded(function() {
|
||||
let cw = TabView.getContentWindow();
|
||||
let body = cw.document.body;
|
||||
let [appTabIcon] = cw.iQ(".appTabTray .appTabIcon");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(appTabIcon, {type: "mousedown"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mousemove"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mouseup"}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(appTabIcon, {type: "mousedown"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mousemove"}, cw);
|
||||
EventUtils.synthesizeMouse(body, 500, 100, {type: "mouseup"}, cw);
|
||||
|
||||
ok(TabView.isVisible(), "tabview is still visible");
|
||||
ok(TabView.isVisible(), "tabview is still visible");
|
||||
|
||||
hideTabView(finish);
|
||||
hideTabView(finish);
|
||||
});
|
||||
gBrowser.pinTab(tab);
|
||||
});
|
||||
}
|
||||
|