This commit is contained in:
Gregory Szorc 2012-03-16 17:25:41 -07:00
Родитель dd67cb8f33 3159e835b7
Коммит f523c1bae6
805 изменённых файлов: 19021 добавлений и 22413 удалений

Просмотреть файл

@ -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)

Просмотреть файл

@ -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 \

Просмотреть файл

@ -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);

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.3 KiB

Двоичные данные
browser/base/content/aboutHome-restore-icon.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 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;
}
}

Просмотреть файл

@ -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>

Двоичные данные
browser/base/content/abouthome/addons.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
browser/base/content/abouthome/bookmarks.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
browser/base/content/abouthome/downloads.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 898 B

Двоичные данные
browser/base/content/abouthome/history.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Двоичные данные
browser/base/content/abouthome/mozilla.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.6 KiB

Двоичные данные
browser/base/content/abouthome/noise.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 11 KiB

Двоичные данные
browser/base/content/abouthome/restore-large.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.8 KiB

Двоичные данные
browser/base/content/abouthome/restore.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичные данные
browser/base/content/abouthome/settings.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 3.2 KiB

После

Ширина:  |  Высота:  |  Размер: 3.2 KiB

Двоичные данные
browser/base/content/abouthome/sync.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 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);
});
}

Просмотреть файл

@ -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);
});
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше